@walkeros/cli 4.8.2 → 4.8.3-next-1793115089237

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 (42) hide show
  1. package/CHANGELOG.md +59 -3
  2. package/README.md +2 -2
  3. package/dist/cli.js +1320 -1318
  4. package/dist/dev.d.ts +51 -3
  5. package/dist/dev.js +186 -0
  6. package/dist/dev.js.map +1 -1
  7. package/dist/examples/README.md +12 -1
  8. package/dist/examples/contracts/app.json +261 -0
  9. package/dist/examples/contracts/base.json +708 -0
  10. package/dist/examples/contracts/ecommerce.json +963 -0
  11. package/dist/examples/contracts/leadgen.json +240 -0
  12. package/dist/examples/contracts/publisher.json +372 -0
  13. package/dist/examples/contracts/saas.json +229 -0
  14. package/dist/examples/contracts/travel.json +234 -0
  15. package/dist/examples/customers/README.md +4 -1
  16. package/dist/examples/flow-complete.json +40 -25
  17. package/dist/examples/flow-complete.md +5 -3
  18. package/dist/examples/index.js +42 -27
  19. package/dist/examples/index.js.map +1 -1
  20. package/dist/examples/shared/README.md +4 -0
  21. package/dist/index.d.ts +41 -41
  22. package/dist/index.js +161 -134
  23. package/dist/index.js.map +1 -1
  24. package/dist/validate.js +264 -132
  25. package/dist/validate.js.map +1 -1
  26. package/examples/README.md +12 -1
  27. package/examples/contracts/app.json +261 -0
  28. package/examples/contracts/base.json +708 -0
  29. package/examples/contracts/ecommerce.json +963 -0
  30. package/examples/contracts/leadgen.json +240 -0
  31. package/examples/contracts/publisher.json +372 -0
  32. package/examples/contracts/saas.json +229 -0
  33. package/examples/contracts/travel.json +234 -0
  34. package/examples/customers/README.md +4 -1
  35. package/examples/flow-complete.json +40 -25
  36. package/examples/flow-complete.md +5 -3
  37. package/examples/shared/README.md +4 -0
  38. package/package.json +30 -30
  39. package/dist/examples/test.html +0 -43
  40. package/dist/examples/web-serve.js +0 -25503
  41. package/examples/test.html +0 -43
  42. package/examples/web-serve.js +0 -25503
package/dist/dev.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from '@walkeros/core/dev';
2
- import { Flow } from '@walkeros/core';
2
+ import { Flow, StepType, Logger, WalkerOSPackage } from '@walkeros/core';
3
3
 
4
4
  /**
5
5
  * CLI Primitive Schemas
@@ -322,7 +322,7 @@ declare namespace index {
322
322
  * always grabbed `mod.default`).
323
323
  */
324
324
 
325
- type ComponentKind = 'source' | 'transformer' | 'destination' | 'store';
325
+ type ComponentKind = StepType;
326
326
  type ResolveSource = 'import' | 'imports' | 'default';
327
327
  interface ResolvedExportName {
328
328
  /**
@@ -362,4 +362,52 @@ declare function resolveExportName(flow: Flow, kind: ComponentKind, id: string):
362
362
  */
363
363
  declare function selectDevExamples(devModule: unknown, exportName: string | undefined): Record<string, unknown> | undefined;
364
364
 
365
- export { resolveExportName, index as schemas, selectDevExamples };
365
+ /**
366
+ * Step-package normalization shared by bundle, setup, validate and the MCP's
367
+ * flow_examples.
368
+ *
369
+ * Pure flow-config logic: which packages do the flow's steps declare, and
370
+ * what is the effective {name, version | path} for each after merging inline
371
+ * step specs with config.bundle.packages pins. Lives in core/ so every
372
+ * command and tool that reads a step's package runs the exact same precedence
373
+ * (a bundle pin always wins; an unversioned bundle entry is filled from the
374
+ * first inline version; conflicting inline versions with no pin throw;
375
+ * local paths become synthetic packageNameToVariable keys).
376
+ */
377
+
378
+ interface ResolvedStepPackage {
379
+ /** Bare package name after normalization (inline version stripped, local path replaced by synthetic key). */
380
+ packageName: string;
381
+ /** The package as messages and results name it: the bare npm name, or a step's own local path as written. */
382
+ label: string;
383
+ /** Effective bundle entry: version pin and/or local path per bundle precedence. */
384
+ spec: Flow.BundlePackage;
385
+ /** flow.config.bundle.overrides, for transitive pins. */
386
+ overrides: Record<string, string>;
387
+ /** Deep clone of the flow with step.package rewritten to bare names; the input flow is never mutated. */
388
+ normalizedFlow: Flow;
389
+ }
390
+ /**
391
+ * Resolve the effective package spec for one step by running the SAME
392
+ * normalization the bundler runs over the whole flow (applyStepPackages),
393
+ * on a clone so the caller's flow stays untouched. The clone comes back as
394
+ * `normalizedFlow` with `step.package` rewritten to the bare name, which is
395
+ * also what resolveExportName needs to match `bundle.packages[pkg].imports`.
396
+ */
397
+ declare function resolveStepPackage(flow: Flow, kind: ComponentKind, id: string, logger: Logger.Instance): ResolvedStepPackage;
398
+
399
+ /** A package's walkerOS.json content, plus the version read (absent for a local package whose package.json names none). */
400
+ type StepPackageInfo = Omit<WalkerOSPackage, 'packageName' | 'version' | 'description'> & {
401
+ version?: string;
402
+ };
403
+ /**
404
+ * Read the walkerOS metadata of a resolved step package. A local path
405
+ * resolves against `configDir`; without one nothing is read from disk and
406
+ * the read fails. `client` names the calling tool in the CDN request.
407
+ */
408
+ declare function readStepPackageInfo(resolved: Pick<ResolvedStepPackage, 'packageName' | 'spec'>, options: {
409
+ configDir?: string;
410
+ client: string;
411
+ }): Promise<StepPackageInfo>;
412
+
413
+ export { type ResolvedStepPackage, type StepPackageInfo, readStepPackageInfo, resolveExportName, resolveStepPackage, index as schemas, selectDevExamples };
package/dist/dev.js CHANGED
@@ -173,8 +173,194 @@ function selectDevExamples(devModule, exportName) {
173
173
  const examples = devModule.examples;
174
174
  return isRecord(examples) ? examples : void 0;
175
175
  }
176
+
177
+ // src/core/step-packages.ts
178
+ import { packageNameToVariable } from "@walkeros/core";
179
+ function getFlowSection(flow, section) {
180
+ switch (section) {
181
+ case "sources":
182
+ return flow.sources;
183
+ case "destinations":
184
+ return flow.destinations;
185
+ case "transformers":
186
+ return flow.transformers;
187
+ case "stores":
188
+ return flow.stores;
189
+ }
190
+ }
191
+ function isLocalPath(spec) {
192
+ return spec.startsWith(".") || spec.startsWith("/");
193
+ }
194
+ function parsePackageSpec(spec) {
195
+ const at = spec.lastIndexOf("@");
196
+ if (at <= 0) return { name: spec };
197
+ const version = spec.slice(at + 1);
198
+ return version ? { name: spec.slice(0, at), version } : { name: spec.slice(0, at) };
199
+ }
200
+ function detectStepPackages(flowSettings, section) {
201
+ const packages = /* @__PURE__ */ new Set();
202
+ const steps = getFlowSection(flowSettings, section);
203
+ if (steps) {
204
+ for (const [, stepConfig] of Object.entries(steps)) {
205
+ if (typeof stepConfig !== "object" || stepConfig === null) continue;
206
+ if (typeof stepConfig.package === "string") {
207
+ packages.add(stepConfig.package);
208
+ }
209
+ }
210
+ }
211
+ return packages;
212
+ }
213
+ function collectAllStepPackages(flowSettings) {
214
+ const allPackages = /* @__PURE__ */ new Set();
215
+ const sections = [
216
+ "sources",
217
+ "destinations",
218
+ "transformers",
219
+ "stores"
220
+ ];
221
+ for (const section of sections) {
222
+ for (const pkg of detectStepPackages(flowSettings, section)) {
223
+ allPackages.add(pkg);
224
+ }
225
+ }
226
+ return allPackages;
227
+ }
228
+ function applyStepPackages(flowSettings, packages, logger) {
229
+ const stepPackages = collectAllStepPackages(flowSettings);
230
+ const originalPins = /* @__PURE__ */ new Map();
231
+ const inlineSeen = /* @__PURE__ */ new Map();
232
+ const rewriteSteps = (from, to) => {
233
+ for (const section of [
234
+ "sources",
235
+ "destinations",
236
+ "transformers",
237
+ "stores"
238
+ ]) {
239
+ const steps = getFlowSection(flowSettings, section);
240
+ if (!steps) continue;
241
+ for (const step of Object.values(steps)) {
242
+ if (step.package === from) {
243
+ step.package = to;
244
+ }
245
+ }
246
+ }
247
+ };
248
+ for (const pkg of stepPackages) {
249
+ if (isLocalPath(pkg)) {
250
+ const varName = packageNameToVariable(pkg);
251
+ if (!packages[varName]) {
252
+ packages[varName] = {
253
+ path: pkg
254
+ };
255
+ }
256
+ rewriteSteps(pkg, varName);
257
+ continue;
258
+ }
259
+ const { name, version } = parsePackageSpec(pkg);
260
+ if (!originalPins.has(name)) {
261
+ const entry = packages[name];
262
+ originalPins.set(
263
+ name,
264
+ entry?.version !== void 0 || entry?.path !== void 0
265
+ );
266
+ }
267
+ const hasBundlePin = originalPins.get(name) === true;
268
+ if (name !== pkg) {
269
+ rewriteSteps(pkg, name);
270
+ }
271
+ if (version && !hasBundlePin) {
272
+ const seen = inlineSeen.get(name);
273
+ if (seen !== void 0 && seen !== version) {
274
+ throw new Error(
275
+ `Conflicting inline versions for ${name}: "${seen}" and "${version}" are declared by different steps. Pin one version in config.bundle.packages.`
276
+ );
277
+ }
278
+ inlineSeen.set(name, version);
279
+ }
280
+ const existing = packages[name];
281
+ if (!existing) {
282
+ packages[name] = version ? { version } : {};
283
+ } else if (version && !existing.path) {
284
+ if (!existing.version) {
285
+ existing.version = version;
286
+ } else if (existing.version !== version) {
287
+ logger.warn(
288
+ `Package ${name}: config.bundle.packages pins ${existing.version}; a step declares ${version} inline. Using the bundle pin.`
289
+ );
290
+ }
291
+ }
292
+ }
293
+ }
294
+ var KIND_TO_SECTION = {
295
+ source: "sources",
296
+ transformer: "transformers",
297
+ destination: "destinations",
298
+ store: "stores"
299
+ };
300
+ function resolveStepPackage(flow, kind, id, logger) {
301
+ const normalizedFlow = structuredClone(flow);
302
+ const packages = structuredClone(
303
+ normalizedFlow.config?.bundle?.packages ?? {}
304
+ );
305
+ applyStepPackages(normalizedFlow, packages, logger);
306
+ const bucket = getFlowSection(normalizedFlow, KIND_TO_SECTION[kind]);
307
+ const step = bucket?.[id];
308
+ if (!step) {
309
+ const available = Object.keys(bucket ?? {}).join(", ") || "(none)";
310
+ throw new Error(
311
+ `${kind} "${id}" not found in flow. Available: ${available}`
312
+ );
313
+ }
314
+ if (typeof step.package !== "string") {
315
+ throw new Error(
316
+ `${kind}.${id} has no "package" (inline code cannot be set up).`
317
+ );
318
+ }
319
+ const declared = getFlowSection(flow, KIND_TO_SECTION[kind])?.[id]?.package;
320
+ return {
321
+ packageName: step.package,
322
+ label: declared !== void 0 && isLocalPath(declared) ? declared : step.package,
323
+ spec: packages[step.package] ?? {},
324
+ overrides: normalizedFlow.config?.bundle?.overrides ?? {},
325
+ normalizedFlow
326
+ };
327
+ }
328
+
329
+ // src/core/package-info.ts
330
+ import * as fs from "fs";
331
+ import * as path from "path";
332
+ import { fetchPackage, isObject, parseWalkerOSJson } from "@walkeros/core";
333
+ function readJson(file) {
334
+ return JSON.parse(fs.readFileSync(file, "utf-8"));
335
+ }
336
+ async function readStepPackageInfo(resolved, options) {
337
+ const { packageName, spec } = resolved;
338
+ if (spec.path === void 0)
339
+ return fetchPackage(packageName, {
340
+ ...spec.version ? { version: spec.version } : {},
341
+ client: options.client
342
+ });
343
+ if (options.configDir === void 0)
344
+ throw new Error(
345
+ "it is a local path package and the input is not a file, so there is no directory to read it from"
346
+ );
347
+ const root = path.isAbsolute(spec.path) ? spec.path : path.resolve(options.configDir, spec.path);
348
+ const file = [
349
+ path.join(root, "dist", "walkerOS.json"),
350
+ path.join(root, "walkerOS.json")
351
+ ].find((candidate) => fs.existsSync(candidate));
352
+ if (!file) throw new Error(`no walkerOS.json under ${root}`);
353
+ const meta = readJson(file);
354
+ if (!isObject(meta)) throw new Error(`${file} is not a JSON object`);
355
+ const pkgFile = path.join(root, "package.json");
356
+ const pkg = fs.existsSync(pkgFile) ? readJson(pkgFile) : void 0;
357
+ const version = isObject(pkg) && typeof pkg.version === "string" ? pkg.version : void 0;
358
+ return { ...parseWalkerOSJson(meta), ...version ? { version } : {} };
359
+ }
176
360
  export {
361
+ readStepPackageInfo,
177
362
  resolveExportName,
363
+ resolveStepPackage,
178
364
  schemas_exports as schemas,
179
365
  selectDevExamples
180
366
  };
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/schemas/index.ts","../src/schemas/primitives.ts","../src/schemas/validate.ts","../src/schemas/bundle.ts","../src/schemas/simulate.ts","../src/schemas/push.ts","../src/core/resolve-export-name.ts","../src/commands/push/dev-examples.ts"],"sourcesContent":["/**\n * CLI Schemas\n *\n * Zod schemas for CLI parameter validation.\n * Follows walkerOS patterns from @walkeros/core.\n */\n\nexport { PortSchema, FilePathSchema } from './primitives';\n\nexport {\n ValidationTypeSchema,\n ValidateOptionsSchema,\n ValidateInputShape,\n ValidateInputSchema,\n type ValidationType,\n type ValidateOptions,\n type ValidateInput,\n} from './validate';\n\nexport {\n BundleOptionsSchema,\n BundleInputShape,\n BundleInputSchema,\n type BundleOptions,\n type BundleInput,\n} from './bundle';\n\nexport {\n PlatformSchema,\n SimulateOptionsSchema,\n SimulateInputShape,\n SimulateInputSchema,\n type Platform,\n type SimulateOptions,\n type SimulateInput,\n} from './simulate';\n\nexport {\n PushOptionsSchema,\n PushInputShape,\n PushInputSchema,\n type PushOptions,\n type PushInput,\n} from './push';\n","/**\n * CLI Primitive Schemas\n *\n * Basic Zod schemas for CLI parameter validation.\n * Follows walkerOS patterns from @walkeros/core.\n */\n\nimport { z } from '@walkeros/core/dev';\n\n/**\n * Port number schema.\n *\n * @remarks\n * Validates HTTP server port number.\n * Must be integer between 1-65535.\n */\nexport const PortSchema = z\n .number()\n .int('Port must be an integer')\n .min(1, 'Port must be at least 1')\n .max(65535, 'Port must be at most 65535')\n .describe('HTTP server port number');\n\n/**\n * File path schema.\n *\n * @remarks\n * Basic string validation for file paths.\n * File existence is checked separately (Zod can't check filesystem).\n */\nexport const FilePathSchema = z\n .string()\n .min(1, 'File path cannot be empty')\n .describe('Path to configuration file');\n","/**\n * Validate Command Schemas\n *\n * Zod schemas for validate command parameter validation.\n */\n\nimport { z } from '@walkeros/core/dev';\n\n/**\n * Validation type schema.\n *\n * @remarks\n * Validates the type of validation to perform.\n * - `contract`: Validate a data contract\n * - `event`: Validate a walkerOS event object\n * - `flow`: Validate a flow configuration file\n * - `mapping`: Validate mapping rules\n */\nexport const ValidationTypeSchema = z\n .enum(['contract', 'event', 'flow', 'mapping'])\n .describe('Validation type: \"event\", \"flow\", \"mapping\", or \"contract\"');\n\nexport type ValidationType = z.infer<typeof ValidationTypeSchema>;\n\n/**\n * Validate options schema.\n *\n * @remarks\n * Options for the programmatic validate() API.\n */\nexport const ValidateOptionsSchema = z.object({\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n path: z\n .string()\n .optional()\n .describe(\n 'Entry path for package schema validation (e.g., \"destinations.snowplow\", \"stores.cache\"). Checks the entry in every flow that has it, or only in --flow.',\n ),\n strict: z\n .boolean()\n .optional()\n .describe(\n 'Escalate: strict turns warnings and skips into failures (valid is false), contract disagreements error',\n ),\n offline: z\n .boolean()\n .optional()\n .describe(\n 'Do not fetch package schemas: step settings are not checked against them, and the result scope says so. Only with type \"flow\" and no path.',\n ),\n configDir: z\n .string()\n .optional()\n .describe(\n \"Directory local `path` packages resolve against. Defaults to the input file's directory; set it when passing a parsed document.\",\n ),\n});\n\nexport type ValidateOptions = z.infer<typeof ValidateOptionsSchema>;\n\n/**\n * Raw shape for MCP SDK compatibility (ZodRawShapeCompat).\n *\n * @remarks\n * MCP SDK's registerTool expects raw shapes (Record<string, ZodType>)\n * rather than ZodObject instances. Define shape first, then wrap.\n */\nexport const ValidateInputShape = {\n type: ValidationTypeSchema,\n input: z\n .string()\n .min(1)\n .describe('JSON string, file path, or URL to validate'),\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n path: z\n .string()\n .optional()\n .describe(\n 'Entry path for package schema validation (e.g., \"destinations.snowplow\"). Only with type \"flow\": validates the entry against its package JSON Schema in every flow that has it, or only in the given flow.',\n ),\n strict: z\n .boolean()\n .optional()\n .describe(\n 'Escalate: strict turns warnings and skips into failures: valid is false (the CLI exits 2), and contract example disagreements become errors. Every check runs with or without it.',\n ),\n offline: z\n .boolean()\n .optional()\n .describe(\n 'Do not fetch package schemas: step settings are not checked against them, and details.scope says so. Only with type \"flow\" and no path.',\n ),\n};\n\n/**\n * Validate input schema for MCP tools.\n *\n * @remarks\n * Full input schema including type and input source.\n */\nexport const ValidateInputSchema = z.object(ValidateInputShape);\n\nexport type ValidateInput = z.infer<typeof ValidateInputSchema>;\n","/**\n * Bundle Command Schemas\n *\n * Zod schemas for bundle command parameter validation.\n */\n\nimport { z } from '@walkeros/core/dev';\nimport { FilePathSchema } from './primitives';\n\n/**\n * Bundle options schema.\n *\n * @remarks\n * Options for the programmatic bundle() API.\n */\nexport const BundleOptionsSchema = z.object({\n silent: z.boolean().optional().describe('Suppress all output'),\n verbose: z.boolean().optional().describe('Enable verbose logging'),\n stats: z\n .boolean()\n .optional()\n .default(true)\n .describe('Return bundle statistics'),\n cache: z\n .boolean()\n .optional()\n .default(true)\n .describe('Enable package caching'),\n flowName: z.string().optional().describe('Flow name for multi-flow configs'),\n});\n\nexport type BundleOptions = z.infer<typeof BundleOptionsSchema>;\n\n/**\n * Raw shape for MCP SDK compatibility (ZodRawShapeCompat).\n *\n * @remarks\n * MCP SDK's registerTool expects raw shapes (Record<string, ZodType>)\n * rather than ZodObject instances. Define shape first, then wrap.\n */\nexport const BundleInputShape = {\n configPath: FilePathSchema.describe(\n 'Path to flow configuration file (JSON or JavaScript), URL, or inline JSON string',\n ),\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n stats: z\n .boolean()\n .optional()\n .default(true)\n .describe('Return bundle statistics'),\n output: z\n .string()\n .optional()\n .describe('Output file path (defaults to config-defined)'),\n};\n\n/**\n * Bundle input schema for MCP tools.\n *\n * @remarks\n * Full input schema including config path and options.\n */\nexport const BundleInputSchema = z.object(BundleInputShape);\n\nexport type BundleInput = z.infer<typeof BundleInputSchema>;\n","/**\n * Simulate Command Schemas\n *\n * Zod schemas for simulate command parameter validation.\n */\n\nimport { z } from '@walkeros/core/dev';\nimport { FilePathSchema } from './primitives';\n\n/**\n * Platform schema.\n *\n * @remarks\n * Validates platform type for event simulation.\n */\nexport const PlatformSchema = z\n .enum(['web', 'server'])\n .describe('Platform type for event processing');\n\nexport type Platform = z.infer<typeof PlatformSchema>;\n\n/**\n * Simulate options schema.\n *\n * @remarks\n * Options for the programmatic simulate() API.\n */\nexport const SimulateOptionsSchema = z.object({\n silent: z.boolean().optional().describe('Suppress all output'),\n verbose: z.boolean().optional().describe('Enable verbose logging'),\n json: z.boolean().optional().describe('Format output as JSON'),\n});\n\nexport type SimulateOptions = z.infer<typeof SimulateOptionsSchema>;\n\n/**\n * Raw shape for MCP SDK compatibility (ZodRawShapeCompat).\n *\n * @remarks\n * MCP SDK's registerTool expects raw shapes (Record<string, ZodType>)\n * rather than ZodObject instances. Define shape first, then wrap.\n */\nexport const SimulateInputShape = {\n configPath: FilePathSchema.describe(\n 'Path to flow configuration file, URL, or inline JSON string',\n ),\n event: z\n .string()\n .min(1)\n .optional()\n .describe(\n 'Event as JSON string, file path, or URL. For sources: { content, trigger?, env? }.',\n ),\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n platform: PlatformSchema.optional().describe('Override platform detection'),\n step: z\n .string()\n .optional()\n .describe(\n 'Step target in type.name format (e.g. \"source.browser\", \"destination.gtag\")',\n ),\n};\n\n/**\n * Simulate input schema for MCP tools.\n *\n * @remarks\n * Full input schema including config path, event, and options.\n */\nexport const SimulateInputSchema = z.object(SimulateInputShape);\n\nexport type SimulateInput = z.infer<typeof SimulateInputSchema>;\n","/**\n * Push Command Schemas\n *\n * Zod schemas for push command parameter validation.\n */\n\nimport { z } from '@walkeros/core/dev';\nimport { FilePathSchema } from './primitives';\nimport { PlatformSchema } from './simulate';\n\n/**\n * Push options schema.\n *\n * @remarks\n * Options for the programmatic push() API.\n */\nexport const PushOptionsSchema = z.object({\n silent: z.boolean().optional().describe('Suppress all output'),\n verbose: z.boolean().optional().describe('Enable verbose logging'),\n json: z.boolean().optional().describe('Format output as JSON'),\n});\n\nexport type PushOptions = z.infer<typeof PushOptionsSchema>;\n\n/**\n * Raw shape for MCP SDK compatibility (ZodRawShapeCompat).\n *\n * @remarks\n * MCP SDK's registerTool expects raw shapes (Record<string, ZodType>)\n * rather than ZodObject instances. Define shape first, then wrap.\n */\nexport const PushInputShape = {\n configPath: FilePathSchema.describe('Path to flow configuration file'),\n event: z.string().min(1).describe('Event as JSON string, file path, or URL'),\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n platform: PlatformSchema.optional().describe('Override platform detection'),\n};\n\n/**\n * Push input schema for MCP tools.\n *\n * @remarks\n * Full input schema including config path, event, and options.\n */\nexport const PushInputSchema = z.object(PushInputShape);\n\nexport type PushInput = z.infer<typeof PushInputSchema>;\n","/**\n * Shared resolver for the export name to import from a flow component's\n * package.\n *\n * Both `walkeros bundle` and `walkeros setup` need to know which named export\n * (or default) to pull off a package referenced by a flow component. The\n * precedence chain is:\n *\n * 1. `flow.<kind>.<id>.import` if set (named export selector at the step).\n * 2. `flow.config.bundle.packages[<package>].imports[0]` if set.\n * 3. Otherwise undefined; the caller falls back to the package's `default`\n * export.\n *\n * This lives in `cli/src/core/` so both `commands/bundle/*` and\n * `commands/setup/*` import the same function. Duplicating the chain is how\n * setup ended up out of sync with bundle (Bug F: `setup destination.pubsub`\n * routed through BigQuery's setup because it ignored the `code` field and\n * always grabbed `mod.default`).\n */\n\nimport type { Flow } from '@walkeros/core';\n\nexport type ComponentKind = 'source' | 'transformer' | 'destination' | 'store';\n\nexport type ResolveSource = 'import' | 'imports' | 'default';\n\nexport interface ResolvedExportName {\n /**\n * The named export to pull off the imported module, or `undefined` to\n * indicate the caller should use the package's `default` export.\n */\n exportName: string | undefined;\n /** Which precedence step produced the result (useful for diagnostics). */\n source: ResolveSource;\n}\n\ninterface FlowStepView {\n package?: string;\n import?: string;\n}\n\nfunction getStep(\n flow: Flow,\n kind: ComponentKind,\n id: string,\n): FlowStepView | undefined {\n switch (kind) {\n case 'source':\n return flow.sources?.[id];\n case 'transformer':\n return flow.transformers?.[id];\n case 'destination':\n return flow.destinations?.[id];\n case 'store':\n return flow.stores?.[id];\n }\n}\n\nfunction getBundlePackages(\n flow: Flow,\n): Record<string, Flow.BundlePackage> | undefined {\n return flow.config?.bundle?.packages;\n}\n\n/**\n * Read the first entry of `bundle.packages[<package>].imports` if it is a\n * non-empty string. Returns `undefined` otherwise.\n */\nfunction readFirstImport(\n packages: Record<string, Flow.BundlePackage> | undefined,\n packageName: string | undefined,\n): string | undefined {\n if (!packages || !packageName) return undefined;\n const pkg = packages[packageName];\n if (!pkg || !pkg.imports || pkg.imports.length === 0) return undefined;\n const first = pkg.imports[0];\n return typeof first === 'string' && first.length > 0 ? first : undefined;\n}\n\n/**\n * Resolve the export name to import for a flow component's package.\n *\n * See module docs for the precedence chain. Inline code (`code` is an object)\n * doesn't enter this resolver at all — setup rejects inline code at a higher\n * layer.\n */\nexport function resolveExportName(\n flow: Flow,\n kind: ComponentKind,\n id: string,\n): ResolvedExportName {\n const step = getStep(flow, kind, id);\n if (!step) return { exportName: undefined, source: 'default' };\n\n const packageName = step.package;\n const importName = step.import;\n\n // 1. Explicit `import` field on the step wins.\n if (typeof importName === 'string' && importName.length > 0) {\n return { exportName: importName, source: 'import' };\n }\n\n // 2. Fallback to bundle.packages[pkg].imports[0].\n const firstImport = readFirstImport(getBundlePackages(flow), packageName);\n if (firstImport) {\n return { exportName: firstImport, source: 'imports' };\n }\n\n // 3. Default export.\n return { exportName: undefined, source: 'default' };\n}\n","function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object';\n}\n\n/**\n * Selects the dev examples of one export from a package's awaited `/dev`\n * module.\n *\n * A package with several exports (`walkerOS.exports` in its package.json)\n * ships `exportExamples`, a map from export name to that export's examples,\n * the default export included. A package with one export ships only\n * `examples`.\n *\n * - Map present, export named: `exportExamples[exportName]`. A name missing\n * from the map resolves to `undefined`, never to another export's examples.\n * - Map present, no export name (the step uses the default export):\n * `examples`, which by convention holds the default export's examples.\n * - No map: `examples`.\n *\n * `exportName` comes from `resolveExportName` (step `import`, else\n * `bundle.packages[pkg].imports[0]`, else default).\n */\nexport function selectDevExamples(\n devModule: unknown,\n exportName: string | undefined,\n): Record<string, unknown> | undefined {\n if (!isRecord(devModule)) return undefined;\n\n const map = devModule.exportExamples;\n if (isRecord(map) && exportName !== undefined) {\n const selected = map[exportName];\n return isRecord(selected) ? selected : undefined;\n }\n\n const examples = devModule.examples;\n return isRecord(examples) ? examples : undefined;\n}\n\n/**\n * A package version from before export-keyed examples ships only\n * `examples` (the default export's), even when it declares several\n * exports. For a step naming an export, those examples may belong to\n * another export, so simulate must refuse instead of running that export's\n * mock (or none) against the real vendor. Returns the refusal message, or\n * `undefined` when the examples can be trusted.\n *\n * `packageExports` is the bundle's `__packageExports` (declared exports per\n * package, read at build time from the bundled copy). A bundle without it\n * (built before it existed) cannot tell single- from multi-export packages,\n * so a step naming an export without a map is refused.\n */\nexport function legacyExportRefusal(\n devModule: unknown,\n packageExports: Record<string, string[]> | undefined,\n packageName: string,\n exportName: string | undefined,\n): string | undefined {\n if (exportName === undefined) return undefined;\n if (isRecord(devModule) && isRecord(devModule.exportExamples))\n return undefined;\n if (packageExports) {\n const declared = packageExports[packageName];\n if (!declared || declared.length <= 1) return undefined;\n }\n return `No mock env for ${packageName} export ${exportName}: this package version predates export-keyed examples; use a version with exportExamples or a local path.`;\n}\n"],"mappings":"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","names":["z","z","z","z","z","z","z"]}
1
+ {"version":3,"sources":["../src/schemas/index.ts","../src/schemas/primitives.ts","../src/schemas/validate.ts","../src/schemas/bundle.ts","../src/schemas/simulate.ts","../src/schemas/push.ts","../src/core/resolve-export-name.ts","../src/commands/push/dev-examples.ts","../src/core/step-packages.ts","../src/core/package-info.ts"],"sourcesContent":["/**\n * CLI Schemas\n *\n * Zod schemas for CLI parameter validation.\n * Follows walkerOS patterns from @walkeros/core.\n */\n\nexport { PortSchema, FilePathSchema } from './primitives';\n\nexport {\n ValidationTypeSchema,\n ValidateOptionsSchema,\n ValidateInputShape,\n ValidateInputSchema,\n type ValidationType,\n type ValidateOptions,\n type ValidateInput,\n} from './validate';\n\nexport {\n BundleOptionsSchema,\n BundleInputShape,\n BundleInputSchema,\n type BundleOptions,\n type BundleInput,\n} from './bundle';\n\nexport {\n PlatformSchema,\n SimulateOptionsSchema,\n SimulateInputShape,\n SimulateInputSchema,\n type Platform,\n type SimulateOptions,\n type SimulateInput,\n} from './simulate';\n\nexport {\n PushOptionsSchema,\n PushInputShape,\n PushInputSchema,\n type PushOptions,\n type PushInput,\n} from './push';\n","/**\n * CLI Primitive Schemas\n *\n * Basic Zod schemas for CLI parameter validation.\n * Follows walkerOS patterns from @walkeros/core.\n */\n\nimport { z } from '@walkeros/core/dev';\n\n/**\n * Port number schema.\n *\n * @remarks\n * Validates HTTP server port number.\n * Must be integer between 1-65535.\n */\nexport const PortSchema = z\n .number()\n .int('Port must be an integer')\n .min(1, 'Port must be at least 1')\n .max(65535, 'Port must be at most 65535')\n .describe('HTTP server port number');\n\n/**\n * File path schema.\n *\n * @remarks\n * Basic string validation for file paths.\n * File existence is checked separately (Zod can't check filesystem).\n */\nexport const FilePathSchema = z\n .string()\n .min(1, 'File path cannot be empty')\n .describe('Path to configuration file');\n","/**\n * Validate Command Schemas\n *\n * Zod schemas for validate command parameter validation.\n */\n\nimport { z } from '@walkeros/core/dev';\n\n/**\n * Validation type schema.\n *\n * @remarks\n * Validates the type of validation to perform.\n * - `contract`: Validate a data contract\n * - `event`: Validate a walkerOS event object\n * - `flow`: Validate a flow configuration file\n * - `mapping`: Validate mapping rules\n */\nexport const ValidationTypeSchema = z\n .enum(['contract', 'event', 'flow', 'mapping'])\n .describe('Validation type: \"event\", \"flow\", \"mapping\", or \"contract\"');\n\nexport type ValidationType = z.infer<typeof ValidationTypeSchema>;\n\n/**\n * Validate options schema.\n *\n * @remarks\n * Options for the programmatic validate() API.\n */\nexport const ValidateOptionsSchema = z.object({\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n path: z\n .string()\n .optional()\n .describe(\n 'Entry path for package schema validation (e.g., \"destinations.snowplow\", \"stores.cache\"). Checks the entry in every flow that has it, or only in --flow.',\n ),\n strict: z\n .boolean()\n .optional()\n .describe(\n 'Escalate: strict turns warnings and skips into failures (valid is false), contract disagreements error',\n ),\n offline: z\n .boolean()\n .optional()\n .describe(\n 'Do not fetch package schemas: step settings are not checked against them, and the result scope says so. Only with type \"flow\" and no path.',\n ),\n configDir: z\n .string()\n .optional()\n .describe(\n \"Directory local `path` packages resolve against. Defaults to the input file's directory; set it when passing a parsed document.\",\n ),\n});\n\nexport type ValidateOptions = z.infer<typeof ValidateOptionsSchema>;\n\n/**\n * Raw shape for MCP SDK compatibility (ZodRawShapeCompat).\n *\n * @remarks\n * MCP SDK's registerTool expects raw shapes (Record<string, ZodType>)\n * rather than ZodObject instances. Define shape first, then wrap.\n */\nexport const ValidateInputShape = {\n type: ValidationTypeSchema,\n input: z\n .string()\n .min(1)\n .describe('JSON string, file path, or URL to validate'),\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n path: z\n .string()\n .optional()\n .describe(\n 'Entry path for package schema validation (e.g., \"destinations.snowplow\"). Only with type \"flow\": validates the entry against its package JSON Schema in every flow that has it, or only in the given flow.',\n ),\n strict: z\n .boolean()\n .optional()\n .describe(\n 'Escalate: strict turns warnings and skips into failures: valid is false (the CLI exits 2), and contract example disagreements become errors. Every check runs with or without it.',\n ),\n offline: z\n .boolean()\n .optional()\n .describe(\n 'Do not fetch package schemas: step settings are not checked against them, and details.scope says so. Only with type \"flow\" and no path.',\n ),\n};\n\n/**\n * Validate input schema for MCP tools.\n *\n * @remarks\n * Full input schema including type and input source.\n */\nexport const ValidateInputSchema = z.object(ValidateInputShape);\n\nexport type ValidateInput = z.infer<typeof ValidateInputSchema>;\n","/**\n * Bundle Command Schemas\n *\n * Zod schemas for bundle command parameter validation.\n */\n\nimport { z } from '@walkeros/core/dev';\nimport { FilePathSchema } from './primitives';\n\n/**\n * Bundle options schema.\n *\n * @remarks\n * Options for the programmatic bundle() API.\n */\nexport const BundleOptionsSchema = z.object({\n silent: z.boolean().optional().describe('Suppress all output'),\n verbose: z.boolean().optional().describe('Enable verbose logging'),\n stats: z\n .boolean()\n .optional()\n .default(true)\n .describe('Return bundle statistics'),\n cache: z\n .boolean()\n .optional()\n .default(true)\n .describe('Enable package caching'),\n flowName: z.string().optional().describe('Flow name for multi-flow configs'),\n});\n\nexport type BundleOptions = z.infer<typeof BundleOptionsSchema>;\n\n/**\n * Raw shape for MCP SDK compatibility (ZodRawShapeCompat).\n *\n * @remarks\n * MCP SDK's registerTool expects raw shapes (Record<string, ZodType>)\n * rather than ZodObject instances. Define shape first, then wrap.\n */\nexport const BundleInputShape = {\n configPath: FilePathSchema.describe(\n 'Path to flow configuration file (JSON or JavaScript), URL, or inline JSON string',\n ),\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n stats: z\n .boolean()\n .optional()\n .default(true)\n .describe('Return bundle statistics'),\n output: z\n .string()\n .optional()\n .describe('Output file path (defaults to config-defined)'),\n};\n\n/**\n * Bundle input schema for MCP tools.\n *\n * @remarks\n * Full input schema including config path and options.\n */\nexport const BundleInputSchema = z.object(BundleInputShape);\n\nexport type BundleInput = z.infer<typeof BundleInputSchema>;\n","/**\n * Simulate Command Schemas\n *\n * Zod schemas for simulate command parameter validation.\n */\n\nimport { z } from '@walkeros/core/dev';\nimport { FilePathSchema } from './primitives';\n\n/**\n * Platform schema.\n *\n * @remarks\n * Validates platform type for event simulation.\n */\nexport const PlatformSchema = z\n .enum(['web', 'server'])\n .describe('Platform type for event processing');\n\nexport type Platform = z.infer<typeof PlatformSchema>;\n\n/**\n * Simulate options schema.\n *\n * @remarks\n * Options for the programmatic simulate() API.\n */\nexport const SimulateOptionsSchema = z.object({\n silent: z.boolean().optional().describe('Suppress all output'),\n verbose: z.boolean().optional().describe('Enable verbose logging'),\n json: z.boolean().optional().describe('Format output as JSON'),\n});\n\nexport type SimulateOptions = z.infer<typeof SimulateOptionsSchema>;\n\n/**\n * Raw shape for MCP SDK compatibility (ZodRawShapeCompat).\n *\n * @remarks\n * MCP SDK's registerTool expects raw shapes (Record<string, ZodType>)\n * rather than ZodObject instances. Define shape first, then wrap.\n */\nexport const SimulateInputShape = {\n configPath: FilePathSchema.describe(\n 'Path to flow configuration file, URL, or inline JSON string',\n ),\n event: z\n .string()\n .min(1)\n .optional()\n .describe(\n 'Event as JSON string, file path, or URL. For sources: { content, trigger?, env? }.',\n ),\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n platform: PlatformSchema.optional().describe('Override platform detection'),\n step: z\n .string()\n .optional()\n .describe(\n 'Step target in type.name format (e.g. \"source.browser\", \"destination.gtag\")',\n ),\n};\n\n/**\n * Simulate input schema for MCP tools.\n *\n * @remarks\n * Full input schema including config path, event, and options.\n */\nexport const SimulateInputSchema = z.object(SimulateInputShape);\n\nexport type SimulateInput = z.infer<typeof SimulateInputSchema>;\n","/**\n * Push Command Schemas\n *\n * Zod schemas for push command parameter validation.\n */\n\nimport { z } from '@walkeros/core/dev';\nimport { FilePathSchema } from './primitives';\nimport { PlatformSchema } from './simulate';\n\n/**\n * Push options schema.\n *\n * @remarks\n * Options for the programmatic push() API.\n */\nexport const PushOptionsSchema = z.object({\n silent: z.boolean().optional().describe('Suppress all output'),\n verbose: z.boolean().optional().describe('Enable verbose logging'),\n json: z.boolean().optional().describe('Format output as JSON'),\n});\n\nexport type PushOptions = z.infer<typeof PushOptionsSchema>;\n\n/**\n * Raw shape for MCP SDK compatibility (ZodRawShapeCompat).\n *\n * @remarks\n * MCP SDK's registerTool expects raw shapes (Record<string, ZodType>)\n * rather than ZodObject instances. Define shape first, then wrap.\n */\nexport const PushInputShape = {\n configPath: FilePathSchema.describe('Path to flow configuration file'),\n event: z.string().min(1).describe('Event as JSON string, file path, or URL'),\n flow: z.string().optional().describe('Flow name for multi-flow configs'),\n platform: PlatformSchema.optional().describe('Override platform detection'),\n};\n\n/**\n * Push input schema for MCP tools.\n *\n * @remarks\n * Full input schema including config path, event, and options.\n */\nexport const PushInputSchema = z.object(PushInputShape);\n\nexport type PushInput = z.infer<typeof PushInputSchema>;\n","/**\n * Shared resolver for the export name to import from a flow component's\n * package.\n *\n * Both `walkeros bundle` and `walkeros setup` need to know which named export\n * (or default) to pull off a package referenced by a flow component. The\n * precedence chain is:\n *\n * 1. `flow.<kind>.<id>.import` if set (named export selector at the step).\n * 2. `flow.config.bundle.packages[<package>].imports[0]` if set.\n * 3. Otherwise undefined; the caller falls back to the package's `default`\n * export.\n *\n * This lives in `cli/src/core/` so both `commands/bundle/*` and\n * `commands/setup/*` import the same function. Duplicating the chain is how\n * setup ended up out of sync with bundle (Bug F: `setup destination.pubsub`\n * routed through BigQuery's setup because it ignored the `code` field and\n * always grabbed `mod.default`).\n */\n\nimport type { Flow, StepType } from '@walkeros/core';\n\nexport type ComponentKind = StepType;\n\nexport type ResolveSource = 'import' | 'imports' | 'default';\n\nexport interface ResolvedExportName {\n /**\n * The named export to pull off the imported module, or `undefined` to\n * indicate the caller should use the package's `default` export.\n */\n exportName: string | undefined;\n /** Which precedence step produced the result (useful for diagnostics). */\n source: ResolveSource;\n}\n\ninterface FlowStepView {\n package?: string;\n import?: string;\n}\n\nfunction getStep(\n flow: Flow,\n kind: ComponentKind,\n id: string,\n): FlowStepView | undefined {\n switch (kind) {\n case 'source':\n return flow.sources?.[id];\n case 'transformer':\n return flow.transformers?.[id];\n case 'destination':\n return flow.destinations?.[id];\n case 'store':\n return flow.stores?.[id];\n }\n}\n\nfunction getBundlePackages(\n flow: Flow,\n): Record<string, Flow.BundlePackage> | undefined {\n return flow.config?.bundle?.packages;\n}\n\n/**\n * Read the first entry of `bundle.packages[<package>].imports` if it is a\n * non-empty string. Returns `undefined` otherwise.\n */\nfunction readFirstImport(\n packages: Record<string, Flow.BundlePackage> | undefined,\n packageName: string | undefined,\n): string | undefined {\n if (!packages || !packageName) return undefined;\n const pkg = packages[packageName];\n if (!pkg || !pkg.imports || pkg.imports.length === 0) return undefined;\n const first = pkg.imports[0];\n return typeof first === 'string' && first.length > 0 ? first : undefined;\n}\n\n/**\n * Resolve the export name to import for a flow component's package.\n *\n * See module docs for the precedence chain. Inline code (`code` is an object)\n * doesn't enter this resolver at all — setup rejects inline code at a higher\n * layer.\n */\nexport function resolveExportName(\n flow: Flow,\n kind: ComponentKind,\n id: string,\n): ResolvedExportName {\n const step = getStep(flow, kind, id);\n if (!step) return { exportName: undefined, source: 'default' };\n\n const packageName = step.package;\n const importName = step.import;\n\n // 1. Explicit `import` field on the step wins.\n if (typeof importName === 'string' && importName.length > 0) {\n return { exportName: importName, source: 'import' };\n }\n\n // 2. Fallback to bundle.packages[pkg].imports[0].\n const firstImport = readFirstImport(getBundlePackages(flow), packageName);\n if (firstImport) {\n return { exportName: firstImport, source: 'imports' };\n }\n\n // 3. Default export.\n return { exportName: undefined, source: 'default' };\n}\n","function isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object';\n}\n\n/**\n * Selects the dev examples of one export from a package's awaited `/dev`\n * module.\n *\n * A package with several exports (`walkerOS.exports` in its package.json)\n * ships `exportExamples`, a map from export name to that export's examples,\n * the default export included. A package with one export ships only\n * `examples`.\n *\n * - Map present, export named: `exportExamples[exportName]`. A name missing\n * from the map resolves to `undefined`, never to another export's examples.\n * - Map present, no export name (the step uses the default export):\n * `examples`, which by convention holds the default export's examples.\n * - No map: `examples`.\n *\n * `exportName` comes from `resolveExportName` (step `import`, else\n * `bundle.packages[pkg].imports[0]`, else default).\n */\nexport function selectDevExamples(\n devModule: unknown,\n exportName: string | undefined,\n): Record<string, unknown> | undefined {\n if (!isRecord(devModule)) return undefined;\n\n const map = devModule.exportExamples;\n if (isRecord(map) && exportName !== undefined) {\n const selected = map[exportName];\n return isRecord(selected) ? selected : undefined;\n }\n\n const examples = devModule.examples;\n return isRecord(examples) ? examples : undefined;\n}\n\n/**\n * A package version from before export-keyed examples ships only\n * `examples` (the default export's), even when it declares several\n * exports. For a step naming an export, those examples may belong to\n * another export, so simulate must refuse instead of running that export's\n * mock (or none) against the real vendor. Returns the refusal message, or\n * `undefined` when the examples can be trusted.\n *\n * `packageExports` is the bundle's `__packageExports` (declared exports per\n * package, read at build time from the bundled copy). A bundle without it\n * (built before it existed) cannot tell single- from multi-export packages,\n * so a step naming an export without a map is refused.\n */\nexport function legacyExportRefusal(\n devModule: unknown,\n packageExports: Record<string, string[]> | undefined,\n packageName: string,\n exportName: string | undefined,\n): string | undefined {\n if (exportName === undefined) return undefined;\n if (isRecord(devModule) && isRecord(devModule.exportExamples))\n return undefined;\n if (packageExports) {\n const declared = packageExports[packageName];\n if (!declared || declared.length <= 1) return undefined;\n }\n return `No mock env for ${packageName} export ${exportName}: this package version predates export-keyed examples; use a version with exportExamples or a local path.`;\n}\n","/**\n * Step-package normalization shared by bundle, setup, validate and the MCP's\n * flow_examples.\n *\n * Pure flow-config logic: which packages do the flow's steps declare, and\n * what is the effective {name, version | path} for each after merging inline\n * step specs with config.bundle.packages pins. Lives in core/ so every\n * command and tool that reads a step's package runs the exact same precedence\n * (a bundle pin always wins; an unversioned bundle entry is filled from the\n * first inline version; conflicting inline versions with no pin throw;\n * local paths become synthetic packageNameToVariable keys).\n */\nimport type { Flow, Logger } from '@walkeros/core';\nimport { packageNameToVariable } from '@walkeros/core';\nimport type { ComponentKind } from './resolve-export-name.js';\n\n/**\n * Type-narrowed accessor for a Flow section. Returns the typed step record\n * (or undefined) — exhaustive switch over the literal-union parameter avoids\n * a generic indexed-access cast.\n *\n * Returns the union of all section types when the caller passes a runtime\n * variable. Call sites that need a specific section type access the field\n * directly (e.g. `flow.sources`).\n */\nexport type FlowStepRecord =\n | Record<string, Flow.Source>\n | Record<string, Flow.Destination>\n | Record<string, Flow.Transformer>\n | Record<string, Flow.Store>;\nexport function getFlowSection(\n flow: Flow,\n section: 'sources' | 'destinations' | 'transformers' | 'stores',\n): FlowStepRecord | undefined {\n switch (section) {\n case 'sources':\n return flow.sources;\n case 'destinations':\n return flow.destinations;\n case 'transformers':\n return flow.transformers;\n case 'stores':\n return flow.stores;\n }\n}\n\n/** A step package spec that is a local path (`./x`, `../x`, `/abs/x`). */\nfunction isLocalPath(spec: string): boolean {\n return spec.startsWith('.') || spec.startsWith('/');\n}\n\n/**\n * Split a step package spec into bare name and optional version suffix.\n * `@walkeros/x@1.2.3` → { name: '@walkeros/x', version: '1.2.3' }.\n * The scope `@` at index 0 is never a separator. A trailing `@` is ignored.\n * Alias/git/file suffixes are not interpreted — the resolver handles or\n * rejects them downstream.\n */\nexport function parsePackageSpec(spec: string): {\n name: string;\n version?: string;\n} {\n const at = spec.lastIndexOf('@');\n if (at <= 0) return { name: spec };\n const version = spec.slice(at + 1);\n return version\n ? { name: spec.slice(0, at), version }\n : { name: spec.slice(0, at) };\n}\n\n/**\n * Detects destination packages from flow configuration.\n * Extracts package names from destinations that have explicit 'package' field.\n */\n/**\n * Detects packages from a flow config section (sources, destinations, transformers, stores).\n * Extracts package names from steps that have an explicit 'package' field.\n */\nexport function detectStepPackages(\n flowSettings: Flow,\n section: 'sources' | 'destinations' | 'transformers' | 'stores',\n): Set<string> {\n const packages = new Set<string>();\n const steps = getFlowSection(flowSettings, section);\n\n if (steps) {\n for (const [, stepConfig] of Object.entries(steps)) {\n if (typeof stepConfig !== 'object' || stepConfig === null) continue;\n // Require explicit package field\n if (typeof stepConfig.package === 'string') {\n packages.add(stepConfig.package);\n }\n }\n }\n\n return packages;\n}\n\n/**\n * Collects all package names declared in flow steps.\n * Returns both npm packages and local paths — caller handles routing.\n */\nexport function collectAllStepPackages(flowSettings: Flow): Set<string> {\n const allPackages = new Set<string>();\n const sections = [\n 'sources',\n 'destinations',\n 'transformers',\n 'stores',\n ] as const;\n\n for (const section of sections) {\n for (const pkg of detectStepPackages(flowSettings, section)) {\n allPackages.add(pkg);\n }\n }\n\n return allPackages;\n}\n\n/**\n * Auto-adds every step-declared package (sources, destinations, transformers,\n * stores) to `packages`, mutating `flowSettings` in place so each step's\n * `package` field points at the key that ends up in `packages`.\n *\n * Local paths (`.` or `/` prefixed) are normalized to a synthetic\n * `packageNameToVariable` key so the regular default-import codegen wires\n * them up automatically.\n *\n * npm specs go through `parsePackageSpec` to split an inline version\n * (`@walkeros/x@1.2.3`) from the bare name. Precedence policy:\n * - An explicit `config.bundle.packages` version always wins; a disagreeing\n * inline version only warns (bundle pin is authoritative).\n * - An unversioned bundle entry is filled from the first inline version seen\n * for that bare name, preserving any other fields already on the entry.\n * - Two different inline versions for the same bare name, with no bundle\n * pin to arbitrate, are ambiguous — throw naming both steps' versions\n * rather than silently picking one.\n * - Identical inline versions across steps are fine (no-op).\n * Alias/git/file suffixes are not special-cased: `parsePackageSpec` splits on\n * the last `@` and the resolver handles or rejects the rest downstream.\n */\nexport function applyStepPackages(\n flowSettings: Flow,\n packages: Record<string, Flow.BundlePackage>,\n logger: Logger.Instance,\n): void {\n const stepPackages = collectAllStepPackages(flowSettings);\n // Bundle-pinned version per bare name, captured the first time each name is\n // encountered — i.e. before this function's own fill-ins can be mistaken\n // for a real `config.bundle.packages` pin on a later iteration.\n const originalPins = new Map<string, boolean>();\n // Inline version already seen per bare name (with no real bundle pin),\n // used to detect a second, different inline version for the same name.\n const inlineSeen = new Map<string, string>();\n\n const rewriteSteps = (from: string, to: string): void => {\n for (const section of [\n 'sources',\n 'destinations',\n 'transformers',\n 'stores',\n ] as const) {\n const steps = getFlowSection(flowSettings, section);\n if (!steps) continue;\n for (const step of Object.values(steps)) {\n if (step.package === from) {\n step.package = to;\n }\n }\n }\n };\n\n for (const pkg of stepPackages) {\n if (isLocalPath(pkg)) {\n // Normalize: convert path-based package: to packages section entry.\n // The synthetic key acts as the package name for downstream codegen,\n // so the regular default-import flow wires it up automatically.\n const varName = packageNameToVariable(pkg);\n if (!packages[varName]) {\n packages[varName] = {\n path: pkg,\n };\n }\n\n // Rewrite all components that reference the raw path to point at the\n // synthetic packages-section key instead.\n rewriteSteps(pkg, varName);\n continue;\n }\n\n const { name, version } = parsePackageSpec(pkg);\n\n if (!originalPins.has(name)) {\n const entry = packages[name];\n // A `path` entry is a pin too: local paths win at resolution, so the\n // inline versions the steps declare can never be used.\n originalPins.set(\n name,\n entry?.version !== undefined || entry?.path !== undefined,\n );\n }\n const hasBundlePin = originalPins.get(name) === true;\n\n if (name !== pkg) {\n // Rewrite every step that declared the versioned spec to the bare\n // name, mirroring the local-path rewrite above.\n rewriteSteps(pkg, name);\n }\n\n if (version && !hasBundlePin) {\n const seen = inlineSeen.get(name);\n if (seen !== undefined && seen !== version) {\n throw new Error(\n `Conflicting inline versions for ${name}: \"${seen}\" and \"${version}\" are ` +\n `declared by different steps. Pin one version in config.bundle.packages.`,\n );\n }\n inlineSeen.set(name, version);\n }\n\n const existing = packages[name];\n if (!existing) {\n packages[name] = version ? { version } : {};\n } else if (version && !existing.path) {\n // A path entry decides on its own; stamping a version onto it would\n // record a version that resolution never consults.\n if (!existing.version) {\n existing.version = version; // fill an unversioned bundle entry\n } else if (existing.version !== version) {\n logger.warn(\n `Package ${name}: config.bundle.packages pins ${existing.version}; ` +\n `a step declares ${version} inline. Using the bundle pin.`,\n );\n }\n }\n }\n}\n\nexport interface ResolvedStepPackage {\n /** Bare package name after normalization (inline version stripped, local path replaced by synthetic key). */\n packageName: string;\n /** The package as messages and results name it: the bare npm name, or a step's own local path as written. */\n label: string;\n /** Effective bundle entry: version pin and/or local path per bundle precedence. */\n spec: Flow.BundlePackage;\n /** flow.config.bundle.overrides, for transitive pins. */\n overrides: Record<string, string>;\n /** Deep clone of the flow with step.package rewritten to bare names; the input flow is never mutated. */\n normalizedFlow: Flow;\n}\n\nconst KIND_TO_SECTION = {\n source: 'sources',\n transformer: 'transformers',\n destination: 'destinations',\n store: 'stores',\n} as const;\n\n/**\n * Resolve the effective package spec for one step by running the SAME\n * normalization the bundler runs over the whole flow (applyStepPackages),\n * on a clone so the caller's flow stays untouched. The clone comes back as\n * `normalizedFlow` with `step.package` rewritten to the bare name, which is\n * also what resolveExportName needs to match `bundle.packages[pkg].imports`.\n */\nexport function resolveStepPackage(\n flow: Flow,\n kind: ComponentKind,\n id: string,\n logger: Logger.Instance,\n): ResolvedStepPackage {\n const normalizedFlow = structuredClone(flow);\n const packages: Record<string, Flow.BundlePackage> = structuredClone(\n normalizedFlow.config?.bundle?.packages ?? {},\n );\n applyStepPackages(normalizedFlow, packages, logger);\n\n const bucket = getFlowSection(normalizedFlow, KIND_TO_SECTION[kind]);\n const step = bucket?.[id];\n if (!step) {\n const available = Object.keys(bucket ?? {}).join(', ') || '(none)';\n throw new Error(\n `${kind} \"${id}\" not found in flow. Available: ${available}`,\n );\n }\n if (typeof step.package !== 'string') {\n throw new Error(\n `${kind}.${id} has no \"package\" (inline code cannot be set up).`,\n );\n }\n\n const declared = getFlowSection(flow, KIND_TO_SECTION[kind])?.[id]?.package;\n return {\n packageName: step.package,\n label:\n declared !== undefined && isLocalPath(declared) ? declared : step.package,\n spec: packages[step.package] ?? {},\n overrides: normalizedFlow.config?.bundle?.overrides ?? {},\n normalizedFlow,\n };\n}\n","/**\n * The walkerOS metadata of a step's package, read from the source\n * resolveStepPackage picked: a local path from its walkerOS.json on disk,\n * any other package from the CDN at the pinned version. Every tool that has\n * a flow reads a step's package here, so all of them read the same source\n * the bundle installs.\n *\n * Node built-ins only: this module is reachable from the `dev` and\n * `validate` entries, which a server process loads without the bundler or\n * the package manager.\n */\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { WalkerOSPackage } from '@walkeros/core';\nimport { fetchPackage, isObject, parseWalkerOSJson } from '@walkeros/core';\nimport type { ResolvedStepPackage } from './step-packages.js';\n\n/** A package's walkerOS.json content, plus the version read (absent for a local package whose package.json names none). */\nexport type StepPackageInfo = Omit<\n WalkerOSPackage,\n 'packageName' | 'version' | 'description'\n> & {\n version?: string;\n};\n\nfunction readJson(file: string): unknown {\n return JSON.parse(fs.readFileSync(file, 'utf-8'));\n}\n\n/**\n * Read the walkerOS metadata of a resolved step package. A local path\n * resolves against `configDir`; without one nothing is read from disk and\n * the read fails. `client` names the calling tool in the CDN request.\n */\nexport async function readStepPackageInfo(\n resolved: Pick<ResolvedStepPackage, 'packageName' | 'spec'>,\n options: { configDir?: string; client: string },\n): Promise<StepPackageInfo> {\n const { packageName, spec } = resolved;\n if (spec.path === undefined)\n return fetchPackage(packageName, {\n ...(spec.version ? { version: spec.version } : {}),\n client: options.client,\n });\n\n if (options.configDir === undefined)\n throw new Error(\n 'it is a local path package and the input is not a file, so there is no directory to read it from',\n );\n const root = path.isAbsolute(spec.path)\n ? spec.path\n : path.resolve(options.configDir, spec.path);\n const file = [\n path.join(root, 'dist', 'walkerOS.json'),\n path.join(root, 'walkerOS.json'),\n ].find((candidate) => fs.existsSync(candidate));\n if (!file) throw new Error(`no walkerOS.json under ${root}`);\n const meta = readJson(file);\n if (!isObject(meta)) throw new Error(`${file} is not a JSON object`);\n const pkgFile = path.join(root, 'package.json');\n const pkg = fs.existsSync(pkgFile) ? readJson(pkgFile) : undefined;\n const version =\n isObject(pkg) && typeof pkg.version === 'string' ? pkg.version : undefined;\n return { ...parseWalkerOSJson(meta), ...(version ? { version } : {}) };\n}\n"],"mappings":"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","names":["z","z","z","z","z","z","z"]}
@@ -49,12 +49,23 @@ npx --package=@walkeros/runner runneros start dist/server/flow.mjs
49
49
  # Web flow: build walker.js, then serve dist/web/ with any static server
50
50
  walkeros bundle examples/flow-complete.json --flow web -o dist/web/
51
51
 
52
- # Test either flow offline, destinations mocked
52
+ # Test the web flow without sending anything, destinations mocked
53
+ walkeros push examples/flow-complete.json --flow web \
54
+ --event '{"name":"page view","data":{"title":"Home"}}' \
55
+ --consent '{"functional":true}' --simulate destination.ga4
56
+
57
+ # The server flow needs GCP_SA, FINGERPRINT_SALT and EMAIL_SALT set (see the
58
+ # setup in flow-complete.md) and a request context for its fingerprint step
53
59
  walkeros push examples/flow-complete.json --flow server \
54
60
  --event '{"name":"page view","data":{"title":"Home"}}' \
61
+ --ingest '{"ip":"203.0.113.7","userAgent":"Mozilla/5.0"}' \
55
62
  --simulate destination.pubsub
56
63
  ```
57
64
 
65
+ Without `GCP_SA` a server simulation stops with
66
+ `required secret "GCP_SA" is not set`; without `--ingest` the fingerprint step
67
+ drops the event and Pub/Sub records `no calls`.
68
+
58
69
  ---
59
70
 
60
71
  ## Web Examples