@run402/sdk 2.45.0 → 2.47.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 (45) hide show
  1. package/README.md +10 -11
  2. package/dist/index.d.ts +4 -4
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +4 -4
  5. package/dist/index.js.map +1 -1
  6. package/dist/namespaces/assets.d.ts.map +1 -1
  7. package/dist/namespaces/assets.js +26 -2
  8. package/dist/namespaces/assets.js.map +1 -1
  9. package/dist/namespaces/deploy.d.ts +1 -1
  10. package/dist/namespaces/deploy.d.ts.map +1 -1
  11. package/dist/namespaces/deploy.js +145 -18
  12. package/dist/namespaces/deploy.js.map +1 -1
  13. package/dist/namespaces/deploy.types.d.ts +19 -10
  14. package/dist/namespaces/deploy.types.d.ts.map +1 -1
  15. package/dist/namespaces/deploy.types.js +3 -3
  16. package/dist/namespaces/deploy.types.js.map +1 -1
  17. package/dist/namespaces/jobs.d.ts +15 -4
  18. package/dist/namespaces/jobs.d.ts.map +1 -1
  19. package/dist/namespaces/jobs.js +19 -1
  20. package/dist/namespaces/jobs.js.map +1 -1
  21. package/dist/namespaces/projects.d.ts +1 -1
  22. package/dist/namespaces/projects.d.ts.map +1 -1
  23. package/dist/namespaces/projects.js +40 -6
  24. package/dist/namespaces/projects.js.map +1 -1
  25. package/dist/namespaces/projects.types.d.ts +7 -0
  26. package/dist/namespaces/projects.types.d.ts.map +1 -1
  27. package/dist/node/deploy-manifest.d.ts +9 -8
  28. package/dist/node/deploy-manifest.d.ts.map +1 -1
  29. package/dist/node/deploy-manifest.js +82 -33
  30. package/dist/node/deploy-manifest.js.map +1 -1
  31. package/dist/node/files.d.ts +2 -2
  32. package/dist/node/files.js +2 -2
  33. package/dist/node/index.d.ts +2 -2
  34. package/dist/node/index.d.ts.map +1 -1
  35. package/dist/node/index.js +2 -2
  36. package/dist/node/index.js.map +1 -1
  37. package/dist/node/sites-node.d.ts +3 -3
  38. package/dist/node/sites-node.js +3 -3
  39. package/dist/retry.d.ts +1 -1
  40. package/dist/retry.js +1 -1
  41. package/dist/scoped.d.ts +10 -21
  42. package/dist/scoped.d.ts.map +1 -1
  43. package/dist/scoped.js +40 -78
  44. package/dist/scoped.js.map +1 -1
  45. package/package.json +1 -1
@@ -159,7 +159,7 @@ export class Deploy {
159
159
  await uploadMissing(this.client, opts.project, plan.missing_content, opts.byteReaders, emit);
160
160
  }
161
161
  /**
162
- * Low-level commit: `POST /apply/v1/plans/:id/commit`, then poll
162
+ * Low-level commit: `POST /apply/v1/plans/:plan_id/commit`, then poll
163
163
  * `/operations/:id` until terminal. Pass the project id whose anon_key
164
164
  * should authenticate the polling — the operations endpoint requires
165
165
  * apikey auth even though the plan/commit endpoints accept SIWX.
@@ -297,9 +297,9 @@ export class Deploy {
297
297
  const limit = typeof opts === "string" ? undefined : opts?.limit;
298
298
  const cursor = typeof opts === "string" ? undefined : opts?.cursor;
299
299
  if (!project) {
300
- throw new LocalError("r.deploy.list requires a project id (as a string or { project: 'prj_...' })", "listing deploy operations");
300
+ throw new LocalError("apply.list requires a project id (as a string or { project: 'prj_...' })", "listing deploy operations");
301
301
  }
302
- const normalizedLimit = normalizePositiveSafeIntegerQueryOption(limit, "r.deploy.list limit", "listing deploy operations");
302
+ const normalizedLimit = normalizePositiveSafeIntegerQueryOption(limit, "apply.list limit", "listing deploy operations");
303
303
  const headers = await apikeyHeaders(this.client, project);
304
304
  const qs = new URLSearchParams();
305
305
  if (normalizedLimit !== undefined)
@@ -346,12 +346,12 @@ export class Deploy {
346
346
  */
347
347
  async getRelease(opts) {
348
348
  if (!opts?.project) {
349
- throw new LocalError("r.deploy.getRelease requires a project id ({ project: 'prj_...', releaseId: 'rel_...' })", "fetching release inventory");
349
+ throw new LocalError("apply.getRelease requires a project id ({ project: 'prj_...', releaseId: 'rel_...' })", "fetching release inventory");
350
350
  }
351
351
  if (!opts.releaseId) {
352
- throw new LocalError("r.deploy.getRelease requires a release id", "fetching release inventory");
352
+ throw new LocalError("apply.getRelease requires a release id", "fetching release inventory");
353
353
  }
354
- const siteLimit = normalizePositiveSafeIntegerQueryOption(opts.siteLimit, "r.deploy.getRelease siteLimit", "fetching release inventory");
354
+ const siteLimit = normalizePositiveSafeIntegerQueryOption(opts.siteLimit, "apply.getRelease siteLimit", "fetching release inventory");
355
355
  const headers = await apikeyHeaders(this.client, opts.project);
356
356
  return this.client.request(appendQuery(`/apply/v1/releases/${encodeURIComponent(opts.releaseId)}`, {
357
357
  site_limit: siteLimit,
@@ -364,9 +364,9 @@ export class Deploy {
364
364
  */
365
365
  async getActiveRelease(opts) {
366
366
  if (!opts?.project) {
367
- throw new LocalError("r.deploy.getActiveRelease requires a project id ({ project: 'prj_...' })", "fetching active release inventory");
367
+ throw new LocalError("apply.getActiveRelease requires a project id ({ project: 'prj_...' })", "fetching active release inventory");
368
368
  }
369
- const siteLimit = normalizePositiveSafeIntegerQueryOption(opts.siteLimit, "r.deploy.getActiveRelease siteLimit", "fetching active release inventory");
369
+ const siteLimit = normalizePositiveSafeIntegerQueryOption(opts.siteLimit, "apply.getActiveRelease siteLimit", "fetching active release inventory");
370
370
  const headers = await apikeyHeaders(this.client, opts.project);
371
371
  return this.client.request(appendQuery("/apply/v1/releases/active", {
372
372
  site_limit: siteLimit,
@@ -379,11 +379,11 @@ export class Deploy {
379
379
  */
380
380
  async diff(opts) {
381
381
  if (!opts?.project) {
382
- throw new LocalError("r.deploy.diff requires a project id ({ project: 'prj_...', from, to })", "diffing releases");
382
+ throw new LocalError("apply.diff requires a project id ({ project: 'prj_...', from, to })", "diffing releases");
383
383
  }
384
- const from = requireNonEmptyStringQueryOption(opts.from, "r.deploy.diff from", "diffing releases");
385
- const to = requireNonEmptyStringQueryOption(opts.to, "r.deploy.diff to", "diffing releases");
386
- const limit = normalizePositiveSafeIntegerQueryOption(opts.limit, "r.deploy.diff limit", "diffing releases");
384
+ const from = requireNonEmptyStringQueryOption(opts.from, "apply.diff from", "diffing releases");
385
+ const to = requireNonEmptyStringQueryOption(opts.to, "apply.diff to", "diffing releases");
386
+ const limit = normalizePositiveSafeIntegerQueryOption(opts.limit, "apply.diff limit", "diffing releases");
387
387
  const headers = await apikeyHeaders(this.client, opts.project);
388
388
  const qs = new URLSearchParams({ from, to });
389
389
  if (limit !== undefined)
@@ -631,6 +631,132 @@ function enrichDeployRetryBody(body, attempts, maxRetries, lastRetryCode) {
631
631
  }
632
632
  return retryFields;
633
633
  }
634
+ function contentRefToWire(ref) {
635
+ const maybeWire = ref;
636
+ return {
637
+ sha256: ref.sha256,
638
+ size: ref.size,
639
+ ...(ref.contentType ?? maybeWire.content_type
640
+ ? { content_type: ref.contentType ?? maybeWire.content_type }
641
+ : {}),
642
+ ...(ref.integrity ? { integrity: ref.integrity } : {}),
643
+ };
644
+ }
645
+ function fileSetToWire(map) {
646
+ const out = {};
647
+ for (const [path, ref] of Object.entries(map))
648
+ out[path] = contentRefToWire(ref);
649
+ return out;
650
+ }
651
+ function requireRoleToWire(gate) {
652
+ return {
653
+ table: gate.table,
654
+ id_column: gate.idColumn,
655
+ role_column: gate.roleColumn,
656
+ allowed: gate.allowed,
657
+ ...(gate.cacheTtl !== undefined ? { cache_ttl: gate.cacheTtl } : {}),
658
+ ...(gate.onDeny !== undefined ? { on_deny: gate.onDeny } : {}),
659
+ ...(gate.signInPath !== undefined ? { sign_in_path: gate.signInPath } : {}),
660
+ };
661
+ }
662
+ function functionToWire(fn) {
663
+ return {
664
+ ...(fn.runtime !== undefined ? { runtime: fn.runtime } : {}),
665
+ ...(fn.source !== undefined ? { source: contentRefToWire(fn.source) } : {}),
666
+ ...(fn.files !== undefined ? { files: fileSetToWire(fn.files) } : {}),
667
+ ...(fn.entrypoint !== undefined ? { entrypoint: fn.entrypoint } : {}),
668
+ ...(fn.config !== undefined
669
+ ? {
670
+ config: {
671
+ ...(fn.config.timeoutSeconds !== undefined ? { timeout_seconds: fn.config.timeoutSeconds } : {}),
672
+ ...(fn.config.memoryMb !== undefined ? { memory_mb: fn.config.memoryMb } : {}),
673
+ },
674
+ }
675
+ : {}),
676
+ ...(fn.schedule !== undefined ? { schedule: fn.schedule } : {}),
677
+ ...(fn.requireAuth !== undefined ? { require_auth: fn.requireAuth } : {}),
678
+ ...(fn.requireRole !== undefined
679
+ ? { require_role: fn.requireRole === null ? null : requireRoleToWire(fn.requireRole) }
680
+ : {}),
681
+ ...(fn.class !== undefined ? { class: fn.class } : {}),
682
+ };
683
+ }
684
+ function functionMapToWire(map) {
685
+ const out = {};
686
+ for (const [name, fn] of Object.entries(map))
687
+ out[name] = functionToWire(fn);
688
+ return out;
689
+ }
690
+ function databaseToWire(database) {
691
+ return {
692
+ ...(database.expose !== undefined ? { expose: database.expose } : {}),
693
+ ...(database.zero_downtime !== undefined ? { zero_downtime: database.zero_downtime } : {}),
694
+ ...(database.migrations !== undefined
695
+ ? {
696
+ migrations: database.migrations.map((m) => ({
697
+ id: m.id,
698
+ checksum: m.checksum,
699
+ sql_ref: contentRefToWire(m.sql_ref),
700
+ ...(m.transaction !== undefined ? { transaction: m.transaction } : {}),
701
+ })),
702
+ }
703
+ : {}),
704
+ };
705
+ }
706
+ function functionsToWire(functions) {
707
+ return {
708
+ ...(functions.replace !== undefined ? { replace: functionMapToWire(functions.replace) } : {}),
709
+ ...(functions.patch !== undefined
710
+ ? {
711
+ patch: {
712
+ ...(functions.patch.set !== undefined ? { set: functionMapToWire(functions.patch.set) } : {}),
713
+ ...(functions.patch.delete !== undefined ? { delete: functions.patch.delete } : {}),
714
+ },
715
+ }
716
+ : {}),
717
+ };
718
+ }
719
+ function siteToWire(site) {
720
+ if ("replace" in site && site.replace) {
721
+ return {
722
+ replace: fileSetToWire(site.replace),
723
+ ...(site.public_paths ? { public_paths: site.public_paths } : {}),
724
+ };
725
+ }
726
+ if ("patch" in site && site.patch) {
727
+ return {
728
+ patch: {
729
+ ...(site.patch.put ? { put: fileSetToWire(site.patch.put) } : {}),
730
+ ...(site.patch.delete ? { delete: site.patch.delete } : {}),
731
+ },
732
+ ...(site.public_paths ? { public_paths: site.public_paths } : {}),
733
+ };
734
+ }
735
+ return { public_paths: site.public_paths };
736
+ }
737
+ function i18nToWire(i18n) {
738
+ return {
739
+ default_locale: i18n.defaultLocale,
740
+ locales: i18n.locales,
741
+ ...(i18n.detect !== undefined ? { detect: i18n.detect } : {}),
742
+ ...(i18n.unknownLocalePolicy !== undefined ? { unknown_locale_policy: i18n.unknownLocalePolicy } : {}),
743
+ };
744
+ }
745
+ function releaseSpecToWire(spec) {
746
+ return {
747
+ project_id: spec.project,
748
+ ...(spec.base !== undefined ? { base: spec.base } : {}),
749
+ ...(spec.database !== undefined ? { database: databaseToWire(spec.database) } : {}),
750
+ ...(spec.secrets !== undefined ? { secrets: spec.secrets } : {}),
751
+ ...(spec.functions !== undefined ? { functions: functionsToWire(spec.functions) } : {}),
752
+ ...(spec.site !== undefined ? { site: siteToWire(spec.site) } : {}),
753
+ ...(spec.subdomains !== undefined ? { subdomains: spec.subdomains } : {}),
754
+ ...(spec.routes !== undefined ? { routes: spec.routes } : {}),
755
+ ...(spec.checks !== undefined ? { checks: spec.checks } : {}),
756
+ ...(spec.assets !== undefined ? { assets: spec.assets } : {}),
757
+ ...(spec.i18n !== undefined ? { i18n: spec.i18n === null ? null : i18nToWire(spec.i18n) } : {}),
758
+ };
759
+ }
634
760
  async function planInternal(client, spec, idempotencyKey, dryRun = false) {
635
761
  const ciCredentials = isCiClient(client);
636
762
  validateSpec(spec);
@@ -638,12 +764,13 @@ async function planInternal(client, spec, idempotencyKey, dryRun = false) {
638
764
  assertCiDeployableSpec(spec);
639
765
  const { normalized, byteReaders } = await normalizeReleaseSpec(client, spec);
640
766
  await preflightTierFunctionLimits(client, normalized, ciCredentials);
767
+ const wireSpec = releaseSpecToWire(normalized);
641
768
  // The gateway expects { spec, manifest_ref?, idempotency_key? } with
642
- // ReleaseSpec.project (singular). For oversized specs the SDK uploads
769
+ // snake_case ReleaseSpec wire JSON. For oversized specs the SDK uploads
643
770
  // the manifest JSON to CAS first and references it; the gateway still
644
771
  // needs `spec` in the body (with at least the project), so we keep a
645
772
  // minimal stub there.
646
- const inlineBody = { spec: normalized };
773
+ const inlineBody = { spec: wireSpec };
647
774
  if (idempotencyKey && !dryRun)
648
775
  inlineBody.idempotency_key = idempotencyKey;
649
776
  const inlineBytes = new TextEncoder().encode(JSON.stringify(inlineBody)).byteLength;
@@ -673,9 +800,9 @@ async function planInternal(client, spec, idempotencyKey, dryRun = false) {
673
800
  // Upload the normalized manifest itself as a CAS object so the gateway
674
801
  // can pick it up via `manifest_ref`. The body still carries a minimal
675
802
  // `spec` so the gateway has the project for auth + plan persistence.
676
- const manifestBytes = new TextEncoder().encode(JSON.stringify(normalized));
803
+ const manifestBytes = new TextEncoder().encode(JSON.stringify(wireSpec));
677
804
  const ref = await uploadInlineCas(client, spec.project, manifestBytes, MANIFEST_CONTENT_TYPE);
678
- body = { spec: { project: spec.project }, manifest_ref: ref };
805
+ body = { spec: { project_id: spec.project }, manifest_ref: contentRefToWire(ref) };
679
806
  if (idempotencyKey)
680
807
  body.idempotency_key = idempotencyKey;
681
808
  }
@@ -1564,7 +1691,7 @@ const ROUTE_ENTRY_FIELDS = new Set(["pattern", "methods", "target", "acknowledge
1564
1691
  const FUNCTION_ROUTE_TARGET_FIELDS = new Set(["type", "name"]);
1565
1692
  const STATIC_ROUTE_TARGET_FIELDS = new Set(["type", "file"]);
1566
1693
  const ROUTE_METHOD_SET = new Set(ROUTE_HTTP_METHODS);
1567
- const I18N_SPEC_FIELDS = new Set(["defaultLocale", "locales", "detect"]);
1694
+ const I18N_SPEC_FIELDS = new Set(["defaultLocale", "locales", "detect", "unknownLocalePolicy"]);
1568
1695
  const I18N_LOCALE_TAG_REGEX = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
1569
1696
  const I18N_COOKIE_NAME_REGEX = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
1570
1697
  const I18N_MAX_LOCALES = 50;
@@ -3004,7 +3131,7 @@ async function uploadInlineCas(client, projectId, bytes, contentType) {
3004
3131
  // ─── Helpers ─────────────────────────────────────────────────────────────────
3005
3132
  /**
3006
3133
  * Build the apikey header set for a project. The v1.34 gateway's
3007
- * `/apply/v1/operations/:id*` and `/content/v1/plans*` routes require
3134
+ * `/apply/v1/operations/:operation_id*` and `/content/v1/plans*` routes require
3008
3135
  * `apikey: <project.anon_key>` (apikeyAuth middleware). Plan + commit on
3009
3136
  * `/apply/v1/plans*` use SIWX, which the kernel's getAuth provides
3010
3137
  * automatically — only the apikey-gated paths need this helper.