@enclave-run/sdk 0.0.0 → 0.2.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.js CHANGED
@@ -101,6 +101,7 @@ __export(src_exports, {
101
101
  ReadyCmd: () => ReadyCmd,
102
102
  RegionCapacityError: () => RegionCapacityError,
103
103
  Sandbox: () => Sandbox,
104
+ SandboxCreateFailedError: () => SandboxCreateFailedError,
104
105
  SandboxCreateRejectedError: () => SandboxCreateRejectedError,
105
106
  SandboxError: () => SandboxError,
106
107
  SandboxRegionScope: () => SandboxRegionScope,
@@ -127,7 +128,7 @@ var import_openapi_fetch = __toESM(require("openapi-fetch"));
127
128
  var import_platform2 = __toESM(require("platform"));
128
129
 
129
130
  // package.json
130
- var version = "0.0.0";
131
+ var version = "0.2.0";
131
132
 
132
133
  // src/utils.ts
133
134
  var import_platform = __toESM(require("platform"));
@@ -169,12 +170,6 @@ async function sha256(data) {
169
170
  function timeoutToSeconds(timeout) {
170
171
  return Math.ceil(timeout / 1e3);
171
172
  }
172
- async function dynamicImport(module2) {
173
- if (runtime === "browser") {
174
- throw new Error("Browser runtime is not supported for dynamic import");
175
- }
176
- return await import(module2);
177
- }
178
173
  function ansiRegex({ onlyFirst = false } = {}) {
179
174
  const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
180
175
  const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
@@ -239,6 +234,13 @@ var OutcomeUnknownError = class extends SandboxError {
239
234
  this.cause = cause;
240
235
  }
241
236
  };
237
+ var SandboxCreateFailedError = class extends SandboxError {
238
+ constructor(message, recovery) {
239
+ super(message);
240
+ this.name = "SandboxCreateFailedError";
241
+ this.recovery = recovery;
242
+ }
243
+ };
242
244
  var SandboxCreateRejectedError = class extends SandboxError {
243
245
  constructor(message, recovery, reason, spilloverAllowed = false, capacityTier = "shared") {
244
246
  super(message);
@@ -315,7 +317,7 @@ var TemplateTagConflictError = class extends TemplateError {
315
317
  constructor(options) {
316
318
  var _a3;
317
319
  super(
318
- (_a3 = options.message) != null ? _a3 : `Template tag "${options.tag}" conflicted with another mutation. Fetch its current head with Template.getTagHead() before retrying.`
320
+ (_a3 = options.message) != null ? _a3 : `Template tag "${options.tag}" conflicted with another mutation. Read its current head with Template.getTags() before retrying.`
319
321
  );
320
322
  this.name = "TemplateTagConflictError";
321
323
  this.templateId = options.templateId;
@@ -3584,8 +3586,9 @@ var SandboxApi = class {
3584
3586
  return operation.sandbox;
3585
3587
  }
3586
3588
  if (operation.state === "failed") {
3587
- throw new SandboxError(
3588
- (_b = (_a3 = operation.error) == null ? void 0 : _a3.message) != null ? _b : "Sandbox create failed after admission"
3589
+ throw new SandboxCreateFailedError(
3590
+ (_b = (_a3 = operation.error) == null ? void 0 : _a3.message) != null ? _b : "Sandbox create failed after admission",
3591
+ recovery
3589
3592
  );
3590
3593
  }
3591
3594
  await new Promise((resolve) => setTimeout(resolve, 25));
@@ -4616,6 +4619,18 @@ var STACK_TRACE_DEPTH = 3;
4616
4619
  var RESOLVE_SYMLINKS = false;
4617
4620
 
4618
4621
  // src/template/utils.ts
4622
+ async function loadGlob() {
4623
+ if (runtime === "browser") {
4624
+ throw new Error("Browser runtime is not supported for local file copies");
4625
+ }
4626
+ return await import("glob");
4627
+ }
4628
+ async function loadTar() {
4629
+ if (runtime === "browser") {
4630
+ throw new Error("Browser runtime is not supported for local file copies");
4631
+ }
4632
+ return await import("tar");
4633
+ }
4619
4634
  function validateRelativePath(src, stackTrace) {
4620
4635
  if (import_node_path.default.isAbsolute(src)) {
4621
4636
  const error = new TemplateError(
@@ -4646,7 +4661,7 @@ function normalizePath(path2) {
4646
4661
  return path2.replace(/\\/g, "/");
4647
4662
  }
4648
4663
  async function getAllFilesInPath(src, contextPath, ignorePatterns, includeDirectories = true) {
4649
- const { glob } = await dynamicImport("glob");
4664
+ const { glob } = await loadGlob();
4650
4665
  const files = /* @__PURE__ */ new Map();
4651
4666
  const globFiles = await glob(src, {
4652
4667
  ignore: ignorePatterns,
@@ -4763,7 +4778,7 @@ function padOctal(mode) {
4763
4778
  return mode.toString(8).padStart(4, "0");
4764
4779
  }
4765
4780
  async function getTarArchiveInputs(fileName, fileContextPath, ignorePatterns) {
4766
- const { create } = await dynamicImport("tar");
4781
+ const { create } = await loadTar();
4767
4782
  const allFiles = await getAllFilesInPath(
4768
4783
  fileName,
4769
4784
  fileContextPath,
@@ -5087,7 +5102,8 @@ async function getTemplateTags(client, { templateID }) {
5087
5102
  return res.data.map((item) => ({
5088
5103
  tag: item.tag,
5089
5104
  buildId: item.buildID,
5090
- createdAt: new Date(item.createdAt)
5105
+ createdAt: new Date(item.createdAt),
5106
+ version: item.version
5091
5107
  }));
5092
5108
  }
5093
5109
 
@@ -5311,126 +5327,10 @@ function handleCmdEntrypointInstruction(instruction, templateBuilder) {
5311
5327
  }
5312
5328
  }
5313
5329
 
5314
- // src/template/activationApi.ts
5315
- async function activateTemplate(build, options = {}) {
5316
- assertBuildIdentity(build);
5317
- assertExpectedVersion(options.expectedVersion);
5318
- const region = resolveRegion(options.region);
5319
- const config = ConnectionConfig.forGlobal(options);
5320
- const client = new ApiClient(config);
5321
- const response = await client.api.POST(
5322
- "/templates/{templateID}/activations/{region}",
5323
- {
5324
- params: {
5325
- path: {
5326
- templateID: build.templateId,
5327
- region
5328
- }
5329
- },
5330
- body: {
5331
- buildID: build.buildId,
5332
- active: true,
5333
- requiredReadyNodes: options.requiredReadyNodes,
5334
- allowRemoteFallback: options.allowRemoteFallback,
5335
- expectedVersion: options.expectedVersion
5336
- },
5337
- signal: config.getSignal(options.requestTimeoutMs)
5338
- }
5339
- );
5340
- return responseData(response, "Enclave API returned no template activation");
5341
- }
5342
- async function deactivateTemplate(build, options = {}) {
5343
- assertBuildIdentity(build);
5344
- assertExpectedVersion(options.expectedVersion);
5345
- const region = resolveRegion(options.region);
5346
- const config = ConnectionConfig.forGlobal(options);
5347
- const client = new ApiClient(config);
5348
- const response = await client.api.POST(
5349
- "/templates/{templateID}/activations/{region}",
5350
- {
5351
- params: {
5352
- path: {
5353
- templateID: build.templateId,
5354
- region
5355
- }
5356
- },
5357
- body: {
5358
- buildID: build.buildId,
5359
- active: false,
5360
- expectedVersion: options.expectedVersion
5361
- },
5362
- signal: config.getSignal(options.requestTimeoutMs)
5363
- }
5364
- );
5365
- return responseData(response, "Enclave API returned no template activation");
5366
- }
5367
- async function getTemplateActivation(templateId, options = {}) {
5368
- if (!templateId.trim()) {
5369
- throw new InvalidArgumentError("templateId is required");
5370
- }
5371
- if (options.buildId !== void 0 && !options.buildId.trim()) {
5372
- throw new InvalidArgumentError("buildId must not be empty");
5373
- }
5374
- const region = resolveRegion(options.region);
5375
- const config = ConnectionConfig.forSandbox(__spreadProps(__spreadValues({}, options), { region }));
5376
- const client = new ApiClient(config);
5377
- const response = await client.api.GET(
5378
- "/templates/{templateID}/activations/{region}",
5379
- {
5380
- params: {
5381
- path: {
5382
- templateID: templateId,
5383
- region
5384
- },
5385
- query: {
5386
- buildID: options.buildId
5387
- }
5388
- },
5389
- signal: config.getSignal(options.requestTimeoutMs)
5390
- }
5391
- );
5392
- return responseData(response, "Enclave API returned no template activation");
5393
- }
5394
- function assertBuildIdentity(build) {
5395
- if (!build.templateId.trim() || !build.buildId.trim()) {
5396
- throw new InvalidArgumentError("templateId and buildId are required");
5397
- }
5398
- }
5399
- function resolveRegion(region) {
5400
- return ConnectionConfig.resolveRegion(region);
5401
- }
5402
- function assertExpectedVersion(expectedVersion) {
5403
- if (expectedVersion !== void 0 && (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)) {
5404
- throw new InvalidArgumentError(
5405
- "expectedVersion must be a non-negative safe integer"
5406
- );
5407
- }
5408
- }
5409
-
5410
5330
  // src/template/tagHeadApi.ts
5411
- async function getTemplateTagHead(client, templateId, tag, signal) {
5412
- assertTemplateAndTag(templateId, tag);
5413
- const response = await client.api.GET("/templates/{templateID}/tags/{tag}", {
5414
- params: {
5415
- path: {
5416
- templateID: templateId,
5417
- tag
5418
- }
5419
- },
5420
- signal
5421
- });
5422
- const error = handleApiError(response, TemplateError);
5423
- if (error) {
5424
- throw error;
5425
- }
5426
- if (!response.data) {
5427
- throw new TemplateError("Enclave API returned no template tag head");
5428
- }
5429
- return mapTagHead(response.data);
5430
- }
5431
5331
  async function promoteTemplateTag(client, candidate, tag, expected, signal) {
5432
5332
  var _a3, _b, _c, _d, _e, _f;
5433
- assertBuildIdentity2(candidate);
5333
+ assertBuildIdentity(candidate);
5434
5334
  assertTemplateAndTag(candidate.templateId, tag);
5435
5335
  assertExpectation(expected);
5436
5336
  const response = await client.api.PUT("/templates/{templateID}/tags/{tag}", {
@@ -5456,7 +5356,7 @@ async function promoteTemplateTag(client, candidate, tag, expected, signal) {
5456
5356
  expectedBuildId: expected == null ? void 0 : expected.buildId,
5457
5357
  expectedVersion: (_f = expected == null ? void 0 : expected.version) != null ? _f : 0,
5458
5358
  reason: response.error.code,
5459
- message: `409: ${message}. Fetch its current head with Template.getTagHead() before retrying.`
5359
+ message: `409: ${message}. Read its current head with Template.getTags() before retrying.`
5460
5360
  });
5461
5361
  }
5462
5362
  const error = handleApiError(response, TemplateError);
@@ -5466,14 +5366,10 @@ async function promoteTemplateTag(client, candidate, tag, expected, signal) {
5466
5366
  if (!response.data) {
5467
5367
  throw new TemplateError("Enclave API returned no promoted template tag");
5468
5368
  }
5469
- return mapTagHead(response.data);
5470
- }
5471
- function mapTagHead(head) {
5472
5369
  return {
5473
- tag: head.tag,
5474
- buildId: head.buildID,
5475
- version: head.version,
5476
- createdAt: new Date(head.createdAt)
5370
+ buildId: response.data.buildID,
5371
+ tags: [response.data.tag],
5372
+ version: response.data.version
5477
5373
  };
5478
5374
  }
5479
5375
  function assertTemplateAndTag(templateId, tag) {
@@ -5481,7 +5377,7 @@ function assertTemplateAndTag(templateId, tag) {
5481
5377
  throw new InvalidArgumentError("templateId and tag are required");
5482
5378
  }
5483
5379
  }
5484
- function assertBuildIdentity2(candidate) {
5380
+ function assertBuildIdentity(candidate) {
5485
5381
  if (!candidate.templateId.trim() || !candidate.buildId.trim()) {
5486
5382
  throw new InvalidArgumentError("templateId and buildId are required");
5487
5383
  }
@@ -5636,29 +5532,6 @@ var TemplateBase = class {
5636
5532
  logsOffset: options == null ? void 0 : options.logsOffset
5637
5533
  });
5638
5534
  }
5639
- /**
5640
- * Materialize one immutable template build in a region before create.
5641
- *
5642
- * The request is recorded on the global control plane; hydration then runs
5643
- * asynchronously inside the selected region. Poll {@link getActivation}
5644
- * until the returned status is `ready`.
5645
- */
5646
- static async activate(data, options) {
5647
- return activateTemplate(data, options);
5648
- }
5649
- /**
5650
- * Return desired state plus exact-generation evidence from the selected
5651
- * regional cell.
5652
- */
5653
- static async getActivation(templateId, options) {
5654
- return getTemplateActivation(templateId, options);
5655
- }
5656
- /**
5657
- * Stop pinning and maintaining one exact build generation in a region.
5658
- */
5659
- static async deactivate(data, options) {
5660
- return deactivateTemplate(data, options);
5661
- }
5662
5535
  /**
5663
5536
  * Check if a template with the given name exists.
5664
5537
  *
@@ -5696,10 +5569,25 @@ var TemplateBase = class {
5696
5569
  * await Template.assignTags('my-template:v1.0', ['production', 'stable'])
5697
5570
  * ```
5698
5571
  */
5699
- static async assignTags(targetName, tags, options) {
5572
+ static async assignTags(target, tags, options) {
5700
5573
  const config = ConnectionConfig.forGlobal(options);
5701
5574
  const client = new ApiClient(config);
5702
5575
  const normalizedTags = Array.isArray(tags) ? tags : [tags];
5576
+ if ((options == null ? void 0 : options.expect) !== void 0) {
5577
+ if (typeof target === "string" || normalizedTags.length !== 1) {
5578
+ throw new InvalidArgumentError(
5579
+ "assignTags with expect requires an exact build ({ templateId, buildId }) and exactly one tag"
5580
+ );
5581
+ }
5582
+ return promoteTemplateTag(
5583
+ client,
5584
+ target,
5585
+ normalizedTags[0],
5586
+ options.expect,
5587
+ config.getSignal(options.requestTimeoutMs)
5588
+ );
5589
+ }
5590
+ const targetName = typeof target === "string" ? target : `${target.templateId}:${target.buildId}`;
5703
5591
  return assignTags(client, { targetName, tags: normalizedTags });
5704
5592
  }
5705
5593
  /**
@@ -5744,42 +5632,6 @@ var TemplateBase = class {
5744
5632
  const client = new ApiClient(config);
5745
5633
  return getTemplateTags(client, { templateID: templateId });
5746
5634
  }
5747
- /**
5748
- * Get the authoritative traffic-selection token for one template tag.
5749
- *
5750
- * Pass the returned head directly to {@link promoteTag}; its monotonic
5751
- * version prevents concurrent releasers from silently overwriting each
5752
- * other.
5753
- */
5754
- static async getTagHead(templateId, tag, options) {
5755
- const config = ConnectionConfig.forGlobal(options);
5756
- const client = new ApiClient(config);
5757
- return getTemplateTagHead(
5758
- client,
5759
- templateId,
5760
- tag,
5761
- config.getSignal(options == null ? void 0 : options.requestTimeoutMs)
5762
- );
5763
- }
5764
- /**
5765
- * Atomically move one template tag to an exact ready, durable build.
5766
- *
5767
- * Use a head returned by {@link getTagHead} as `expected`. Pass `null` only
5768
- * when creating a tag that must not already exist. A concurrent change throws
5769
- * `TemplateTagConflictError`; fetch the head again before deciding whether to
5770
- * retry.
5771
- */
5772
- static async promoteTag(candidate, tag, expected, options) {
5773
- const config = ConnectionConfig.forGlobal(options);
5774
- const client = new ApiClient(config);
5775
- return promoteTemplateTag(
5776
- client,
5777
- candidate,
5778
- tag,
5779
- expected,
5780
- config.getSignal(options == null ? void 0 : options.requestTimeoutMs)
5781
- );
5782
- }
5783
5635
  fromDebianImage(variant = "stable") {
5784
5636
  return this.fromImage(`debian:${variant}`);
5785
5637
  }
@@ -6457,15 +6309,10 @@ function Template(options) {
6457
6309
  Template.build = TemplateBase.build;
6458
6310
  Template.buildInBackground = TemplateBase.buildInBackground;
6459
6311
  Template.getBuildStatus = TemplateBase.getBuildStatus;
6460
- Template.activate = TemplateBase.activate;
6461
- Template.getActivation = TemplateBase.getActivation;
6462
- Template.deactivate = TemplateBase.deactivate;
6463
6312
  Template.exists = TemplateBase.exists;
6464
6313
  Template.assignTags = TemplateBase.assignTags;
6465
6314
  Template.removeTags = TemplateBase.removeTags;
6466
6315
  Template.getTags = TemplateBase.getTags;
6467
- Template.getTagHead = TemplateBase.getTagHead;
6468
- Template.promoteTag = TemplateBase.promoteTag;
6469
6316
  Template.toJSON = TemplateBase.toJSON;
6470
6317
  Template.toDockerfile = TemplateBase.toDockerfile;
6471
6318
 
@@ -6498,6 +6345,7 @@ var src_default = Sandbox;
6498
6345
  ReadyCmd,
6499
6346
  RegionCapacityError,
6500
6347
  Sandbox,
6348
+ SandboxCreateFailedError,
6501
6349
  SandboxCreateRejectedError,
6502
6350
  SandboxError,
6503
6351
  SandboxRegionScope,