mcpField
S
salla-app-functions-validate

salla-app-functions-validate

github.com/sallaappTesting & quality278 installsUpdated 3w ago
Repository

About salla-app-functions-validate

A validation skill for Salla App Functions that defines a repeatable check-and-fix loop before and after saving. It is for developers who need to verify the trigger wrapper, TypeScript types, API schemas, and demo-store behavior before release.

Key features

  1. 01Match the trigger template wrapper
  2. 02Type-check against trigger declarations
  3. 03Validate Admin API calls against OpenAPI
  4. 04Run the saved function in demo preview
  5. 05Repeat save and checks after fixes

Use cases

  1. 01Catch handler type errors before release
  2. 02Verify request and response shapes for API calls
  3. 03Check function behavior with demo-store data
  4. 04Revalidate a function after changing its code

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/sallaapp/salla-partners-agent-kit --skill salla-app-functions-validate

After installing, type/salla-app-functions-validatein Claude Code to confirm it loaded.

Details

From the project README

App Functions — Validate Before Save

A successful save is the START of validation, not the end. salla_functions action=save returns 200 once the wrapper's first and last line match — it does not type-check or run your body, so a 200 ≠ a correct function. Treat every salla_functions action=save as the trigger for one closed loop: validate → fix → re-save → re-validate until clean. A handler that type-fails or breaks at runtime surfaces after save, once it deploys to the demo stores.

The loop (each step below): (1) wrapper first/last line matches the template → (2) the TypeScript compiler against the trigger's .d.ts at the editor's bar (non-strict, ignore unused TS6133) → (3) each outbound Admin API call's request/response validates against its documented OpenAPI → (4) salla_functions action=preview runs clean on a demo store (→ salla-app-functions-test) → fix any failure, re-save, and run the loop again. Steps 1–2 are the only pre-save safety net; run them before each save.

Keep credentials in App Settings (read via context.settings), not in the saved source — App Functions commonly call external services, but secrets, tokens, and API keys belong in settings. Token/OAuth handling → salla-app-auth; webhook signature + idempotency → salla-webhooks.

1. Match the template wrapper exactly (STRICT)

The wrapper — its first line (the function signature) and last line (the closing of the function definition) — is fixed by the trigger. Copy the wrapper from salla_functions action=get (its template) and edit only the body: keep the context parameter name, its type, the return type, and the closing line exactly as given. Put ALL code INSIDE the body — every const / let / function / import / class stays between the first and last line (a hoisted constant or helper is the most common cause of breakage).

save fetches the template and rejects content whose first or last wrapper line differs, returning the expected lines. content is the whole function (the full wrapper as a string), not just the body. The body itself is unchecked at save — that's what the local tsc check in step 2 covers.

2. Type-check with the trigger's types (mirror the editor)

The Portal editor validates with Monaco's TypeScript worker (the typescript compiler): it loads the trigger's .d.ts (the config.types) via addExtraLib, uses non-strict default compiler options, and ignores TS6133 (declared-but-unused). Match that bar so you're not stricter than what actually blocks save — validate with the same compiler, same types, same leniency.

types (from action=get) is a list of .d.ts URLs — the exact libs the editor loads. Download each one next to your handler — fetch only the URLs action=get returns for this trigger (not arbitrary or user-supplied URLs), and use the real .d.ts rather than hand-written mocks:

curl -sSL "https://…/shipments.d.ts" -o salla-globals.d.ts   # one per types URL

Put your full wrapper in handler.ts, then type-check both at the editor's bar — non-strict (Monaco defaults), no emit — and fix every error except TS6133 (unused), which the editor ignores:

# Editor's bar: non-strict, ignores unused (TS6133)
npx -y -p typescript tsc --noEmit --skipLibCheck salla-globals.d.ts handler.ts

Optional stricter superset: --strict catches more, but the editor's bar is non-strict and ignores unused (TS6133). Clear --strict before save only if you choose to hold a higher standard than the editor; it is not what blocks save.

npx -y -p typescript tsc --noEmit --strict --skipLibCheck salla-globals.d.ts handler.ts  # optional, stricter than the editor

If a types URL is unreachable, retry or re-fetch it from action=get. A hand-written mock is a last resort, shaped for one trigger only — the example below is shipment-shaped, so rename the context type and adjust payload to match your trigger, and confirm the real shape against that trigger's types first:

// ILLUSTRATIVE fallback — verify the exact shape from the trigger's `types` (action=get).
declare class Resp {
  static success(): Resp;
  static error(): Resp;
  setStatus(status: number): Resp;
  setMessage(message: string): Resp;
  setData(data: Record<string, unknown>): Resp;
}
declare type Shipments = {
  merchant?: { id?: string | number };
  payload?: {
    event?: string;
    created_at?: string;
    data?: Record<string, unknown>;
  };
  settings?: Record<string, unknown>;
};

Gate: "First and last wrapper lines match the template, all code inside the wrapper, and tsc --noEmit against the trigger's types compiles clean at the editor's bar (non-strict, TS6133 ignored)?" → step 3.

3. Validate outbound Admin API calls against the documented schema

Steps 1–2 cover the handler's shape; this closes the loop on the Admin API calls the handler makes. When the function calls a documented endpoint, validate the request body/params and the parsed response against that endpoint's OpenAPI schema — Salla's doc page (docs.salla.dev/<id>.md) embeds a full OpenAPI 3.x block (paths, components schemas, types, enums, required).

Run the canonical read the doc's OpenAPI → build to match → validate → fix → retry loop from salla-api-core for each call: find the endpoint's doc id (→ salla-docs), check the request and parsed response against its schema's required/types/enums, fix any mismatch, and re-run until clean. Don't restate the loop here — salla-api-core owns it.

Gate: "Each documented Admin API call's request and parsed response validate clean against its endpoint's OpenAPI schema?" → step 4.

4. Run the saved function on a demo store

A clean tsc and schema check still don't prove the function behaves correctly with real data — save, then run salla_functions action=preview on a demo store to exercise the handler end to end (→ salla-app-functions-test). If preview fails or returns the wrong result, fix the body, re-save, and re-run steps 1–4 until preview is clean.

Gate: "Wrapper + tsc + every Admin API call's schema pass, and action=preview runs clean on a demo store?" → salla-app-functions-release.

Comments

Markdown supported