@zerodot/node-sdk 1.0.0 → 1.1.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.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,17 @@
1
1
  import { z } from "zod";
2
+ /**
3
+ * Binary data in a node output. zerodot has no separate binary store, so the bytes are base64
4
+ * text under `binary.<property>` in the JSON output. The size limit of a node output applies.
5
+ */
6
+ type BinaryData = {
7
+ data: string;
8
+ mimeType: string;
9
+ fileName?: string;
10
+ };
11
+ export declare function mimeTypeOf(fileName: string): string;
12
+ export declare function toBinary(bytes: Uint8Array, fileName: string, mimeType?: string): BinaryData;
13
+ /** The binary data that an earlier node put under `input.binary[property]`. */
14
+ export declare function readBinary(input: unknown, property: string): BinaryData;
2
15
  declare const sandboxRequestSchema: z.ZodObject<{
3
16
  code: z.ZodString;
4
17
  scope: z.ZodRecord<z.ZodString, z.ZodUnknown>;
@@ -419,11 +432,6 @@ type NodeDefinition<Schema extends z.ZodType = z.ZodType> = {
419
432
  listen?(ctx: ListenContext<z.output<Schema>>): Promise<ListenHandle>;
420
433
  /** Output ports that depend on the config (a switch has one port for each case). */
421
434
  outPorts?(config: Record<string, unknown>): string[];
422
- /**
423
- * Data form of `outPorts`, for a node whose code the browser does not have (an adapted n8n
424
- * node). The catalog carries it, so the editor can draw the ports.
425
- */
426
- outPortsKind?: "n8n-switch";
427
435
  run(ctx: NodeRunContext<z.output<Schema>>): Promise<NodeResult> | NodeResult;
428
436
  };
429
437
  export declare function defineNode<Schema extends z.ZodType>(definition: NodeDefinition<Schema>): NodeDefinition<Schema>;
@@ -465,6 +473,43 @@ type CredentialTypeDefinition = {
465
473
  };
466
474
  /** A string with one `` and nothing else keeps the value type. Otherwise the result is text. */
467
475
  export declare function resolveTemplate(input: string, scope: Record<string, unknown>): unknown;
476
+ /** Resolve every string inside a config value. Errors carry the path to the bad value. */
477
+ export declare function resolveConfig(value: unknown, scope: Record<string, unknown>, path?: string): unknown;
478
+ /**
479
+ * The shape of a nested field (a collection or a fixed collection), as plain data. A node writes
480
+ * it into the JSON Schema of its config. The editor draws a form from it.
481
+ * A key of a condition that starts with "/" reads from the top level of the config.
482
+ */
483
+ type FieldSpec = {
484
+ name: string;
485
+ label: string;
486
+ kind: "string" | "number" | "boolean" | "options" | "filter" | "collection" | "fixed";
487
+ description?: string;
488
+ placeholder?: string;
489
+ default?: unknown;
490
+ multiline?: boolean;
491
+ options?: {
492
+ value: string | number | boolean;
493
+ label: string;
494
+ hint?: string;
495
+ }[];
496
+ show?: FieldCondition | FieldCondition[];
497
+ hide?: FieldCondition;
498
+ /** `collection`: the fields that the user can add. */
499
+ fields?: FieldSpec[];
500
+ /** `fixed`: the groups. A group holds a list when `multiple` is set, or one object. */
501
+ groups?: {
502
+ name: string;
503
+ label: string;
504
+ fields: FieldSpec[];
505
+ }[];
506
+ multiple?: boolean;
507
+ };
508
+ /** One item of a node run: a plain object. */
509
+ type Item = Record<string, unknown>;
510
+ export declare const isRecord: (value: unknown) => value is Item;
511
+ /** The items of a node run. A list is the items. One object is one item. Null is one empty item. */
512
+ export declare function toItems(input: unknown): Item[];
468
513
  /**
469
514
  * Reads an icon file of a package and returns it as a data URL, for `iconUrl` of a node or a
470
515
  * credential type. `from` is `import.meta.url` of the file that calls it, and `path` is relative
@@ -476,11 +521,11 @@ export declare function fileIcon(from: string, path: string): string;
476
521
  * Version of the node contract (the shape of `NodeDefinition` and what a node can use).
477
522
  * A minor version only adds. A major version can break a node package.
478
523
  */
479
- export declare const SDK_VERSION = "1.0.0";
524
+ export declare const SDK_VERSION = "1.1.0";
480
525
  /**
481
526
  * True when `version` fits `range`. A range is a caret range (`^1.4`, `^1.4.2`) or one exact
482
527
  * version (`1.4.2`). A caret range allows the same major version, from the given version up.
483
528
  * For major 0 it allows the same minor version only, as npm does.
484
529
  */
485
530
  export declare function satisfiesSdk(range: string, version?: string): boolean;
486
- export type { CredentialTypeDefinition, ListenContext, ListenHandle, NodeCategory, NodeDefinition, NodeResult, NodeRunContext, NodeWebhook, OAuth2Config, PollContext, PollItem, PollResult, ResolvedCredential, ShowRules, WaitForm, WaitFormField, WebhookContext, WebhookRequest, WebhookVerdict };
531
+ export type { BinaryData, CredentialTypeDefinition, FieldSpec, Item, ListenContext, ListenHandle, NodeCategory, NodeDefinition, NodeResult, NodeRunContext, NodeWebhook, OAuth2Config, PollContext, PollItem, PollResult, ResolvedCredential, ShowRules, WaitForm, WaitFormField, WebhookContext, WebhookRequest, WebhookVerdict };
package/dist/index.mjs CHANGED
@@ -2,6 +2,46 @@ import { z } from "zod";
2
2
  import { readFileSync } from "node:fs";
3
3
  import { extname } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
+ // ../engine/src/binary.ts
6
+ const MIME = {
7
+ jpg: "image/jpeg",
8
+ jpeg: "image/jpeg",
9
+ png: "image/png",
10
+ gif: "image/gif",
11
+ webp: "image/webp",
12
+ mp4: "video/mp4",
13
+ mov: "video/quicktime",
14
+ mp3: "audio/mpeg",
15
+ ogg: "audio/ogg",
16
+ oga: "audio/ogg",
17
+ wav: "audio/wav",
18
+ pdf: "application/pdf",
19
+ txt: "text/plain",
20
+ json: "application/json",
21
+ csv: "text/csv",
22
+ zip: "application/zip",
23
+ tgs: "application/x-tgsticker"
24
+ };
25
+ function mimeTypeOf(fileName) {
26
+ return MIME[fileName.split(".").pop()?.toLowerCase() ?? ""] ?? "application/octet-stream";
27
+ }
28
+ function toBinary(bytes, fileName, mimeType) {
29
+ return {
30
+ data: Buffer.from(bytes).toString("base64"),
31
+ mimeType: mimeType ?? mimeTypeOf(fileName),
32
+ fileName
33
+ };
34
+ }
35
+ /** The binary data that an earlier node put under `input.binary[property]`. */
36
+ function readBinary(input, property) {
37
+ const found = (input?.binary)?.[property];
38
+ if (!found || typeof found.data !== "string") throw new Error(`The input has no binary data in the property "${property}"`);
39
+ return {
40
+ data: found.data,
41
+ mimeType: found.mimeType ?? "application/octet-stream",
42
+ fileName: found.fileName
43
+ };
44
+ }
5
45
  // ../engine/src/expression.ts
6
46
  /**
7
47
  * Small safe expression evaluator. No eval, no new Function, no function calls.
@@ -389,6 +429,21 @@ function resolveTemplate(input, scope) {
389
429
  if (only && "expression" in only) return evaluateExpression(only.expression, scope);
390
430
  return segments.map((s) => "text" in s ? s.text : stringify(evaluateExpression(s.expression, scope))).join("");
391
431
  }
432
+ /** Resolve every string inside a config value. Errors carry the path to the bad value. */
433
+ function resolveConfig(value, scope, path = "config") {
434
+ if (typeof value === "string") try {
435
+ return resolveTemplate(value, scope);
436
+ } catch (error) {
437
+ if (error instanceof ExpressionError) {
438
+ const inner = error.path ? ` [${error.path}]` : "";
439
+ throw new ExpressionError(`${error.detail}${inner}`, path);
440
+ }
441
+ throw error;
442
+ }
443
+ if (Array.isArray(value)) return value.map((item, index) => resolveConfig(item, scope, `${path}[${index}]`));
444
+ if (value !== null && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, resolveConfig(item, scope, `${path}.${key}`)]));
445
+ return value;
446
+ }
392
447
  // ../engine/src/graph.ts
393
448
  const retrySchema = z.object({
394
449
  max: z.number().int().min(1).max(10),
@@ -460,6 +515,15 @@ graphSchema.extend({
460
515
  name: z.string().trim().min(1).max(120).optional(),
461
516
  variables: z.array(z.string()).optional()
462
517
  });
518
+ // ../engine/src/items.ts
519
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
520
+ /** The items of a node run. A list is the items. One object is one item. Null is one empty item. */
521
+ function toItems(input) {
522
+ if (Array.isArray(input)) return input.map((item) => isRecord(item) ? item : { value: item });
523
+ if (isRecord(input)) return [input];
524
+ if (input === null || input === void 0) return [{}];
525
+ return [{ value: input }];
526
+ }
463
527
  z.object({
464
528
  code: z.string().min(1).max(2e5),
465
529
  /** Names the code can read, for example `$input` and `$vars`. Plain JSON values only. */
@@ -661,7 +725,7 @@ function fileIcon(from, path) {
661
725
  * Version of the node contract (the shape of `NodeDefinition` and what a node can use).
662
726
  * A minor version only adds. A major version can break a node package.
663
727
  */
664
- const SDK_VERSION = "1.0.0";
728
+ const SDK_VERSION = "1.1.0";
665
729
  function parse(text) {
666
730
  const match = /^(\d+)(?:\.(\d+))?(?:\.(\d+))?$/.exec(text.trim());
667
731
  if (!match) return null;
@@ -691,4 +755,4 @@ function satisfiesSdk(range, version = SDK_VERSION) {
691
755
  const exact = parse(text);
692
756
  return exact !== null && compare(actual, exact) === 0;
693
757
  }
694
- export { FORM_FIELD_TYPES, POLL_MAX_ITEMS, SDK_VERSION, defineNode, fileIcon, resolveTemplate, satisfiesSdk };
758
+ export { FORM_FIELD_TYPES, POLL_MAX_ITEMS, SDK_VERSION, defineNode, fileIcon, isRecord, mimeTypeOf, readBinary, resolveConfig, resolveTemplate, satisfiesSdk, toBinary, toItems };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerodot/node-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Contract for zerodot node packages: node types, helpers and the SDK version.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {