@auto-engineer/narrative 0.13.2 → 0.14.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 (239) hide show
  1. package/.turbo/turbo-build.log +10 -9
  2. package/CHANGELOG.md +24 -0
  3. package/dist/scripts/convert-flow-exec.js +2 -2
  4. package/dist/scripts/convert-flow-exec.js.map +1 -1
  5. package/dist/scripts/convert-flow-helper.js +3 -4
  6. package/dist/scripts/convert-flow-helper.js.map +1 -1
  7. package/dist/scripts/convert-flow.js +4 -4
  8. package/dist/scripts/convert-flow.js.map +1 -1
  9. package/dist/scripts/print-schema.js +1 -1
  10. package/dist/scripts/print-schema.js.map +1 -1
  11. package/dist/src/commands/export-schema-helper.js +9 -9
  12. package/dist/src/commands/export-schema-helper.js.map +1 -1
  13. package/dist/src/commands/export-schema.d.ts.map +1 -1
  14. package/dist/src/commands/export-schema.js +44 -67
  15. package/dist/src/commands/export-schema.js.map +1 -1
  16. package/dist/src/data-narrative-builders.d.ts +1 -1
  17. package/dist/src/data-narrative-builders.d.ts.map +1 -1
  18. package/dist/src/data-narrative-builders.js +13 -19
  19. package/dist/src/data-narrative-builders.js.map +1 -1
  20. package/dist/src/fluent-builder.d.ts.map +1 -1
  21. package/dist/src/fluent-builder.js +2 -2
  22. package/dist/src/fluent-builder.js.map +1 -1
  23. package/dist/src/fluent-builder.specs.js +2 -2
  24. package/dist/src/fluent-builder.specs.js.map +1 -1
  25. package/dist/src/getNarratives.cache.specs.js +5 -5
  26. package/dist/src/getNarratives.cache.specs.js.map +1 -1
  27. package/dist/src/getNarratives.d.ts +1 -1
  28. package/dist/src/getNarratives.d.ts.map +1 -1
  29. package/dist/src/getNarratives.js +6 -3
  30. package/dist/src/getNarratives.js.map +1 -1
  31. package/dist/src/getNarratives.specs.js +6 -6
  32. package/dist/src/getNarratives.specs.js.map +1 -1
  33. package/dist/src/id/addAutoIds.d.ts +1 -1
  34. package/dist/src/id/addAutoIds.d.ts.map +1 -1
  35. package/dist/src/id/addAutoIds.js.map +1 -1
  36. package/dist/src/id/addAutoIds.specs.js +1 -1
  37. package/dist/src/id/addAutoIds.specs.js.map +1 -1
  38. package/dist/src/id/hasAllIds.d.ts +1 -1
  39. package/dist/src/id/hasAllIds.d.ts.map +1 -1
  40. package/dist/src/id/hasAllIds.specs.js +1 -1
  41. package/dist/src/id/hasAllIds.specs.js.map +1 -1
  42. package/dist/src/id/index.d.ts +1 -1
  43. package/dist/src/id/index.d.ts.map +1 -1
  44. package/dist/src/id/index.js +1 -1
  45. package/dist/src/id/index.js.map +1 -1
  46. package/dist/src/index.d.ts +14 -17
  47. package/dist/src/index.d.ts.map +1 -1
  48. package/dist/src/index.js +8 -10
  49. package/dist/src/index.js.map +1 -1
  50. package/dist/src/integration-export-registry.d.ts +2 -2
  51. package/dist/src/integration-export-registry.d.ts.map +1 -1
  52. package/dist/src/integration-registry.d.ts +1 -1
  53. package/dist/src/integration-registry.d.ts.map +1 -1
  54. package/dist/src/integration-registry.js +1 -0
  55. package/dist/src/integration-registry.js.map +1 -1
  56. package/dist/src/loader/fs-path.js +2 -2
  57. package/dist/src/loader/fs-path.js.map +1 -1
  58. package/dist/src/loader/graph.d.ts +2 -2
  59. package/dist/src/loader/graph.d.ts.map +1 -1
  60. package/dist/src/loader/graph.js +7 -3
  61. package/dist/src/loader/graph.js.map +1 -1
  62. package/dist/src/loader/index.d.ts +1 -1
  63. package/dist/src/loader/index.d.ts.map +1 -1
  64. package/dist/src/loader/index.js +5 -5
  65. package/dist/src/loader/index.js.map +1 -1
  66. package/dist/src/loader/resolver.js +1 -1
  67. package/dist/src/loader/resolver.js.map +1 -1
  68. package/dist/src/loader/runtime-cjs.d.ts.map +1 -1
  69. package/dist/src/loader/runtime-cjs.js +2 -2
  70. package/dist/src/loader/runtime-cjs.js.map +1 -1
  71. package/dist/src/loader/ts-utils.js +5 -5
  72. package/dist/src/loader/ts-utils.js.map +1 -1
  73. package/dist/src/model-to-narrative.specs.js +73 -98
  74. package/dist/src/model-to-narrative.specs.js.map +1 -1
  75. package/dist/src/narrative-context.d.ts +4 -4
  76. package/dist/src/narrative-context.d.ts.map +1 -1
  77. package/dist/src/narrative-context.js +2 -2
  78. package/dist/src/narrative-context.js.map +1 -1
  79. package/dist/src/narrative-context.specs.js +118 -3
  80. package/dist/src/narrative-context.specs.js.map +1 -1
  81. package/dist/src/narrative-registry.d.ts +1 -1
  82. package/dist/src/narrative-registry.d.ts.map +1 -1
  83. package/dist/src/narrative-registry.js +1 -1
  84. package/dist/src/narrative-registry.js.map +1 -1
  85. package/dist/src/narrative.d.ts +3 -3
  86. package/dist/src/narrative.d.ts.map +1 -1
  87. package/dist/src/narrative.js +15 -17
  88. package/dist/src/narrative.js.map +1 -1
  89. package/dist/src/node.d.ts +1 -1
  90. package/dist/src/node.d.ts.map +1 -1
  91. package/dist/src/node.js +1 -1
  92. package/dist/src/node.js.map +1 -1
  93. package/dist/src/samples/items.narrative.js +2 -2
  94. package/dist/src/samples/items.narrative.js.map +1 -1
  95. package/dist/src/samples/mixed-given-types.narrative.js +1 -1
  96. package/dist/src/samples/mixed-given-types.narrative.js.map +1 -1
  97. package/dist/src/samples/place-order.narrative.js +1 -1
  98. package/dist/src/samples/place-order.narrative.js.map +1 -1
  99. package/dist/src/samples/questionnaires.narrative.js +1 -1
  100. package/dist/src/samples/questionnaires.narrative.js.map +1 -1
  101. package/dist/src/samples/test-with-ids.narrative.js +1 -1
  102. package/dist/src/samples/test-with-ids.narrative.js.map +1 -1
  103. package/dist/src/schema-test.js +1 -1
  104. package/dist/src/schema-test.js.map +1 -1
  105. package/dist/src/schema.d.ts +264 -264
  106. package/dist/src/slice-builder.d.ts.map +1 -1
  107. package/dist/src/slice-builder.js +1 -1
  108. package/dist/src/slice-builder.js.map +1 -1
  109. package/dist/src/transformers/model-to-narrative/ast/emit-helpers.d.ts +1 -1
  110. package/dist/src/transformers/model-to-narrative/ast/emit-helpers.d.ts.map +1 -1
  111. package/dist/src/transformers/model-to-narrative/formatting/sort-types.js +1 -1
  112. package/dist/src/transformers/model-to-narrative/formatting/sort-types.js.map +1 -1
  113. package/dist/src/transformers/model-to-narrative/generators/compose.d.ts +1 -1
  114. package/dist/src/transformers/model-to-narrative/generators/compose.d.ts.map +1 -1
  115. package/dist/src/transformers/model-to-narrative/generators/compose.js +4 -4
  116. package/dist/src/transformers/model-to-narrative/generators/compose.js.map +1 -1
  117. package/dist/src/transformers/model-to-narrative/generators/flow.d.ts +1 -1
  118. package/dist/src/transformers/model-to-narrative/generators/flow.d.ts.map +1 -1
  119. package/dist/src/transformers/model-to-narrative/generators/flow.js.map +1 -1
  120. package/dist/src/transformers/model-to-narrative/generators/gwt.d.ts +1 -1
  121. package/dist/src/transformers/model-to-narrative/generators/gwt.d.ts.map +1 -1
  122. package/dist/src/transformers/model-to-narrative/generators/gwt.js +47 -57
  123. package/dist/src/transformers/model-to-narrative/generators/gwt.js.map +1 -1
  124. package/dist/src/transformers/model-to-narrative/generators/gwt.specs.d.ts +2 -0
  125. package/dist/src/transformers/model-to-narrative/generators/gwt.specs.d.ts.map +1 -0
  126. package/dist/src/transformers/model-to-narrative/generators/gwt.specs.js +142 -0
  127. package/dist/src/transformers/model-to-narrative/generators/gwt.specs.js.map +1 -0
  128. package/dist/src/transformers/model-to-narrative/generators/imports.d.ts +1 -1
  129. package/dist/src/transformers/model-to-narrative/generators/imports.d.ts.map +1 -1
  130. package/dist/src/transformers/model-to-narrative/generators/imports.js +0 -4
  131. package/dist/src/transformers/model-to-narrative/generators/imports.js.map +1 -1
  132. package/dist/src/transformers/model-to-narrative/generators/types.d.ts +1 -1
  133. package/dist/src/transformers/model-to-narrative/generators/types.d.ts.map +1 -1
  134. package/dist/src/transformers/model-to-narrative/index.d.ts +1 -1
  135. package/dist/src/transformers/model-to-narrative/index.d.ts.map +1 -1
  136. package/dist/src/transformers/model-to-narrative/index.js +1 -1
  137. package/dist/src/transformers/model-to-narrative/index.js.map +1 -1
  138. package/dist/src/transformers/narrative-to-model/assemble.d.ts +1 -1
  139. package/dist/src/transformers/narrative-to-model/assemble.d.ts.map +1 -1
  140. package/dist/src/transformers/narrative-to-model/example-shapes.d.ts +1 -1
  141. package/dist/src/transformers/narrative-to-model/example-shapes.d.ts.map +1 -1
  142. package/dist/src/transformers/narrative-to-model/index.d.ts +2 -2
  143. package/dist/src/transformers/narrative-to-model/index.d.ts.map +1 -1
  144. package/dist/src/transformers/narrative-to-model/index.js +5 -5
  145. package/dist/src/transformers/narrative-to-model/index.js.map +1 -1
  146. package/dist/src/transformers/narrative-to-model/inlining.d.ts +2 -2
  147. package/dist/src/transformers/narrative-to-model/inlining.d.ts.map +1 -1
  148. package/dist/src/transformers/narrative-to-model/integrations.d.ts +2 -2
  149. package/dist/src/transformers/narrative-to-model/integrations.d.ts.map +1 -1
  150. package/dist/src/transformers/narrative-to-model/integrations.js +3 -3
  151. package/dist/src/transformers/narrative-to-model/integrations.js.map +1 -1
  152. package/dist/src/transformers/narrative-to-model/messages.d.ts +2 -2
  153. package/dist/src/transformers/narrative-to-model/messages.d.ts.map +1 -1
  154. package/dist/src/transformers/narrative-to-model/messages.js +1 -1
  155. package/dist/src/transformers/narrative-to-model/messages.js.map +1 -1
  156. package/dist/src/transformers/narrative-to-model/normalize.d.ts +1 -1
  157. package/dist/src/transformers/narrative-to-model/normalize.d.ts.map +1 -1
  158. package/dist/src/transformers/narrative-to-model/spec-processors.d.ts +3 -3
  159. package/dist/src/transformers/narrative-to-model/spec-processors.d.ts.map +1 -1
  160. package/dist/src/transformers/narrative-to-model/spec-processors.js +2 -2
  161. package/dist/src/transformers/narrative-to-model/spec-processors.js.map +1 -1
  162. package/dist/src/transformers/narrative-to-model/type-inference.d.ts +1 -1
  163. package/dist/src/transformers/narrative-to-model/type-inference.d.ts.map +1 -1
  164. package/dist/src/transformers/narrative-to-model/type-inference.js +1 -1
  165. package/dist/src/transformers/narrative-to-model/type-inference.js.map +1 -1
  166. package/dist/src/transformers/narrative-to-model/type-inference.specs.js +1 -1
  167. package/dist/src/transformers/narrative-to-model/type-inference.specs.js.map +1 -1
  168. package/dist/src/transformers/narrative-to-model/zod-adapter.d.ts +2 -2
  169. package/dist/src/transformers/narrative-to-model/zod-adapter.d.ts.map +1 -1
  170. package/dist/src/types.d.ts +1 -1
  171. package/dist/src/types.d.ts.map +1 -1
  172. package/dist/tsconfig.tsbuildinfo +1 -1
  173. package/package.json +5 -12
  174. package/scripts/convert-flow-exec.ts +2 -2
  175. package/scripts/convert-flow-helper.ts +3 -4
  176. package/scripts/convert-flow.ts +4 -4
  177. package/scripts/print-schema.ts +2 -2
  178. package/src/commands/export-schema-helper.ts +10 -12
  179. package/src/commands/export-schema.ts +45 -69
  180. package/src/data-narrative-builders.ts +8 -11
  181. package/src/fluent-builder.specs.ts +2 -2
  182. package/src/fluent-builder.ts +6 -6
  183. package/src/getNarratives.cache.specs.ts +6 -6
  184. package/src/getNarratives.specs.ts +6 -6
  185. package/src/getNarratives.ts +13 -5
  186. package/src/id/addAutoIds.specs.ts +2 -2
  187. package/src/id/addAutoIds.ts +1 -1
  188. package/src/id/hasAllIds.specs.ts +1 -1
  189. package/src/id/hasAllIds.ts +1 -1
  190. package/src/id/index.ts +1 -1
  191. package/src/index.ts +61 -54
  192. package/src/integration-export-registry.ts +2 -2
  193. package/src/integration-registry.ts +2 -1
  194. package/src/loader/fs-path.ts +2 -2
  195. package/src/loader/graph.ts +15 -10
  196. package/src/loader/index.ts +7 -7
  197. package/src/loader/resolver.ts +1 -1
  198. package/src/loader/runtime-cjs.ts +3 -3
  199. package/src/loader/ts-utils.ts +5 -5
  200. package/src/model-to-narrative.specs.ts +76 -99
  201. package/src/narrative-context.specs.ts +138 -4
  202. package/src/narrative-context.ts +6 -7
  203. package/src/narrative-registry.ts +2 -2
  204. package/src/narrative.ts +27 -33
  205. package/src/node.ts +1 -2
  206. package/src/samples/items.narrative.ts +3 -3
  207. package/src/samples/mixed-given-types.narrative.ts +2 -2
  208. package/src/samples/place-order.narrative.ts +1 -1
  209. package/src/samples/questionnaires.narrative.ts +10 -10
  210. package/src/samples/test-with-ids.narrative.ts +2 -2
  211. package/src/schema-test.ts +1 -1
  212. package/src/slice-builder.ts +2 -2
  213. package/src/transformers/model-to-narrative/ast/emit-helpers.ts +1 -1
  214. package/src/transformers/model-to-narrative/formatting/sort-types.ts +1 -1
  215. package/src/transformers/model-to-narrative/generators/compose.ts +5 -5
  216. package/src/transformers/model-to-narrative/generators/flow.ts +9 -9
  217. package/src/transformers/model-to-narrative/generators/gwt.specs.ts +157 -0
  218. package/src/transformers/model-to-narrative/generators/gwt.ts +80 -122
  219. package/src/transformers/model-to-narrative/generators/imports.ts +0 -4
  220. package/src/transformers/model-to-narrative/generators/types.ts +1 -1
  221. package/src/transformers/model-to-narrative/index.ts +2 -2
  222. package/src/transformers/narrative-to-model/assemble.ts +1 -1
  223. package/src/transformers/narrative-to-model/example-shapes.ts +1 -1
  224. package/src/transformers/narrative-to-model/index.ts +7 -7
  225. package/src/transformers/narrative-to-model/inlining.ts +2 -2
  226. package/src/transformers/narrative-to-model/integrations.ts +5 -5
  227. package/src/transformers/narrative-to-model/messages.ts +3 -3
  228. package/src/transformers/narrative-to-model/normalize.ts +1 -1
  229. package/src/transformers/narrative-to-model/spec-processors.ts +4 -4
  230. package/src/transformers/narrative-to-model/type-inference.specs.ts +2 -2
  231. package/src/transformers/narrative-to-model/type-inference.ts +2 -2
  232. package/src/transformers/narrative-to-model/zod-adapter.ts +2 -2
  233. package/src/types.ts +1 -1
  234. package/dist/src/commands/export-schema-runner.d.ts +0 -3
  235. package/dist/src/commands/export-schema-runner.d.ts.map +0 -1
  236. package/dist/src/commands/export-schema-runner.js +0 -53
  237. package/dist/src/commands/export-schema-runner.js.map +0 -1
  238. package/eslint.config.ts +0 -12
  239. package/src/commands/export-schema-runner.ts +0 -74
@@ -1,6 +1,7 @@
1
1
  // integration-helper.ts - Add this to your flow package
2
- import { Integration } from './types';
2
+
3
3
  import createDebug from 'debug';
4
+ import type { Integration } from './types';
4
5
 
5
6
  const debug = createDebug('auto:flow:integrations');
6
7
  if ('color' in debug && typeof debug === 'object') {
@@ -9,7 +9,7 @@ export function dirname(p: string) {
9
9
  export function join(a: string, b: string) {
10
10
  const aa = toPosix(a).replace(/\/+$/, '');
11
11
  const bb = toPosix(b).replace(/^\/+/, '');
12
- return (aa ? aa + '/' : '/') + bb;
12
+ return (aa ? `${aa}/` : '/') + bb;
13
13
  }
14
14
 
15
15
  export function normalize(path: string): string {
@@ -23,7 +23,7 @@ export function normalize(path: string): string {
23
23
  }
24
24
  out.push(part);
25
25
  }
26
- return '/' + out.join('/');
26
+ return `/${out.join('/')}`;
27
27
  }
28
28
 
29
29
  export const CANDIDATE_EXTS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
@@ -1,25 +1,30 @@
1
- import createDebug from 'debug';
2
- import type { Graph } from './types';
3
1
  import type { IFileStore } from '@auto-engineer/file-store';
2
+ import createDebug from 'debug';
3
+ import { integrationExportRegistry } from '../integration-export-registry';
4
+ import { toPosix } from './fs-path';
5
+ import { resolveSpecifier } from './resolver';
4
6
  import {
7
+ parseGivenTypeArguments,
5
8
  parseImports,
6
- parseTypeDefinitions,
7
9
  parseIntegrationExports,
8
10
  parseIntegrationImports,
9
- parseGivenTypeArguments,
10
- parseWhenTypeArguments,
11
11
  parseThenTypeArguments,
12
+ parseTypeDefinitions,
13
+ parseWhenTypeArguments,
12
14
  patchImportMeta,
15
+ type TypeInfo,
13
16
  transpileToCjs,
14
- TypeInfo,
15
17
  } from './ts-utils';
16
- import { toPosix } from './fs-path';
17
- import { resolveSpecifier } from './resolver';
18
- import { integrationExportRegistry } from '../integration-export-registry';
18
+ import type { Graph } from './types';
19
19
  import { createVfsCompilerHost } from './vfs-compiler-host';
20
20
 
21
21
  const debug = createDebug('auto:flow:graph');
22
22
 
23
+ function interopDefault<T>(mod: unknown): T {
24
+ const m = mod as Record<string, unknown> | null;
25
+ return m !== null && typeof m === 'object' && 'default' in m ? ((m.default as T) ?? (mod as T)) : (mod as T);
26
+ }
27
+
23
28
  async function collectAllTypings(
24
29
  vfs: IFileStore,
25
30
  externalPkgs: Set<string>,
@@ -166,7 +171,7 @@ export async function buildGraph(
166
171
  importMap: Record<string, unknown>,
167
172
  rootDir: string,
168
173
  ): Promise<BuildGraphResult> {
169
- const ts = await import('typescript');
174
+ const ts = interopDefault<typeof import('typescript')>(await import('typescript'));
170
175
 
171
176
  const graph: Graph = new Map();
172
177
  const visited = new Set<string>();
@@ -1,12 +1,12 @@
1
1
  import createDebug from 'debug';
2
- import type { ExecuteOptions } from './types';
3
- import { registry } from '../narrative-registry';
4
- import { integrationRegistry } from '../integration-registry';
5
2
  import { integrationExportRegistry } from '../integration-export-registry';
6
- import { buildGraph, type BuildGraphResult } from './graph';
7
- import { runGraph } from './runtime-cjs';
8
- import { createEnhancedImportMap } from './importmap';
3
+ import { integrationRegistry } from '../integration-registry';
9
4
  import { setGivenTypesByFile } from '../narrative-context';
5
+ import { registry } from '../narrative-registry';
6
+ import { type BuildGraphResult, buildGraph } from './graph';
7
+ import { createEnhancedImportMap } from './importmap';
8
+ import { runGraph } from './runtime-cjs';
9
+ import type { ExecuteOptions } from './types';
10
10
 
11
11
  const debug = createDebug('auto:flow:ast-loader:index');
12
12
 
@@ -42,7 +42,7 @@ export async function executeAST(
42
42
  // auto-map any externals we can load
43
43
  const autoMapped: Record<string, unknown> = {};
44
44
  for (const spec of first.externals) {
45
- if (Object.prototype.hasOwnProperty.call(enhanced, spec)) continue;
45
+ if (Object.hasOwn(enhanced, spec)) continue;
46
46
  try {
47
47
  const mod = (await import(spec)) as Record<string, unknown>;
48
48
  autoMapped[spec] = interopDefault(mod); // <<< IMPORTANT
@@ -8,7 +8,7 @@ export async function resolveSpecifier(
8
8
  parent: string,
9
9
  importMap: Record<string, unknown>,
10
10
  ): Promise<Resolved> {
11
- if (Object.prototype.hasOwnProperty.call(importMap, spec)) {
11
+ if (Object.hasOwn(importMap, spec)) {
12
12
  return { kind: 'mapped', value: importMap[spec] };
13
13
  }
14
14
  if (spec.startsWith('./') || spec.startsWith('../')) {
@@ -1,9 +1,9 @@
1
1
  import createDebug from 'debug';
2
- import type { Graph } from './types';
3
- import { dirname, toPosix } from './fs-path';
4
2
  import { integrationRegistry } from '../integration-registry';
5
3
  import { registry } from '../narrative-registry';
6
4
  import type { Integration } from '../types';
5
+ import { dirname, toPosix } from './fs-path';
6
+ import type { Graph } from './types';
7
7
 
8
8
  const debug = createDebug('auto:flow:runtime');
9
9
  const dImp = createDebug('auto:flow:runtime:require');
@@ -119,7 +119,7 @@ export function runGraph(entryFiles: string[], graph: Graph): void {
119
119
  };
120
120
 
121
121
  try {
122
- const codeWithShim = 'var r = require; var __require = require;\n' + mod.js;
122
+ const codeWithShim = `var r = require; var __require = require;\n${mod.js}`;
123
123
  // eslint-disable-next-line @typescript-eslint/no-implied-eval
124
124
  const fn = new Function('require', 'module', 'exports', '__filename', '__dirname', codeWithShim) as (
125
125
  req: (s: string) => unknown,
@@ -1,6 +1,6 @@
1
1
  import type { IFileStore } from '@auto-engineer/file-store';
2
- import { CANDIDATE_EXTS, dirname, join, normalize } from './fs-path';
3
2
  import createDebug from 'debug';
3
+ import { CANDIDATE_EXTS, dirname, join, normalize } from './fs-path';
4
4
 
5
5
  const debug = createDebug('auto:flow:when-types');
6
6
 
@@ -16,7 +16,7 @@ export async function resolveRelative(vfs: IFileStore, spec: string, parent: str
16
16
  if (await fileExists(vfs, raw)) return raw;
17
17
  for (const ext of CANDIDATE_EXTS) if (await fileExists(vfs, raw + ext)) return raw + ext;
18
18
  for (const ext of CANDIDATE_EXTS) {
19
- const idx = normalize(join(raw, 'index' + ext));
19
+ const idx = normalize(join(raw, `index${ext}`));
20
20
  if (await fileExists(vfs, idx)) return idx;
21
21
  }
22
22
  return null;
@@ -28,7 +28,7 @@ export async function resolveAbsolute(vfs: IFileStore, spec: string): Promise<st
28
28
  if (await fileExists(vfs, raw)) return raw;
29
29
  for (const ext of CANDIDATE_EXTS) if (await fileExists(vfs, raw + ext)) return raw + ext;
30
30
  for (const ext of CANDIDATE_EXTS) {
31
- const idx = normalize(join(raw, 'index' + ext));
31
+ const idx = normalize(join(raw, `index${ext}`));
32
32
  if (await fileExists(vfs, idx)) return idx;
33
33
  }
34
34
  return null;
@@ -36,7 +36,7 @@ export async function resolveAbsolute(vfs: IFileStore, spec: string): Promise<st
36
36
 
37
37
  /** Shim import.meta in user code (we only provide a url). */
38
38
  export function patchImportMeta(src: string, absPath: string): string {
39
- return src.replace(/\bimport\.meta\b/g, `({ url: ${JSON.stringify('file://' + absPath)} })`);
39
+ return src.replace(/\bimport\.meta\b/g, `({ url: ${JSON.stringify(`file://${absPath}`)} })`);
40
40
  }
41
41
 
42
42
  export function parseImports(ts: typeof import('typescript'), fileName: string, source: string): string[] {
@@ -546,7 +546,7 @@ function findTypeInfo(
546
546
  }
547
547
  }
548
548
 
549
- return ti && ti.classification ? ti : null;
549
+ return ti?.classification ? ti : null;
550
550
  }
551
551
 
552
552
  function createGivenTypeInfo(
@@ -1,7 +1,7 @@
1
- import { describe, it, expect } from 'vitest';
1
+ import { describe, expect, it } from 'vitest';
2
+ import type { Model } from './index';
2
3
  import schema from './samples/seasonal-assistant.schema.json';
3
4
  import { modelToNarrative } from './transformers/model-to-narrative';
4
- import { Model } from './index';
5
5
 
6
6
  describe('modelToNarrative', () => {
7
7
  it('should create a full flow DSL from a model', async () => {
@@ -12,7 +12,6 @@ describe('modelToNarrative', () => {
12
12
  data,
13
13
  describe,
14
14
  example,
15
- given,
16
15
  gql,
17
16
  it,
18
17
  narrative,
@@ -22,8 +21,6 @@ describe('modelToNarrative', () => {
22
21
  sink,
23
22
  source,
24
23
  specs,
25
- then,
26
- when,
27
24
  } from '@auto-engineer/narrative';
28
25
  import type { Command, Event, State } from '@auto-engineer/narrative';
29
26
  import { AI, ProductCatalog } from '../server/src/integrations';
@@ -120,36 +117,34 @@ narrative('Seasonal Assistant', () => {
120
117
  data([sink().event('ShoppingCriteriaEntered').toStream('shopping-session-\${sessionId}')]);
121
118
  specs('When shopper submits criteria, a shopping session is started', () => {
122
119
  rule('Valid criteria should start a shopping session', () => {
123
- example('User submits shopping criteria for children', () => {
124
- when<EnterShoppingCriteria>({
120
+ example('User submits shopping criteria for children')
121
+ .when<EnterShoppingCriteria>({
125
122
  sessionId: 'shopper-123',
126
123
  criteria:
127
124
  'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
128
- });
129
- then<ShoppingCriteriaEntered>({
125
+ })
126
+ .then<ShoppingCriteriaEntered>({
130
127
  sessionId: 'shopper-123',
131
128
  criteria:
132
129
  'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
133
130
  });
134
- });
135
131
  });
136
132
  });
137
133
  });
138
134
  react('creates a chat session').server(() => {
139
135
  specs('When shopping criteria are entered, request wishlist creation', () => {
140
136
  rule('Shopping criteria should trigger item suggestion', () => {
141
- example('Criteria entered triggers wishlist creation', () => {
142
- when<ShoppingCriteriaEntered>({
137
+ example('Criteria entered triggers wishlist creation')
138
+ .when<ShoppingCriteriaEntered>({
143
139
  sessionId: 'session-abc',
144
140
  criteria:
145
141
  'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
146
- });
147
- then<SuggestShoppingItems>({
142
+ })
143
+ .then<SuggestShoppingItems>({
148
144
  sessionId: 'session-abc',
149
145
  prompt:
150
146
  'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
151
147
  });
152
- });
153
148
  });
154
149
  });
155
150
  });
@@ -166,8 +161,8 @@ narrative('Seasonal Assistant', () => {
166
161
  ]);
167
162
  specs('When chat is triggered, AI suggests items based on product catalog', () => {
168
163
  rule('AI should suggest relevant items from available products', () => {
169
- example('Product catalog with matching items generates suggestions', () => {
170
- given<Products>({
164
+ example('Product catalog with matching items generates suggestions')
165
+ .given<Products>({
171
166
  products: [
172
167
  {
173
168
  productId: 'prod-soccer-ball',
@@ -202,13 +197,13 @@ narrative('Seasonal Assistant', () => {
202
197
  imageUrl: 'https://example.com/mtg-starter.jpg',
203
198
  },
204
199
  ],
205
- });
206
- when<SuggestShoppingItems>({
200
+ })
201
+ .when<SuggestShoppingItems>({
207
202
  sessionId: 'session-abc',
208
203
  prompt:
209
204
  'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
210
- });
211
- then<ShoppingItemsSuggested>({
205
+ })
206
+ .then<ShoppingItemsSuggested>({
212
207
  sessionId: 'session-abc',
213
208
  suggestedItems: [
214
209
  {
@@ -237,7 +232,6 @@ narrative('Seasonal Assistant', () => {
237
232
  },
238
233
  ],
239
234
  });
240
- });
241
235
  });
242
236
  });
243
237
  });
@@ -266,8 +260,8 @@ narrative('Seasonal Assistant', () => {
266
260
  data([source().state('SuggestedItems').fromProjection('SuggestedItemsProjection', 'sessionId')]);
267
261
  specs('Suggested items are available for viewing', () => {
268
262
  rule('Items should be available for viewing after suggestion', () => {
269
- example('Item becomes available after AI suggestion event', () => {
270
- when<ShoppingItemsSuggested>({
263
+ example('Item becomes available after AI suggestion event')
264
+ .when<ShoppingItemsSuggested>({
271
265
  sessionId: 'session-abc',
272
266
  suggestedItems: [
273
267
  {
@@ -295,8 +289,8 @@ narrative('Seasonal Assistant', () => {
295
289
  reason: 'Ideal starter set for Magic the Gathering enthusiasts',
296
290
  },
297
291
  ],
298
- });
299
- then<SuggestedItems>({
292
+ })
293
+ .then<SuggestedItems>({
300
294
  sessionId: 'session-abc',
301
295
  items: [
302
296
  {
@@ -325,7 +319,6 @@ narrative('Seasonal Assistant', () => {
325
319
  },
326
320
  ],
327
321
  });
328
- });
329
322
  });
330
323
  });
331
324
  });
@@ -341,8 +334,8 @@ narrative('Seasonal Assistant', () => {
341
334
  data([sink().event('ItemsAddedToCart').toStream('shopping-session-\${sessionId}')]);
342
335
  specs('When shopper accepts items, they are added to cart', () => {
343
336
  rule('Accepted items should be added to the shopping cart', () => {
344
- example('User selects all suggested items for cart', () => {
345
- when<AddItemsToCart>({
337
+ example('User selects all suggested items for cart')
338
+ .when<AddItemsToCart>({
346
339
  sessionId: 'session-abc',
347
340
  items: [
348
341
  { productId: 'prod-soccer-ball', quantity: 1 },
@@ -350,8 +343,8 @@ narrative('Seasonal Assistant', () => {
350
343
  { productId: 'prod-laptop-bag', quantity: 1 },
351
344
  { productId: 'prod-mtg-starter', quantity: 1 },
352
345
  ],
353
- });
354
- then<ItemsAddedToCart>({
346
+ })
347
+ .then<ItemsAddedToCart>({
355
348
  sessionId: 'session-abc',
356
349
  items: [
357
350
  { productId: 'prod-soccer-ball', quantity: 1 },
@@ -360,7 +353,6 @@ narrative('Seasonal Assistant', () => {
360
353
  { productId: 'prod-mtg-starter', quantity: 1 },
361
354
  ],
362
355
  });
363
- });
364
356
  });
365
357
  });
366
358
  });
@@ -613,8 +605,7 @@ narrative('Test Flow with IDs', 'FLOW-123', () => {
613
605
 
614
606
  const code = await modelToNarrative(modelWithRuleIds);
615
607
 
616
- expect(code)
617
- .toEqual(`import { command, example, narrative, rule, specs, then, when } from '@auto-engineer/narrative';
608
+ expect(code).toEqual(`import { command, example, narrative, rule, specs } from '@auto-engineer/narrative';
618
609
  import type { Command, Event } from '@auto-engineer/narrative';
619
610
  type ProcessCommand = Command<
620
611
  'ProcessCommand',
@@ -634,10 +625,9 @@ narrative('Test Flow with Rule IDs', 'FLOW-456', () => {
634
625
  command('process command', 'SLICE-789').server(() => {
635
626
  specs('Command Processing', () => {
636
627
  rule('Valid commands should be processed', 'RULE-ABC', () => {
637
- example('User submits valid command', () => {
638
- when<ProcessCommand>({ id: 'cmd-123', action: 'create' });
639
- then<CommandProcessed>({ id: 'cmd-123', status: 'success' });
640
- });
628
+ example('User submits valid command')
629
+ .when<ProcessCommand>({ id: 'cmd-123', action: 'create' })
630
+ .then<CommandProcessed>({ id: 'cmd-123', status: 'success' });
641
631
  });
642
632
  });
643
633
  });
@@ -945,7 +935,6 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
945
935
  describe,
946
936
  example,
947
937
  experience,
948
- given,
949
938
  gql,
950
939
  it,
951
940
  narrative,
@@ -953,8 +942,6 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
953
942
  rule,
954
943
  source,
955
944
  specs,
956
- then,
957
- when,
958
945
  } from '@auto-engineer/narrative';
959
946
  import type { Event, State } from '@auto-engineer/narrative';
960
947
  type QuestionnaireLinkSent = Event<
@@ -1023,21 +1010,21 @@ narrative('Questionnaires', 'Q9m2Kp4Lx', () => {
1023
1010
  data([source().state('QuestionnaireProgress').fromProjection('Questionnaires', 'questionnaire-participantId')]);
1024
1011
  specs(() => {
1025
1012
  rule('questionnaires show current progress', 'r1A3Bp9W', () => {
1026
- example('a question has already been answered', () => {
1027
- given<QuestionnaireLinkSent>({
1013
+ example('a question has already been answered')
1014
+ .given<QuestionnaireLinkSent>({
1028
1015
  questionnaireId: 'q-001',
1029
1016
  participantId: 'participant-abc',
1030
1017
  link: 'https://app.example.com/q/q-001?participant=participant-abc',
1031
1018
  sentAt: new Date('2030-01-01T09:00:00.000Z'),
1032
- });
1033
- when<QuestionAnswered>({
1019
+ })
1020
+ .when<QuestionAnswered>({
1034
1021
  questionnaireId: 'q-001',
1035
1022
  participantId: 'participant-abc',
1036
1023
  questionId: 'q1',
1037
1024
  answer: 'Yes',
1038
1025
  savedAt: new Date('2030-01-01T09:05:00.000Z'),
1039
- });
1040
- then<QuestionnaireProgress>({
1026
+ })
1027
+ .then<QuestionnaireProgress>({
1041
1028
  questionnaireId: 'q-001',
1042
1029
  participantId: 'participant-abc',
1043
1030
  status: 'in_progress',
@@ -1045,7 +1032,6 @@ narrative('Questionnaires', 'Q9m2Kp4Lx', () => {
1045
1032
  remainingQuestions: ['q2', 'q3'],
1046
1033
  answers: [{ questionId: 'q1', value: 'Yes' }],
1047
1034
  });
1048
- });
1049
1035
  });
1050
1036
  });
1051
1037
  });
@@ -1184,8 +1170,7 @@ narrative('Questionnaires', 'Q9m2Kp4Lx', () => {
1184
1170
 
1185
1171
  const code = await modelToNarrative(modelWithDuplicateRules);
1186
1172
 
1187
- expect(code)
1188
- .toEqual(`import { example, given, narrative, query, rule, specs, then, when } from '@auto-engineer/narrative';
1173
+ expect(code).toEqual(`import { example, narrative, query, rule, specs } from '@auto-engineer/narrative';
1189
1174
  import type { Event, State } from '@auto-engineer/narrative';
1190
1175
  type QuestionnaireLinkSent = Event<
1191
1176
  'QuestionnaireLinkSent',
@@ -1213,15 +1198,13 @@ narrative('Test Flow', 'TEST-FLOW', () => {
1213
1198
  query('test slice', 'TEST-SLICE').server(() => {
1214
1199
  specs('Test Rules', () => {
1215
1200
  rule('questionnaires show current progress', 'r1A3Bp9W', () => {
1216
- example('a question has already been answered', () => {
1217
- given<QuestionnaireLinkSent>({ questionnaireId: 'q-001', participantId: 'participant-abc' });
1218
- when<QuestionAnswered>({ questionnaireId: 'q-001', questionId: 'q1', answer: 'Yes' });
1219
- then<QuestionnaireProgress>({ questionnaireId: 'q-001', status: 'in_progress' });
1220
- });
1221
- example('no questions have been answered yet', () => {
1222
- given<QuestionnaireLinkSent>({ questionnaireId: 'q-001', participantId: 'participant-abc' });
1223
- then<QuestionnaireProgress>({ questionnaireId: 'q-001', status: 'in_progress' });
1224
- });
1201
+ example('a question has already been answered')
1202
+ .given<QuestionnaireLinkSent>({ questionnaireId: 'q-001', participantId: 'participant-abc' })
1203
+ .when<QuestionAnswered>({ questionnaireId: 'q-001', questionId: 'q1', answer: 'Yes' })
1204
+ .then<QuestionnaireProgress>({ questionnaireId: 'q-001', status: 'in_progress' });
1205
+ example('no questions have been answered yet')
1206
+ .given<QuestionnaireLinkSent>({ questionnaireId: 'q-001', participantId: 'participant-abc' })
1207
+ .then<QuestionnaireProgress>({ questionnaireId: 'q-001', status: 'in_progress' });
1225
1208
  });
1226
1209
  });
1227
1210
  });
@@ -1391,8 +1374,7 @@ narrative('Test Flow', 'TEST-FLOW', () => {
1391
1374
 
1392
1375
  const code = await modelToNarrative(modelWithMultiGiven);
1393
1376
 
1394
- expect(code)
1395
- .toEqual(`import { and, example, given, narrative, query, rule, specs, then, when } from '@auto-engineer/narrative';
1377
+ expect(code).toEqual(`import { example, narrative, query, rule, specs } from '@auto-engineer/narrative';
1396
1378
  import type { Event, State } from '@auto-engineer/narrative';
1397
1379
  type QuestionnaireConfig = State<
1398
1380
  'QuestionnaireConfig',
@@ -1438,36 +1420,36 @@ narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
1438
1420
  query('multi given slice', 'MULTI-SLICE').server(() => {
1439
1421
  specs('Multi Given Rules', () => {
1440
1422
  rule('all questions have been answered', 'MultiGiven', () => {
1441
- example('questionnaire with multiple events', () => {
1442
- given<QuestionnaireConfig>({ questionnaireId: 'q-001', numberOfQuestions: 3 });
1443
- and<QuestionnaireLinkSent>({
1423
+ example('questionnaire with multiple events')
1424
+ .given<QuestionnaireConfig>({ questionnaireId: 'q-001', numberOfQuestions: 3 })
1425
+ .and<QuestionnaireLinkSent>({
1444
1426
  questionnaireId: 'q-001',
1445
1427
  participantId: 'participant-abc',
1446
1428
  link: 'https://example.com/q/q-001',
1447
1429
  sentAt: new Date('2030-01-01T09:00:00.000Z'),
1448
- });
1449
- and<QuestionAnswered>({
1430
+ })
1431
+ .and<QuestionAnswered>({
1450
1432
  questionnaireId: 'q-001',
1451
1433
  participantId: 'participant-abc',
1452
1434
  questionId: 'q1',
1453
1435
  answer: 'Yes',
1454
1436
  savedAt: new Date('2030-01-01T09:05:00.000Z'),
1455
- });
1456
- and<QuestionAnswered>({
1437
+ })
1438
+ .and<QuestionAnswered>({
1457
1439
  questionnaireId: 'q-001',
1458
1440
  participantId: 'participant-abc',
1459
1441
  questionId: 'q2',
1460
1442
  answer: 'No',
1461
1443
  savedAt: new Date('2030-01-01T09:10:00.000Z'),
1462
- });
1463
- when<QuestionAnswered>({
1444
+ })
1445
+ .when<QuestionAnswered>({
1464
1446
  questionnaireId: 'q-001',
1465
1447
  participantId: 'participant-abc',
1466
1448
  questionId: 'q3',
1467
1449
  answer: 'Maybe',
1468
1450
  savedAt: new Date('2030-01-01T09:15:00.000Z'),
1469
- });
1470
- then<QuestionnaireProgress>({
1451
+ })
1452
+ .then<QuestionnaireProgress>({
1471
1453
  questionnaireId: 'q-001',
1472
1454
  participantId: 'participant-abc',
1473
1455
  status: 'ready_to_submit',
@@ -1478,7 +1460,6 @@ narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
1478
1460
  { questionId: 'q2', value: 'No' },
1479
1461
  ],
1480
1462
  });
1481
- });
1482
1463
  });
1483
1464
  });
1484
1465
  });
@@ -1604,8 +1585,9 @@ narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
1604
1585
 
1605
1586
  const code = await modelToNarrative(modelWithReferencedStates);
1606
1587
 
1607
- expect(code)
1608
- .toEqual(`import { data, example, given, narrative, query, rule, source, specs, then } from '@auto-engineer/narrative';
1588
+ expect(
1589
+ code,
1590
+ ).toEqual(`import { data, example, narrative, query, rule, source, specs } from '@auto-engineer/narrative';
1609
1591
  import type { State } from '@auto-engineer/narrative';
1610
1592
  type QuestionnaireProgress = State<
1611
1593
  'QuestionnaireProgress',
@@ -1632,19 +1614,18 @@ narrative('Referenced States Flow', 'REF-STATES', () => {
1632
1614
  ]);
1633
1615
  specs('Database State Rules', () => {
1634
1616
  rule('questionnaire config is available when referenced', 'RefState', () => {
1635
- example('config from database is accessible', () => {
1636
- given<QuestionnaireConfig>({
1617
+ example('config from database is accessible')
1618
+ .given<QuestionnaireConfig>({
1637
1619
  questionnaireId: 'q-001',
1638
1620
  numberOfQuestions: 5,
1639
1621
  title: 'Customer Satisfaction Survey',
1640
- });
1641
- then<QuestionnaireProgress>({
1622
+ })
1623
+ .then<QuestionnaireProgress>({
1642
1624
  questionnaireId: 'q-001',
1643
1625
  participantId: 'participant-abc',
1644
1626
  status: 'in_progress',
1645
1627
  totalQuestions: 5,
1646
1628
  });
1647
- });
1648
1629
  });
1649
1630
  });
1650
1631
  });
@@ -1758,8 +1739,7 @@ narrative('Referenced States Flow', 'REF-STATES', () => {
1758
1739
 
1759
1740
  const code = await modelToNarrative(modelWithDateFields);
1760
1741
 
1761
- expect(code)
1762
- .toEqual(`import { example, given, narrative, query, rule, specs, then, when } from '@auto-engineer/narrative';
1742
+ expect(code).toEqual(`import { example, narrative, query, rule, specs } from '@auto-engineer/narrative';
1763
1743
  import type { Event, State } from '@auto-engineer/narrative';
1764
1744
  type TimestampedEvent = Event<
1765
1745
  'TimestampedEvent',
@@ -1789,21 +1769,20 @@ narrative('Date Handling Flow', 'DATE-FLOW', () => {
1789
1769
  query('date handling slice', 'DATE-SLICE').server(() => {
1790
1770
  specs('Date Field Rules', () => {
1791
1771
  rule('handles Date fields correctly', 'DateRule', () => {
1792
- example('event with Date fields', () => {
1793
- given<TimestampedEvent>({
1772
+ example('event with Date fields')
1773
+ .given<TimestampedEvent>({
1794
1774
  id: 'event-123',
1795
1775
  sentAt: new Date('2030-01-01T09:00:00.000Z'),
1796
1776
  savedAt: new Date('2030-01-01T09:05:00.000Z'),
1797
1777
  attemptedAt: new Date('2030-01-01T09:10:00.000Z'),
1798
1778
  submittedAt: new Date('2030-01-01T09:15:00.000Z'),
1799
- });
1800
- when<ProcessEvent>({ processedAt: new Date('2030-01-01T10:00:00.000Z') });
1801
- then<ProcessState>({
1779
+ })
1780
+ .when<ProcessEvent>({ processedAt: new Date('2030-01-01T10:00:00.000Z') })
1781
+ .then<ProcessState>({
1802
1782
  id: 'state-123',
1803
1783
  completedAt: new Date('2030-01-01T11:00:00.000Z'),
1804
1784
  status: 'completed',
1805
1785
  });
1806
- });
1807
1786
  });
1808
1787
  });
1809
1788
  });
@@ -2025,8 +2004,7 @@ narrative('Response Analytics', () => {
2025
2004
 
2026
2005
  const code = await modelToNarrative(modelWithEmptyWhen);
2027
2006
 
2028
- expect(code)
2029
- .toEqual(`import { and, example, given, narrative, query, rule, specs, then } from '@auto-engineer/narrative';
2007
+ expect(code).toEqual(`import { example, narrative, query, rule, specs } from '@auto-engineer/narrative';
2030
2008
  import type { Event, State } from '@auto-engineer/narrative';
2031
2009
  type TodoAdded = Event<
2032
2010
  'TodoAdded',
@@ -2066,22 +2044,22 @@ narrative('Todo List Summary', 'TODO-001', () => {
2066
2044
  query('views completion summary', 'SUMMARY-001').server(() => {
2067
2045
  specs('Summary Statistics', () => {
2068
2046
  rule('summary shows overall todo list statistics', 'RULE-SUMMARY', () => {
2069
- example('calculates summary from multiple todos', () => {
2070
- given<TodoAdded>({
2047
+ example('calculates summary from multiple todos')
2048
+ .given<TodoAdded>({
2071
2049
  todoId: 'todo-001',
2072
2050
  description: 'Buy groceries',
2073
2051
  status: 'pending',
2074
2052
  addedAt: new Date('2030-01-01T09:00:00.000Z'),
2075
- });
2076
- and<TodoAdded>({
2053
+ })
2054
+ .and<TodoAdded>({
2077
2055
  todoId: 'todo-002',
2078
2056
  description: 'Write report',
2079
2057
  status: 'pending',
2080
2058
  addedAt: new Date('2030-01-01T09:10:00.000Z'),
2081
- });
2082
- and<TodoMarkedInProgress>({ todoId: 'todo-001', markedAt: new Date('2030-01-01T10:00:00.000Z') });
2083
- and<TodoMarkedComplete>({ todoId: 'todo-002', completedAt: new Date('2030-01-01T11:00:00.000Z') });
2084
- then<TodoListSummary>({
2059
+ })
2060
+ .and<TodoMarkedInProgress>({ todoId: 'todo-001', markedAt: new Date('2030-01-01T10:00:00.000Z') })
2061
+ .and<TodoMarkedComplete>({ todoId: 'todo-002', completedAt: new Date('2030-01-01T11:00:00.000Z') })
2062
+ .then<TodoListSummary>({
2085
2063
  summaryId: 'main-summary',
2086
2064
  totalTodos: 2,
2087
2065
  pendingCount: 0,
@@ -2089,7 +2067,6 @@ narrative('Todo List Summary', 'TODO-001', () => {
2089
2067
  completedCount: 1,
2090
2068
  completionPercentage: 50,
2091
2069
  });
2092
- });
2093
2070
  });
2094
2071
  });
2095
2072
  });