@specverse/engines 6.33.1 → 6.35.0

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 (61) hide show
  1. package/dist/libs/instance-factories/communication/rabbitmq-events.yaml +11 -0
  2. package/dist/libs/instance-factories/controllers/fastify.yaml +11 -0
  3. package/dist/libs/instance-factories/managed/stripe-rest-sdk.yaml +78 -0
  4. package/dist/libs/instance-factories/managed/templates/stripe/stripe-client-generator.js +8 -0
  5. package/dist/libs/instance-factories/orms/prisma.yaml +11 -0
  6. package/dist/libs/instance-factories/services/templates/prisma/behavior-generator.js +4 -1
  7. package/dist/realize/index.d.ts.map +1 -1
  8. package/dist/realize/index.js +246 -1
  9. package/dist/realize/index.js.map +1 -1
  10. package/dist/realize/library/loader.d.ts.map +1 -1
  11. package/dist/realize/library/loader.js +81 -1
  12. package/dist/realize/library/loader.js.map +1 -1
  13. package/dist/realize/per-action-emitter.d.ts +11 -33
  14. package/dist/realize/per-action-emitter.d.ts.map +1 -1
  15. package/dist/realize/per-action-emitter.js.map +1 -1
  16. package/dist/realize/per-action-llm-emit.d.ts.map +1 -1
  17. package/dist/realize/per-action-llm-emit.js +5 -1
  18. package/dist/realize/per-action-llm-emit.js.map +1 -1
  19. package/dist/realize/per-action-runner.d.ts +45 -0
  20. package/dist/realize/per-action-runner.d.ts.map +1 -1
  21. package/dist/realize/per-action-runner.js +132 -0
  22. package/dist/realize/per-action-runner.js.map +1 -1
  23. package/dist/realize/resolver/index.d.ts +157 -0
  24. package/dist/realize/resolver/index.d.ts.map +1 -0
  25. package/dist/realize/resolver/index.js +307 -0
  26. package/dist/realize/resolver/index.js.map +1 -0
  27. package/dist/realize/runtime-emitters/dispatcher.d.ts +176 -0
  28. package/dist/realize/runtime-emitters/dispatcher.d.ts.map +1 -0
  29. package/dist/realize/runtime-emitters/dispatcher.js +76 -0
  30. package/dist/realize/runtime-emitters/dispatcher.js.map +1 -0
  31. package/dist/realize/runtime-emitters/executable.d.ts +57 -0
  32. package/dist/realize/runtime-emitters/executable.d.ts.map +1 -0
  33. package/dist/realize/runtime-emitters/executable.js +316 -0
  34. package/dist/realize/runtime-emitters/executable.js.map +1 -0
  35. package/dist/realize/runtime-emitters/library.d.ts +52 -0
  36. package/dist/realize/runtime-emitters/library.d.ts.map +1 -0
  37. package/dist/realize/runtime-emitters/library.js +349 -0
  38. package/dist/realize/runtime-emitters/library.js.map +1 -0
  39. package/dist/realize/runtime-emitters/managed.d.ts +44 -0
  40. package/dist/realize/runtime-emitters/managed.d.ts.map +1 -0
  41. package/dist/realize/runtime-emitters/managed.js +283 -0
  42. package/dist/realize/runtime-emitters/managed.js.map +1 -0
  43. package/dist/realize/runtime-emitters/messaging.d.ts +77 -0
  44. package/dist/realize/runtime-emitters/messaging.d.ts.map +1 -0
  45. package/dist/realize/runtime-emitters/messaging.js +423 -0
  46. package/dist/realize/runtime-emitters/messaging.js.map +1 -0
  47. package/dist/realize/runtime-emitters/service.d.ts +42 -0
  48. package/dist/realize/runtime-emitters/service.d.ts.map +1 -0
  49. package/dist/realize/runtime-emitters/service.js +355 -0
  50. package/dist/realize/runtime-emitters/service.js.map +1 -0
  51. package/dist/realize/types/instance-factory.d.ts +1 -1
  52. package/dist/realize/types/instance-factory.d.ts.map +1 -1
  53. package/libs/instance-factories/communication/rabbitmq-events.yaml +11 -0
  54. package/libs/instance-factories/controllers/fastify.yaml +11 -0
  55. package/libs/instance-factories/managed/stripe-rest-sdk.yaml +78 -0
  56. package/libs/instance-factories/managed/templates/stripe/stripe-client-generator.ts +26 -0
  57. package/libs/instance-factories/orms/prisma.yaml +11 -0
  58. package/libs/instance-factories/services/templates/_shared/step-matching.ts +11 -29
  59. package/libs/instance-factories/services/templates/prisma/__tests__/behavior-generator.test.ts +85 -0
  60. package/libs/instance-factories/services/templates/prisma/behavior-generator.ts +21 -1
  61. package/package.json +2 -2
@@ -0,0 +1,85 @@
1
+ /**
2
+ * behavior-generator.ts — postcondition emission tests (#53D).
3
+ *
4
+ * The generator emits one `console.assert(true, '<text>');` line per
5
+ * postcondition string in the dev-mode block. Pre-#53D the wrapper was
6
+ * single-quoted; postcondition text containing apostrophes — common in
7
+ * natural prose like "no other nodes' cache entries are affected" —
8
+ * terminated the JS string and esbuild rejected the file.
9
+ *
10
+ * #53D fix: emit with backticks + escape any backticks / `${` markers
11
+ * in the source. These tests pin the new shape so a future change
12
+ * can't silently regress to single-quoted strings.
13
+ */
14
+
15
+ import { describe, it, expect } from 'vitest';
16
+ import { generatePostconditionVerification } from '../behavior-generator.js';
17
+
18
+ describe('generatePostconditionVerification — 53D apostrophe handling', () => {
19
+ it('returns empty string for empty input', () => {
20
+ expect(generatePostconditionVerification([])).toBe('');
21
+ });
22
+
23
+ it('emits backtick-wrapped strings (not single-quoted)', () => {
24
+ const out = generatePostconditionVerification(['simple postcondition']);
25
+ expect(out).toContain('`POSTCONDITION: simple postcondition`');
26
+ expect(out).not.toContain("'POSTCONDITION:");
27
+ });
28
+
29
+ it('preserves apostrophes verbatim in postcondition text', () => {
30
+ const out = generatePostconditionVerification([
31
+ "no other nodes' cache entries are affected",
32
+ ]);
33
+ expect(out).toContain("nodes' cache entries");
34
+ // Must not have escaped the apostrophe — backticks accept it natively.
35
+ expect(out).not.toContain("nodes\\'");
36
+ });
37
+
38
+ it('escapes embedded backticks to prevent string termination', () => {
39
+ const out = generatePostconditionVerification([
40
+ 'value matches `expected` shape',
41
+ ]);
42
+ expect(out).toContain('value matches \\`expected\\` shape');
43
+ });
44
+
45
+ it('escapes ${...} interpolation markers to prevent template execution', () => {
46
+ const out = generatePostconditionVerification([
47
+ 'rejects ${malicious} payloads',
48
+ ]);
49
+ expect(out).toContain('rejects \\${malicious} payloads');
50
+ // The marker must NOT appear unescaped — that would let the spec
51
+ // author smuggle template-literal interpolation into realized code.
52
+ expect(out).not.toMatch(/[^\\]\$\{malicious\}/);
53
+ });
54
+
55
+ it('escapes backslashes before other escapes (stable round-trip)', () => {
56
+ const out = generatePostconditionVerification(['regex \\d+ matches']);
57
+ expect(out).toContain('regex \\\\d+ matches');
58
+ });
59
+
60
+ it('emits one console.assert line per postcondition', () => {
61
+ const out = generatePostconditionVerification(['p1', 'p2', 'p3']);
62
+ const matches = out.match(/console\.assert\(true,/g);
63
+ expect(matches?.length).toBe(3);
64
+ });
65
+
66
+ it('wraps the assertion block in NODE_ENV development guard', () => {
67
+ const out = generatePostconditionVerification(['p1']);
68
+ expect(out).toContain("process.env.NODE_ENV === 'development'");
69
+ expect(out).toContain('// === POSTCONDITIONS (dev-mode) ===');
70
+ });
71
+
72
+ it('produces output that parses as valid JavaScript', async () => {
73
+ // The whole point of #53D — the emitted code must actually parse.
74
+ // Use Function() as a lightweight syntax-check (rejects malformed
75
+ // template literals just as esbuild would).
76
+ const realistic = generatePostconditionVerification([
77
+ "no other nodes' cache entries are affected",
78
+ 'response includes a `Last-Modified` header',
79
+ 'rejects ${oversized} payloads with 413',
80
+ ]);
81
+ // Wrap in a function body to give it a syntactic context.
82
+ const wrap = `(function() {\n${realistic}\n})`;
83
+ expect(() => new Function(`return ${wrap}`)).not.toThrow();
84
+ });
85
+ });
@@ -323,8 +323,28 @@ function inferLogicFromOperationName(context: BehaviorContext): string {
323
323
  return { success: true };`;
324
324
  }
325
325
 
326
+ /**
327
+ * Escape a postcondition string for safe inclusion in a JS template
328
+ * literal (backtick) — the only chars that can break a backtick string
329
+ * are unescaped backticks and `${` interpolation markers.
330
+ *
331
+ * Postcondition text comes verbatim from the spec author and frequently
332
+ * contains apostrophes (e.g. "no other nodes' cache entries are
333
+ * affected"). Pre-53D the emitter wrapped these in single quotes, so
334
+ * the apostrophe terminated the JS string and esbuild rejected the
335
+ * file. Switching to backticks + this escape closes that class.
336
+ */
337
+ function escapeForBacktick(text: string): string {
338
+ return text.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
339
+ }
340
+
326
341
  /**
327
342
  * Generate postcondition verification (dev-mode assertions).
343
+ *
344
+ * 53D fix: emit with backtick template literals (not single quotes) so
345
+ * postconditions containing apostrophes — which the spec format
346
+ * encourages for natural prose — survive realize without breaking
347
+ * esbuild's parse.
328
348
  */
329
349
  export function generatePostconditionVerification(
330
350
  postconditions: string[]
@@ -332,7 +352,7 @@ export function generatePostconditionVerification(
332
352
  if (postconditions.length === 0) return '';
333
353
 
334
354
  const checks = postconditions.map(pc =>
335
- ` console.assert(true, 'POSTCONDITION: ${pc}');`
355
+ ` console.assert(true, \`POSTCONDITION: ${escapeForBacktick(pc)}\`);`
336
356
  );
337
357
 
338
358
  return ` // === POSTCONDITIONS (dev-mode) ===
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specverse/engines",
3
- "version": "6.33.1",
3
+ "version": "6.35.0",
4
4
  "description": "SpecVerse toolchain — parser, inference, realize, generators, AI, registry, bundles",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -65,7 +65,7 @@
65
65
  "@specverse/engines": "^6.29.3",
66
66
  "@specverse/entities": "^5.4.0",
67
67
  "@specverse/runtime": "^5.0.1",
68
- "@specverse/types": "^5.1.0",
68
+ "@specverse/types": "^5.2.0",
69
69
  "ai": "^6.0.168",
70
70
  "ajv": "^8.17.0",
71
71
  "ajv-formats": "^2.1.0",