@nanobpm/urban 0.21.0 → 0.23.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 (97) hide show
  1. package/README.md +35 -0
  2. package/dist/cli.d.ts +26 -0
  3. package/dist/cli.js +80 -16
  4. package/dist/runtime/adapters/deno.js +19 -3
  5. package/dist/runtime/adapters/detect.js +2 -2
  6. package/dist/runtime/adapters/globals.d.ts +19 -0
  7. package/dist/runtime/adapters/globals.js +9 -0
  8. package/dist/runtime/adapters/node.js +25 -5
  9. package/dist/runtime/core/context.d.ts +4 -0
  10. package/dist/runtime/core/guards.d.ts +2 -0
  11. package/dist/runtime/core/guards.js +10 -0
  12. package/dist/runtime/core/host.js +5 -4
  13. package/dist/runtime/core/manifest.d.ts +8 -0
  14. package/dist/runtime/core/manifest.js +0 -1
  15. package/dist/runtime/core/modules/actions.js +9 -5
  16. package/dist/runtime/core/modules/connectors.js +6 -4
  17. package/dist/runtime/core/modules/dataops.d.ts +36 -0
  18. package/dist/runtime/core/modules/dataops.js +231 -0
  19. package/dist/runtime/core/modules/datasource.d.ts +51 -1
  20. package/dist/runtime/core/modules/datasource.js +98 -21
  21. package/dist/runtime/core/modules/deploy.d.ts +3 -1
  22. package/dist/runtime/core/modules/deploy.js +29 -7
  23. package/dist/runtime/core/modules/gateway.d.ts +1 -1
  24. package/dist/runtime/core/modules/gateway.js +16 -17
  25. package/dist/runtime/core/modules/llm.js +9 -7
  26. package/dist/runtime/core/modules/pages.js +118 -16
  27. package/dist/runtime/core/modules/security.js +5 -5
  28. package/dist/runtime/core/modules/templates.d.ts +18 -0
  29. package/dist/runtime/core/modules/templates.js +133 -0
  30. package/dist/runtime/core/modules/triggers.js +14 -5
  31. package/dist/runtime/core/modules/workers.js +15 -9
  32. package/dist/runtime/core/runtime.d.ts +5 -0
  33. package/dist/runtime/core/runtime.js +5 -5
  34. package/dist/runtime/core/validate.d.ts +2 -1
  35. package/dist/runtime/core/validate.js +38 -28
  36. package/dist/runtime/devserver.js +2 -1
  37. package/dist/runtime/engine/nanosdk.d.ts +1 -1
  38. package/dist/runtime/engine/nanosdk.js +15 -9
  39. package/dist/runtime/index.d.ts +5 -0
  40. package/dist/runtime/index.js +4 -0
  41. package/dist/runtime/run.js +10 -7
  42. package/dist/toolkit/addConnector.js +4 -3
  43. package/dist/toolkit/fsio.js +2 -1
  44. package/dist/toolkit/models.js +3 -5
  45. package/package.json +1 -1
  46. package/src/cli.test.ts +44 -0
  47. package/src/cli.ts +82 -16
  48. package/src/runtime/adapters/deno.ts +23 -3
  49. package/src/runtime/adapters/detect.ts +2 -2
  50. package/src/runtime/adapters/globals.ts +27 -0
  51. package/src/runtime/adapters/node.ts +27 -4
  52. package/src/runtime/connector-worker-sdk.test.ts +2 -1
  53. package/src/runtime/core/context.ts +4 -0
  54. package/src/runtime/core/guards.ts +10 -0
  55. package/src/runtime/core/host.ts +4 -4
  56. package/src/runtime/core/manifest.ts +19 -5
  57. package/src/runtime/core/modules/actions.test.ts +82 -31
  58. package/src/runtime/core/modules/actions.ts +11 -7
  59. package/src/runtime/core/modules/connectors.test.ts +29 -8
  60. package/src/runtime/core/modules/connectors.ts +6 -4
  61. package/src/runtime/core/modules/dataops.test.ts +306 -0
  62. package/src/runtime/core/modules/dataops.ts +292 -0
  63. package/src/runtime/core/modules/datasource.migrations.test.ts +12 -3
  64. package/src/runtime/core/modules/datasource.test.ts +129 -0
  65. package/src/runtime/core/modules/datasource.ts +105 -23
  66. package/src/runtime/core/modules/deploy.test.ts +258 -0
  67. package/src/runtime/core/modules/deploy.ts +29 -7
  68. package/src/runtime/core/modules/gateway.test.ts +5 -4
  69. package/src/runtime/core/modules/gateway.ts +29 -30
  70. package/src/runtime/core/modules/llm.test.ts +10 -12
  71. package/src/runtime/core/modules/llm.ts +11 -9
  72. package/src/runtime/core/modules/pages.test.ts +53 -2
  73. package/src/runtime/core/modules/pages.ts +121 -23
  74. package/src/runtime/core/modules/security.ts +5 -13
  75. package/src/runtime/core/modules/surfaces.test.ts +53 -10
  76. package/src/runtime/core/modules/templates.ts +153 -0
  77. package/src/runtime/core/modules/triggers.test.ts +51 -19
  78. package/src/runtime/core/modules/triggers.ts +14 -6
  79. package/src/runtime/core/modules/workers.test.ts +43 -20
  80. package/src/runtime/core/modules/workers.ts +18 -10
  81. package/src/runtime/core/runtime.test.ts +23 -10
  82. package/src/runtime/core/runtime.ts +15 -2
  83. package/src/runtime/core/validate.ts +43 -32
  84. package/src/runtime/devserver.test.ts +18 -5
  85. package/src/runtime/devserver.ts +2 -1
  86. package/src/runtime/engine/nanosdk.test.ts +16 -11
  87. package/src/runtime/engine/nanosdk.ts +22 -15
  88. package/src/runtime/index.ts +7 -0
  89. package/src/runtime/run.ts +10 -10
  90. package/src/toolkit/addConnector.ts +6 -5
  91. package/src/toolkit/derivers/messages.test.ts +4 -2
  92. package/src/toolkit/derivers/worker-io.test.ts +4 -2
  93. package/src/toolkit/fsio.ts +2 -1
  94. package/src/toolkit/gen.ts +4 -4
  95. package/src/toolkit/models.test.ts +1 -1
  96. package/src/toolkit/models.ts +3 -4
  97. package/src/toolkit/scaffold.ts +1 -1
@@ -13,6 +13,7 @@
13
13
  // unit-testable.
14
14
 
15
15
  import type { GenIO } from "./gen.ts";
16
+ import { errorMessage, isRecord } from "../runtime/core/guards.ts";
16
17
 
17
18
  /** A config field a pack declares (subset of ext-types `ConfigField`). */
18
19
  interface PackConfigField {
@@ -90,9 +91,9 @@ export async function addConnector(opts: AddConnectorOptions): Promise<AddConnec
90
91
  }
91
92
  let pack: PackManifest;
92
93
  try {
93
- pack = JSON.parse(await io.readText(packManifestPath)) as PackManifest;
94
+ pack = JSON.parse(await io.readText(packManifestPath));
94
95
  } catch (err) {
95
- throw new Error(`failed to parse ${packManifestPath}: ${(err as Error).message}`);
96
+ throw new Error(`failed to parse ${packManifestPath}: ${errorMessage(err)}`);
96
97
  }
97
98
  if (typeof pack.id !== "string" || !pack.id) {
98
99
  throw new Error(`${packManifestPath} has no string "id" (a pack must declare its id).`);
@@ -123,7 +124,7 @@ export async function addConnector(opts: AddConnectorOptions): Promise<AddConnec
123
124
  try {
124
125
  app = JSON.parse(await io.readText(appManifestPath));
125
126
  } catch (err) {
126
- throw new Error(`failed to parse ${appManifestPath}: ${(err as Error).message}`);
127
+ throw new Error(`failed to parse ${appManifestPath}: ${errorMessage(err)}`);
127
128
  }
128
129
  if (app === null || typeof app !== "object" || Array.isArray(app)) {
129
130
  throw new Error(`${appManifestPath} is not a JSON object.`);
@@ -168,10 +169,10 @@ export async function addConnector(opts: AddConnectorOptions): Promise<AddConnec
168
169
  // A pre-existing connection of this name must be a compatible object of the
169
170
  // same pack `type`; otherwise wiring workers to it would produce an invalid
170
171
  // or misleading manifest. Fail loudly instead of silently reusing it.
171
- if (existing === null || typeof existing !== "object" || Array.isArray(existing)) {
172
+ if (!isRecord(existing)) {
172
173
  throw new Error(`connection "${connection}" already exists and is not an object.`);
173
174
  }
174
- const conn = existing as Record<string, unknown>;
175
+ const conn = existing;
175
176
  if (conn.type !== undefined && conn.type !== pack.id) {
176
177
  throw new Error(
177
178
  `connection "${connection}" already exists with type "${String(conn.type)}", ` +
@@ -134,10 +134,12 @@ const XML = `<?xml version="1.0"?>
134
134
 
135
135
  test("scanModelMessages extracts message name + envelope; a self-closing message is name-only", () => {
136
136
  const m = scanModelMessages(XML);
137
- const placed = m.find((x) => x.messageName === "OrderPlaced") as MessageIo;
137
+ const placed = m.find((x) => x.messageName === "OrderPlaced");
138
+ assert.ok(placed);
138
139
  assert.ok(placed);
139
140
  assert.equal(placed.inputType, "Order");
140
- const ping = m.find((x) => x.messageName === "Ping") as MessageIo;
141
+ const ping = m.find((x) => x.messageName === "Ping");
142
+ assert.ok(ping);
141
143
  assert.ok(ping);
142
144
  assert.equal(ping.inputType, undefined);
143
145
  });
@@ -40,13 +40,15 @@ const XML = `<?xml version="1.0"?>
40
40
 
41
41
  test("scanModelWorkers extracts task type, element id, process, and envelope io", () => {
42
42
  const w = scanModelWorkers(XML);
43
- const charge = w.find((x) => x.taskType === "orders.charge") as WorkerIo;
43
+ const charge = w.find((x) => x.taskType === "orders.charge");
44
+ assert.ok(charge);
44
45
  assert.ok(charge);
45
46
  assert.equal(charge.elementId, "Charge");
46
47
  assert.equal(charge.process, "orders");
47
48
  assert.equal(charge.in, "Payment");
48
49
  assert.equal(charge.out, "Receipt");
49
- const notify = w.find((x) => x.taskType === "orders.notify") as WorkerIo;
50
+ const notify = w.find((x) => x.taskType === "orders.notify");
51
+ assert.ok(notify);
50
52
  assert.equal(notify.in, undefined);
51
53
  assert.equal(notify.out, undefined);
52
54
  });
@@ -50,7 +50,8 @@ export function createNodeGenIO(): GenIO {
50
50
  // stat failed (e.g. a virtual path); fall back to no cache key and let import() surface it.
51
51
  }
52
52
  const href = `${pathToFileURL(abs).href}${version}`;
53
- return import(href) as Promise<Record<string, unknown>>;
53
+ const mod: Promise<Record<string, unknown>> = import(href);
54
+ return mod;
54
55
  },
55
56
  };
56
57
  }
@@ -110,9 +110,9 @@ async function collectAll(opts: GenOptions): Promise<{ artifacts: DerivedArtifac
110
110
  const { root, io } = opts;
111
111
  const emitModels = opts.emitModels ?? true;
112
112
  const manifestPath = join(root, opts.manifestFile ?? "nano.app.json");
113
- const manifest = JSON.parse(await io.readText(manifestPath)) as ToolkitManifest & {
113
+ const manifest: ToolkitManifest & {
114
114
  models?: { processes?: string[]; workflows?: string[] };
115
- };
115
+ } = JSON.parse(await io.readText(manifestPath));
116
116
 
117
117
  const artifacts: DerivedArtifact[] = [];
118
118
 
@@ -186,8 +186,8 @@ export { dirOf, join as joinPath };
186
186
  export async function previewModels(opts: GenOptions): Promise<DerivedModels> {
187
187
  const { root, io } = opts;
188
188
  const manifestPath = join(root, opts.manifestFile ?? "nano.app.json");
189
- const manifest = JSON.parse(await io.readText(manifestPath)) as {
189
+ const manifest: {
190
190
  models?: { processes?: string[]; workflows?: string[] };
191
- };
191
+ } = JSON.parse(await io.readText(manifestPath));
192
192
  return deriveModels(root, io, manifest);
193
193
  }
@@ -93,7 +93,7 @@ test("deriveModels turns workflows/*.ts into a provenance-stamped processes/<id>
93
93
 
94
94
  test("deriveModels is a no-op without a module loader (pure/IDE callers)", async () => {
95
95
  const io = memIO({ "/app/workflows/greet.ts": "// source" });
96
- delete (io as { importModule?: unknown }).importModule;
96
+ delete io.importModule;
97
97
  const d = await deriveModels("/app", io, CODE_FIRST_MANIFEST);
98
98
  assert.equal(d.attempted, false);
99
99
  assert.equal(d.artifacts.length, 0);
@@ -14,6 +14,7 @@ import type { DerivedArtifact } from "./artifact.ts";
14
14
  import type { GenIO } from "./gen.ts";
15
15
  import { expandPattern, joinPath } from "./gen.ts";
16
16
  import type { ModelSource } from "./derivers/worker-io.ts";
17
+ import { isRecord } from "../runtime/core/guards.ts";
17
18
 
18
19
  /** Default source glob for code-first flows (matches the code-first scaffold layout). */
19
20
  export const DEFAULT_WORKFLOW_PATTERNS = ["workflows/*.ts"];
@@ -34,9 +35,7 @@ export interface ModelsManifest {
34
35
 
35
36
  /** A `defineFlow` export: has a string `id` and an `imperative`/`declarative` `kind`. */
36
37
  export function isWorkflow(v: unknown): v is Workflow {
37
- if (!v || typeof v !== "object") return false;
38
- const o = v as { id?: unknown; kind?: unknown };
39
- return typeof o.id === "string" && (o.kind === "imperative" || o.kind === "declarative");
38
+ return isRecord(v) && typeof v.id === "string" && (v.kind === "imperative" || v.kind === "declarative");
40
39
  }
41
40
 
42
41
  /** Sanitize a flow id into a safe `.bpmn` filename (mirrors the host generator). */
@@ -113,7 +112,7 @@ function messageOf(e: unknown): string {
113
112
  /** Append an actionable hint when a `.ts` import fails because the runtime can't strip types. */
114
113
  function importHint(rel: string, e: unknown): string {
115
114
  const base = messageOf(e);
116
- const code = (e as { code?: string })?.code ?? "";
115
+ const code = isRecord(e) && typeof e.code === "string" ? e.code : "";
117
116
  const looksLikeNoTsLoader =
118
117
  rel.endsWith(".ts") &&
119
118
  (code === "ERR_UNKNOWN_FILE_EXTENSION" || /Unknown file extension "\.ts"/.test(base));
@@ -57,7 +57,7 @@ export async function scaffoldWorkers(opts: ScaffoldOptions): Promise<ScaffoldRu
57
57
  const manifestFile = opts.manifestFile ?? "nano.app.json";
58
58
  const manifestPath = joinPath(root, manifestFile);
59
59
 
60
- const manifest = JSON.parse(await io.readText(manifestPath)) as ScaffoldManifest;
60
+ const manifest: ScaffoldManifest = JSON.parse(await io.readText(manifestPath));
61
61
  const models = await readModels(root, io, manifest);
62
62
  const declaredTypeIds = Object.keys(manifest.types ?? {});
63
63