@sungen/driver-api 3.1.2-beta.111 → 3.1.2-beta.112

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 (2) hide show
  1. package/package.json +2 -2
  2. package/src/index.ts +13 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sungen/driver-api",
3
- "version": "3.1.2-beta.111",
3
+ "version": "3.1.2-beta.112",
4
4
  "description": "Sungen API capability — the @api annotation, API catalog, OpenAPI import + `sungen api import`, and the specs/api.ts runtime template. Plugs into @sun-asterisk/sungen via the capability SPI.",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -13,7 +13,7 @@
13
13
  "author": "eqe team (engineer & quality) — Sun Asterisk",
14
14
  "license": "MIT",
15
15
  "dependencies": {
16
- "@sun-asterisk/sungen": "3.1.2-beta.111",
16
+ "@sun-asterisk/sungen": "3.1.2-beta.112",
17
17
  "commander": "^14.0.2",
18
18
  "yaml": "^2.8.2"
19
19
  },
package/src/index.ts CHANGED
@@ -55,6 +55,11 @@ export { importCsv, parseCsv } from './csv-import';
55
55
  function apiPreconditionCodegen(input: { tags: string[]; screenName: string; cwd: string }): Array<{ comment?: string; code: string; boundVars?: string[] }> {
56
56
  const out: Array<{ comment?: string; code: string; boundVars?: string[] }> = [];
57
57
  const TAG = /^@api:([A-Za-z_][A-Za-z0-9_]*)(?:\((.*)\))?$/;
58
+ // @concurrent:N (AP-5): fire each @api call N times in parallel and bind aggregates
59
+ // ({{name.ok_count}}, {{name.status_counts}}) — the idempotency/race oracle. Applies to the
60
+ // scenario's @api call(s); pair with @query to cross-check the DB ("exactly one charge").
61
+ const concMatch = input.tags.map((t) => t.match(/^@concurrent:(\d+)$/)).find(Boolean);
62
+ const concurrent = concMatch ? Math.max(1, parseInt(concMatch[1], 10)) : 0;
58
63
  for (const tag of input.tags) {
59
64
  const m = tag.match(TAG);
60
65
  if (!m) continue;
@@ -71,9 +76,15 @@ function apiPreconditionCodegen(input: { tags: string[]; screenName: string; cwd
71
76
  // mechanism (the dynamic value comes via an override like `token={{login.body.token}}`).
72
77
  const hdr = entry.headers && Object.keys(entry.headers).length ? `, headers: ${JSON.stringify(entry.headers)}` : '';
73
78
  const req = `{ method: ${JSON.stringify(entry.method)}, path: ${JSON.stringify(entry.path)}${entry.body !== undefined ? `, body: ${JSON.stringify(entry.body)}` : ''}${hdr}, datasource: ${ds} }`;
79
+ // @concurrent:N → callN (N parallel calls, aggregate result); else a single call.
80
+ const callExpr = concurrent
81
+ ? `await api.callN(${label}, ${req}, { ${paramsObj} }, ${concurrent})`
82
+ : `await api.call(${label}, ${req}, { ${paramsObj} })`;
74
83
  out.push({
75
- comment: `@api:${name} → bind {{${name}}} (${entry.method} ${entry.path})`,
76
- code: `testData.bind(${JSON.stringify(name)}, await api.call(${label}, ${req}, { ${paramsObj} }));`,
84
+ comment: concurrent
85
+ ? `@api:${name} ×${concurrent} (@concurrent) → bind {{${name}}} aggregates (${entry.method} ${entry.path})`
86
+ : `@api:${name} → bind {{${name}}} (${entry.method} ${entry.path})`,
87
+ code: `testData.bind(${JSON.stringify(name)}, ${callExpr});`,
77
88
  boundVars: [name],
78
89
  });
79
90
  }