@nzila/sdk 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +27 -1
  2. package/dist/cli/constants.d.ts +13 -0
  3. package/dist/cli/constants.d.ts.map +1 -0
  4. package/dist/cli/constants.js +20 -0
  5. package/dist/cli/main.d.ts +3 -0
  6. package/dist/cli/main.d.ts.map +1 -0
  7. package/dist/cli/main.js +223 -0
  8. package/dist/cli/open-browser.d.ts +2 -0
  9. package/dist/cli/open-browser.d.ts.map +1 -0
  10. package/dist/cli/open-browser.js +26 -0
  11. package/examples/COMPLEX-USAGE.md +113 -0
  12. package/examples/INDEX.md +27 -0
  13. package/examples/README.md +94 -0
  14. package/examples/RUNTIME-TRACE.md +222 -0
  15. package/examples/TRACING-FAILURES.md +186 -0
  16. package/examples/backend/error-tracing.test.ts +44 -0
  17. package/examples/backend/order-pricing.test.ts +54 -0
  18. package/examples/backend/order-pricing.ts +27 -0
  19. package/examples/backend/runtime-trace.example.ts +31 -0
  20. package/examples/backend/sample-payload.json +62 -0
  21. package/examples/backend/sample-tracing-payload.json +90 -0
  22. package/examples/complex/api-services.demo.ts +72 -0
  23. package/examples/complex/full-platform.demo.test.ts +46 -0
  24. package/examples/frontend/checkout-form.test.ts +54 -0
  25. package/examples/frontend/checkout-form.ts +29 -0
  26. package/examples/frontend/error-tracing.test.ts +59 -0
  27. package/examples/frontend/sample-payload.json +62 -0
  28. package/examples/frontend/sample-tracing-payload.json +73 -0
  29. package/examples/frontend-webhook-client.ts +32 -0
  30. package/examples/jest.config.example.cjs +18 -0
  31. package/examples/mocharc.nzila.example.cjs +21 -0
  32. package/examples/react/checkout-feature.example.tsx +41 -0
  33. package/examples/send-run-manual.mjs +16 -0
  34. package/examples/shared/feature-map.ts +24 -0
  35. package/examples/shared/load-env.mjs +24 -0
  36. package/examples/shared/send-webhook.mjs +43 -0
  37. package/examples/vitest.config.example.ts +20 -0
  38. package/package.json +9 -4
package/README.md CHANGED
@@ -11,6 +11,21 @@ npm install @nzila/sdk
11
11
  # Vitest projects also need vitest as a peer
12
12
  ```
13
13
 
14
+ ## CLI (onboarding)
15
+
16
+ `npx @nzila/sdk` opens the [Nzila dashboard](https://nzila-kappa.vercel.app) and prints setup commands. No separate CLI package.
17
+
18
+ ```bash
19
+ npx @nzila/sdk # open app + help
20
+ npx @nzila/sdk login
21
+ npx @nzila/sdk link --api-key <key> --project-id <uuid>
22
+ npx @nzila/sdk doctor
23
+ ```
24
+
25
+ Also available as `npx nzila` after install. Override platform with `NZILA_APP_URL` or `--endpoint`.
26
+
27
+ After you sign in on [nzila-kappa.vercel.app](https://nzila-kappa.vercel.app), the dashboard runs a **first-visit tour** per section (localized). Use **Guide** in the header to replay.
28
+
14
29
  ## Exports
15
30
 
16
31
  | Path | Purpose |
@@ -67,4 +82,15 @@ const nzila = traceNzilaFeature("Checkout");
67
82
  await nzila.runApi("charge", () => charge());
68
83
  ```
69
84
 
70
- See JSDoc on each export in `src/` and the monorepo guide [examples/COMPLEX-USAGE.md](../../examples/COMPLEX-USAGE.md).
85
+ ## Examples (included in this package)
86
+
87
+ After install, open **`node_modules/@nzila/sdk/examples/`**:
88
+
89
+ - **[INDEX.md](./examples/INDEX.md)** — map of all samples
90
+ - **[COMPLEX-USAGE.md](./examples/COMPLEX-USAGE.md)** — every feature (Vitest, runtime, `mapFeature`, webhooks)
91
+ - **[RUNTIME-TRACE.md](./examples/RUNTIME-TRACE.md)** — React + backend live tracing
92
+ - **[TRACING-FAILURES.md](./examples/TRACING-FAILURES.md)** — tests → dashboard
93
+ - Config: `vitest.config.example.ts`, `jest.config.example.cjs`, `mocharc.nzila.example.cjs`
94
+ - Code: `backend/`, `frontend/`, `complex/`, `react/checkout-feature.example.tsx`
95
+
96
+ All example imports use `@nzila/sdk` (same as your app).
@@ -0,0 +1,13 @@
1
+ /** Hosted Nzila dashboard — override with NZILA_APP_URL or --endpoint */
2
+ export declare const NZILA_PLATFORM_URL = "https://nzila-kappa.vercel.app";
3
+ export declare function resolvePlatformUrl(): string;
4
+ export declare function platformPaths(base: string): {
5
+ home: string;
6
+ login: string;
7
+ register: string;
8
+ docs: string;
9
+ keys: string;
10
+ webhook: string;
11
+ signals: string;
12
+ };
13
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/cli/constants.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,eAAO,MAAM,kBAAkB,mCAAmC,CAAC;AAEnE,wBAAgB,kBAAkB,IAAI,MAAM,CAM3C;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM;;;;;;;;EAWzC"}
@@ -0,0 +1,20 @@
1
+ /** Hosted Nzila dashboard — override with NZILA_APP_URL or --endpoint */
2
+ export const NZILA_PLATFORM_URL = "https://nzila-kappa.vercel.app";
3
+ export function resolvePlatformUrl() {
4
+ const raw = process.env.NZILA_APP_URL?.trim() ||
5
+ process.env.NZILA_ENDPOINT?.trim() ||
6
+ NZILA_PLATFORM_URL;
7
+ return raw.replace(/\/$/, "");
8
+ }
9
+ export function platformPaths(base) {
10
+ const root = base.replace(/\/$/, "");
11
+ return {
12
+ home: `${root}/en`,
13
+ login: `${root}/en/login`,
14
+ register: `${root}/en/register`,
15
+ docs: `${root}/en/docs`,
16
+ keys: `${root}/en/keys`,
17
+ webhook: `${root}/api/webhooks/tests`,
18
+ signals: `${root}/api/signals/runtime`,
19
+ };
20
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":""}
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+ import { readFile, writeFile } from "node:fs/promises";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import path from "node:path";
5
+ import { platformPaths, resolvePlatformUrl } from "./constants.js";
6
+ import { openBrowser } from "./open-browser.js";
7
+ const PKG = "@nzila/sdk";
8
+ const CONFIG_FILE = "nzila.config.ts";
9
+ function defaultEndpoint() {
10
+ return resolvePlatformUrl();
11
+ }
12
+ async function loadConfig(cwd) {
13
+ const file = path.join(cwd, CONFIG_FILE);
14
+ if (!existsSync(file))
15
+ return null;
16
+ const source = await readFile(file, "utf8");
17
+ const match = source.match(/apiKey:\s*["']([^"']+)["']/);
18
+ const projectMatch = source.match(/projectId:\s*["']([^"']+)["']/);
19
+ const endpointMatch = source.match(/endpoint:\s*["']([^"']+)["']/);
20
+ const frameworkMatch = source.match(/framework:\s*["']([^"']+)["']/);
21
+ if (!match?.[1] || !projectMatch?.[1])
22
+ return null;
23
+ return {
24
+ apiKey: match[1],
25
+ projectId: projectMatch[1],
26
+ endpoint: endpointMatch?.[1] ?? defaultEndpoint(),
27
+ framework: frameworkMatch?.[1] ?? "vitest",
28
+ };
29
+ }
30
+ async function writeConfig(cwd, config) {
31
+ const body = `/** Generated by ${PKG} — do not commit secrets to public repos */
32
+ export default {
33
+ apiKey: "${config.apiKey}",
34
+ projectId: "${config.projectId}",
35
+ endpoint: "${config.endpoint.replace(/"/g, '\\"')}",
36
+ framework: "${config.framework}",
37
+ } as const;
38
+ `;
39
+ await writeFile(path.join(cwd, CONFIG_FILE), body, "utf8");
40
+ }
41
+ function detectFramework(cwd) {
42
+ const pkgPath = path.join(cwd, "package.json");
43
+ if (existsSync(pkgPath)) {
44
+ try {
45
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
46
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
47
+ if (deps["@playwright/test"] || deps.playwright)
48
+ return "playwright";
49
+ if (deps.jest)
50
+ return "jest";
51
+ if (deps.vitest)
52
+ return "vitest";
53
+ }
54
+ catch {
55
+ /* fall through */
56
+ }
57
+ }
58
+ if (existsSync(path.join(cwd, "vitest.config.ts")) || existsSync(path.join(cwd, "vitest.config.mts"))) {
59
+ return "vitest";
60
+ }
61
+ if (existsSync(path.join(cwd, "jest.config.js")) || existsSync(path.join(cwd, "jest.config.ts"))) {
62
+ return "jest";
63
+ }
64
+ if (existsSync(path.join(cwd, "playwright.config.ts")))
65
+ return "playwright";
66
+ return "vitest";
67
+ }
68
+ function printEnvSnippet(endpoint) {
69
+ const paths = platformPaths(endpoint);
70
+ console.log("");
71
+ console.log("Add to your project .env.local:");
72
+ console.log(`NZILA_WEBHOOK_URL=${paths.webhook}`);
73
+ console.log(`NZILA_SIGNALS_URL=${paths.signals}`);
74
+ console.log("NZILA_API_KEY=<from dashboard → API Keys>");
75
+ console.log("");
76
+ console.log(`SDK already installed via ${PKG}; add Vitest reporter from docs.`);
77
+ console.log(`Docs: ${paths.docs}`);
78
+ }
79
+ async function tryOpen(url, quiet = false) {
80
+ try {
81
+ await openBrowser(url);
82
+ if (!quiet)
83
+ console.log(`Opened ${url}`);
84
+ }
85
+ catch {
86
+ if (!quiet)
87
+ console.log(`Open in your browser: ${url}`);
88
+ }
89
+ }
90
+ async function cmdOpen(flags) {
91
+ const base = String(flags.endpoint ?? defaultEndpoint()).replace(/\/$/, "");
92
+ const paths = platformPaths(base);
93
+ const target = flags.register ? paths.register : flags.login ? paths.login : paths.home;
94
+ await tryOpen(target);
95
+ }
96
+ async function cmdInit(flags) {
97
+ const cwd = process.cwd();
98
+ const framework = detectFramework(cwd);
99
+ const base = defaultEndpoint();
100
+ const paths = platformPaths(base);
101
+ console.log(`Nzila — platform: ${base}`);
102
+ console.log(`Detected test framework: ${framework}`);
103
+ console.log("");
104
+ console.log("Quick start:");
105
+ console.log(` 1. npx ${PKG} login → sign in (opens browser)`);
106
+ console.log(" 2. Create a project + API key in the dashboard");
107
+ console.log(` 3. npx ${PKG} link --api-key nzl_… --project-id <uuid>`);
108
+ console.log(" 4. Wire @nzila/sdk/vitest and run tests");
109
+ printEnvSnippet(base);
110
+ if (flags.open !== false) {
111
+ await tryOpen(paths.register, true);
112
+ }
113
+ }
114
+ async function cmdLogin(flags) {
115
+ const base = String(flags.endpoint ?? defaultEndpoint()).replace(/\/$/, "");
116
+ const loginUrl = `${platformPaths(base).login}?cli=1`;
117
+ console.log(`Nzila platform: ${base}`);
118
+ console.log("Sign in, then create an API key:");
119
+ console.log(` ${platformPaths(base).keys}`);
120
+ console.log("");
121
+ console.log("Then link this repo:");
122
+ console.log(` npx ${PKG} link --api-key <key> --project-id <uuid>`);
123
+ await tryOpen(loginUrl);
124
+ }
125
+ async function cmdLink(flags) {
126
+ const apiKey = String(flags["api-key"] ?? flags.apiKey ?? "");
127
+ const projectId = String(flags["project-id"] ?? flags.projectId ?? "");
128
+ const endpoint = String(flags.endpoint ?? defaultEndpoint()).replace(/\/$/, "");
129
+ if (!apiKey || !projectId) {
130
+ console.error(`Usage: npx ${PKG} link --api-key <token> --project-id <uuid> [--endpoint <url>]`);
131
+ process.exit(1);
132
+ }
133
+ const cwd = process.cwd();
134
+ const framework = detectFramework(cwd);
135
+ await writeConfig(cwd, { apiKey, projectId, endpoint, framework });
136
+ console.log(`Wrote ${CONFIG_FILE} (endpoint: ${endpoint})`);
137
+ printEnvSnippet(endpoint);
138
+ }
139
+ async function cmdDoctor() {
140
+ const cwd = process.cwd();
141
+ const config = await loadConfig(cwd);
142
+ if (!config) {
143
+ console.log(`No nzila.config.ts — run \`npx ${PKG} link\` first.`);
144
+ process.exit(1);
145
+ }
146
+ const paths = platformPaths(config.endpoint);
147
+ console.log("Config OK:", {
148
+ projectId: config.projectId,
149
+ endpoint: config.endpoint,
150
+ framework: config.framework,
151
+ });
152
+ console.log("Webhook URL:", paths.webhook);
153
+ }
154
+ function printHelp(base) {
155
+ const paths = platformPaths(base);
156
+ console.log(`Nzila (${PKG}) — ${base}
157
+
158
+ Commands:
159
+ open Open the dashboard in your browser (default)
160
+ init Detect framework + show setup steps
161
+ login Open sign-in and linking instructions
162
+ link Write nzila.config.ts (--api-key, --project-id)
163
+ doctor Validate nzila.config.ts
164
+
165
+ Examples:
166
+ npx ${PKG}
167
+ npx ${PKG} login
168
+ npx ${PKG} link --api-key nzl_… --project-id <uuid>
169
+
170
+ Docs: ${paths.docs}
171
+ `);
172
+ }
173
+ function parseArgs(argv) {
174
+ const [command, ...rest] = argv;
175
+ const flags = {};
176
+ for (let i = 0; i < rest.length; i++) {
177
+ const token = rest[i];
178
+ if (token.startsWith("--")) {
179
+ const key = token.slice(2);
180
+ const next = rest[i + 1];
181
+ if (next && !next.startsWith("--")) {
182
+ flags[key] = next;
183
+ i++;
184
+ }
185
+ else {
186
+ flags[key] = true;
187
+ }
188
+ }
189
+ }
190
+ return { command: command ?? "", flags };
191
+ }
192
+ async function main() {
193
+ const { command, flags } = parseArgs(process.argv.slice(2));
194
+ const base = defaultEndpoint();
195
+ if (!command || command === "open" || command === "start") {
196
+ if (!command)
197
+ await tryOpen(platformPaths(base).home);
198
+ else
199
+ await cmdOpen(flags);
200
+ if (!command)
201
+ printHelp(base);
202
+ return;
203
+ }
204
+ if (command === "init")
205
+ return cmdInit(flags);
206
+ if (command === "login")
207
+ return cmdLogin(flags);
208
+ if (command === "link")
209
+ return cmdLink(flags);
210
+ if (command === "doctor")
211
+ return cmdDoctor();
212
+ if (command === "help" || command === "-h" || command === "--help") {
213
+ printHelp(base);
214
+ return;
215
+ }
216
+ console.error(`Unknown command: ${command}`);
217
+ printHelp(base);
218
+ process.exit(1);
219
+ }
220
+ main().catch((err) => {
221
+ console.error(err instanceof Error ? err.message : err);
222
+ process.exit(1);
223
+ });
@@ -0,0 +1,2 @@
1
+ export declare function openBrowser(url: string): Promise<void>;
2
+ //# sourceMappingURL=open-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../../src/cli/open-browser.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBtD"}
@@ -0,0 +1,26 @@
1
+ import { execFile } from "node:child_process";
2
+ export function openBrowser(url) {
3
+ return new Promise((resolve, reject) => {
4
+ const platform = process.platform;
5
+ let command;
6
+ let args;
7
+ if (platform === "win32") {
8
+ command = "cmd";
9
+ args = ["/c", "start", "", url];
10
+ }
11
+ else if (platform === "darwin") {
12
+ command = "open";
13
+ args = [url];
14
+ }
15
+ else {
16
+ command = "xdg-open";
17
+ args = [url];
18
+ }
19
+ execFile(command, args, (err) => {
20
+ if (err)
21
+ reject(err);
22
+ else
23
+ resolve();
24
+ });
25
+ });
26
+ }
@@ -0,0 +1,113 @@
1
+ # Complex usage — all Nzila SDK features
2
+
3
+ This guide ties together **test webhooks**, **runtime signals**, **mapFeature**, and **manual error reporting** in one flow. Use it after the quick starts in [README.md](README.md), [TRACING-FAILURES.md](TRACING-FAILURES.md), and [RUNTIME-TRACE.md](RUNTIME-TRACE.md).
4
+
5
+ ## Feature matrix
6
+
7
+ | Capability | API | When to use |
8
+ |------------|-----|-------------|
9
+ | CI test run | `NzilaVitestReporter` / `NzilaJestReporter` / Mocha | Every `vitest run` / Jest / Mocha finish |
10
+ | Manual run POST | `sendNzilaRun(payload, { webhookUrl, apiKey })` | Custom runners, replay payloads |
11
+ | Feature naming | `mapFeature(describePath, testName)` | Suite title ≠ dashboard feature |
12
+ | Backend handler | `traceNzilaFeature("Checkout")` | First line of route/service |
13
+ | React screen | `useNzilaFeature("Checkout")` | Top of component matching tests |
14
+ | HTTP wrapper | `nzila.runApi("label", () => fetch…)` | Auto `api` success/failure |
15
+ | Handled errors | `nzila.captureError(err, { … })` | `catch`, validation, business rules |
16
+ | No handle in scope | `reportFeatureError("Checkout", err)` | Deep helper, fire-and-forget |
17
+ | API failure label | `nzila.captureApiError(err, "payment.charge")` | After failed call outside `runApi` |
18
+ | UI issues | `nzila.reportUi("custom_banner", { … })` | Non-throwing UX problems |
19
+ | Render errors | `NzilaFeatureBoundary` + `useNzilaFeature` | Child tree throws |
20
+ | Static demo payload | `shared/send-webhook.mjs` | No Vitest installed |
21
+
22
+ Use the **same feature strings** everywhere (e.g. `"Checkout"`, `"Inventory"`) so test failures and runtime signals land on one dashboard row.
23
+
24
+ ## 1. Complex Vitest run (multi-feature, pass + fail)
25
+
26
+ **Files:** `complex/full-platform.demo.test.ts`, `vitest.complex.config.ts`, `shared/feature-map.ts`
27
+
28
+ - Three describe roots: `Checkout UI`, `Inventory`, `Authentication`
29
+ - `mapFeature` maps UI vs API names via `resolveFrontendFeature` / `resolveBackendFeature`
30
+ - Several tests **fail on purpose** so Nzila shows failure analysis
31
+
32
+ ```bash
33
+ # .env.local: NZILA_API_KEY, NZILA_WEBHOOK_URL
34
+ # Optional: NZILA_COMPLEX_APP_NAME=checkout-api (must exist in dashboard)
35
+ npm run example:test:complex
36
+ ```
37
+
38
+ Open **Runs** → latest run → failures grouped by feature.
39
+
40
+ ## 2. Complex backend runtime (runApi + capture + reportFeatureError)
41
+
42
+ **File:** `complex/api-services.demo.ts`
43
+
44
+ Demonstrates:
45
+
46
+ 1. `initNzilaRuntime({ signalsUrl, apiKey })`
47
+ 2. `traceNzilaFeature("Checkout")` with `runApi` for inventory + payment
48
+ 3. `captureError` for handled business failure (409)
49
+ 4. `captureApiError` for pipeline failure
50
+ 5. Second feature `Inventory` with `reportFeatureError` in a job
51
+
52
+ ```bash
53
+ npm run example:runtime:complex
54
+ ```
55
+
56
+ Wait ~1s for batched flush, then check **Feature health** / runtime signals for `Checkout` and `Inventory`.
57
+
58
+ ## 3. Tracing-only Vitest (focused failure fingerprints)
59
+
60
+ ```bash
61
+ npm run example:test:tracing:all
62
+ npm run example:webhook:tracing
63
+ npm run example:webhook:tracing:frontend
64
+ ```
65
+
66
+ ## 4. React runtime (monorepo)
67
+
68
+ See [RUNTIME-TRACE.md](RUNTIME-TRACE.md). Pattern:
69
+
70
+ ```tsx
71
+ initNzilaRuntime({ signalsUrl, apiKey });
72
+
73
+ function CheckoutPage() {
74
+ const nzila = useNzilaFeature("Checkout");
75
+ async function pay() {
76
+ try {
77
+ await nzila.runApi("checkout.submit", () =>
78
+ fetch("/api/checkout", { method: "POST" }),
79
+ );
80
+ } catch (e) {
81
+ nzila.captureError(e, { step: "submit" });
82
+ }
83
+ }
84
+ return (
85
+ <NzilaFeatureBoundary feature="Checkout" nzila={nzila}>
86
+ {/* children */}
87
+ </NzilaFeatureBoundary>
88
+ );
89
+ }
90
+ ```
91
+
92
+ ## 5. Jest and Mocha
93
+
94
+ - Jest: copy `jest.config.example.cjs` → wire `NzilaJestReporter` with same env vars as Vitest.
95
+ - Mocha: `mocharc.nzila.example.cjs` — register reporter, call `sendNzilaRun` on `end` if you roll your own.
96
+
97
+ ## 6. End-to-end local checklist
98
+
99
+ 1. `npm run dev` + `npm run worker`
100
+ 2. Create app(s): `checkout-api`, `checkout-web` (or your `NZILA_COMPLEX_APP_NAME`)
101
+ 3. API key in `.env.local`
102
+ 4. `npm run example:test:complex` → webhook run
103
+ 5. `npm run example:runtime:complex` → runtime signals
104
+ 6. Dashboard: **Runs**, **Failures**, **Feature health** — same feature names
105
+
106
+ ## Environment reference
107
+
108
+ | Variable | Used by |
109
+ |----------|---------|
110
+ | `NZILA_API_KEY` | Webhook + runtime |
111
+ | `NZILA_WEBHOOK_URL` | Vitest/Jest reporters, `sendNzilaRun` |
112
+ | `NZILA_SIGNALS_URL` | `initNzilaRuntime` (default `http://localhost:3000/api/signals/runtime`) |
113
+ | `NZILA_COMPLEX_APP_NAME` | Complex Vitest config only |
@@ -0,0 +1,27 @@
1
+ # @nzila/sdk examples
2
+
3
+ These files ship inside the npm package under `node_modules/@nzila/sdk/examples/`.
4
+
5
+ | Topic | Files |
6
+ |-------|--------|
7
+ | Overview | [README from monorepo](./README.md) |
8
+ | All features walkthrough | [COMPLEX-USAGE.md](./COMPLEX-USAGE.md) |
9
+ | Live app tracing | [RUNTIME-TRACE.md](./RUNTIME-TRACE.md) |
10
+ | Test → dashboard mapping | [TRACING-FAILURES.md](./TRACING-FAILURES.md) |
11
+ | Vitest | [vitest.config.example.ts](./vitest.config.example.ts), [complex/](./complex/) |
12
+ | Jest | [jest.config.example.cjs](./jest.config.example.cjs) |
13
+ | Mocha | [mocharc.nzila.example.cjs](./mocharc.nzila.example.cjs) |
14
+ | Backend runtime | [backend/runtime-trace.example.ts](./backend/runtime-trace.example.ts), [complex/api-services.demo.ts](./complex/api-services.demo.ts) |
15
+ | React | [react/checkout-feature.example.tsx](./react/checkout-feature.example.tsx) |
16
+ | Manual webhook | [send-run-manual.mjs](./send-run-manual.mjs), [shared/send-webhook.mjs](./shared/send-webhook.mjs) |
17
+ | Sample payloads | [backend/sample-payload.json](./backend/sample-payload.json), [frontend/sample-payload.json](./frontend/sample-payload.json) |
18
+
19
+ ## Environment
20
+
21
+ ```env
22
+ NZILA_API_KEY=nzl_...
23
+ NZILA_WEBHOOK_URL=https://your-host/api/webhooks/tests
24
+ NZILA_SIGNALS_URL=https://your-host/api/signals/runtime
25
+ ```
26
+
27
+ Imports in these files use `@nzila/sdk` — the same as in your application after `npm install @nzila/sdk`.
@@ -0,0 +1,94 @@
1
+ > **npm:** Start with [INDEX.md](./INDEX.md). Imports use `@nzila/sdk`.
2
+
3
+ # Nzila integration examples
4
+
5
+ End-to-end samples for **backend (API)** and **frontend (UI)** test flows.
6
+
7
+ ## Prerequisites
8
+
9
+ 1. `npm run dev` and `npm run worker` (with `QUEUE_DRIVER` and DB migrated).
10
+ 2. Register, create an API key at `/en/keys`.
11
+ 3. In **`.env.local`**:
12
+
13
+ ```env
14
+ NZILA_API_KEY=nzl_...
15
+ NZILA_WEBHOOK_URL=http://localhost:3000/api/webhooks/tests
16
+ HF_API_TOKEN=hf_... # optional, for AI summaries
17
+ ```
18
+
19
+ The same examples are published inside **`@nzila/sdk`** at `node_modules/@nzila/sdk/examples/` (see `INDEX.md` there).
20
+
21
+ ## Layout
22
+
23
+ | Path | Purpose |
24
+ |------|---------|
25
+ | `backend/` | API-style unit tests (pricing, inventory, auth) |
26
+ | `frontend/` | UI logic tests (checkout form, product card) |
27
+ | `shared/send-webhook.mjs` | POST static JSON payloads (CI / manual) |
28
+ | `vitest.config.ts` | Vitest + Nzila reporter (fires webhook on finish) |
29
+ | `jest.config.example.cjs` | Jest + NzilaJestReporter |
30
+ | `mocharc.nzila.example.cjs` | Mocha reporter setup notes |
31
+ | `@nzila/sdk` | Installed npm package (you are reading its `examples/` folder) |
32
+
33
+ Each suite includes **passing and failing** tests so the dashboard shows real failure analysis.
34
+
35
+ ## Trace failures (tests → dashboard)
36
+
37
+ See **[TRACING-FAILURES.md](TRACING-FAILURES.md)** for how `describe()` paths, fingerprints, and `errors[]` map to **Runs**, **Failures**, and **Feature health**.
38
+
39
+ ## Complex usage (all features)
40
+
41
+ See **[COMPLEX-USAGE.md](COMPLEX-USAGE.md)** for a single walkthrough: multi-feature Vitest, `mapFeature`, runtime `runApi` / `captureError`, Jest/Mocha, and env vars.
42
+
43
+ ```bash
44
+ npm run example:test:complex # Vitest: Checkout UI + Inventory + Auth (pass/fail)
45
+ npm run example:runtime:complex # Backend: traceNzilaFeature + reportFeatureError
46
+ ```
47
+
48
+ ## Runtime trace (live app → Feature health)
49
+
50
+ See **[RUNTIME-TRACE.md](RUNTIME-TRACE.md)** for `useNzilaFeature` (React), `traceNzilaFeature` (backend), and **`captureError` / `reportFeatureError`** when you handle errors yourself.
51
+
52
+ Example backend handler: `backend/runtime-trace.example.ts`. Heavier demo: `complex/api-services.demo.ts`.
53
+
54
+ Quick demo (Vitest only):
55
+
56
+ ```bash
57
+ npm run example:test:tracing # Vitest → webhook
58
+ npm run example:webhook:tracing # static JSON payload
59
+ ```
60
+
61
+ ## Run Vitest (sends one webhook per run)
62
+
63
+ ```bash
64
+ # All examples (mixed app name: nzila-demo)
65
+ npm run example:test
66
+
67
+ # Backend only → app name checkout-api
68
+ npm run example:test:backend
69
+
70
+ # Frontend only → app name checkout-web
71
+ npm run example:test:frontend
72
+ ```
73
+
74
+ ## Send sample payloads (no Vitest)
75
+
76
+ ```bash
77
+ npm run example:webhook:backend
78
+ npm run example:webhook:frontend
79
+ npm run example:webhook # both
80
+ ```
81
+
82
+ ## Full local demo
83
+
84
+ ```bash
85
+ npm run example:all # vitest + both webhooks (needs dev + worker up)
86
+ ```
87
+
88
+ ## Server-side client
89
+
90
+ Use `frontend-webhook-client.ts` from a Route Handler or CI job — not from browser bundles.
91
+
92
+ ## Payload contract
93
+
94
+ See `backend/sample-payload.json`, `frontend/sample-payload.json`, and `src/lib/webhook-schema.ts`.