@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.mjs CHANGED
@@ -60,7 +60,7 @@ import createClient from "openapi-fetch";
60
60
  import platform2 from "platform";
61
61
 
62
62
  // package.json
63
- var version = "0.0.0";
63
+ var version = "0.2.0";
64
64
 
65
65
  // src/utils.ts
66
66
  import platform from "platform";
@@ -102,12 +102,6 @@ async function sha256(data) {
102
102
  function timeoutToSeconds(timeout) {
103
103
  return Math.ceil(timeout / 1e3);
104
104
  }
105
- async function dynamicImport(module) {
106
- if (runtime === "browser") {
107
- throw new Error("Browser runtime is not supported for dynamic import");
108
- }
109
- return await import(module);
110
- }
111
105
  function ansiRegex({ onlyFirst = false } = {}) {
112
106
  const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
113
107
  const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
@@ -172,6 +166,13 @@ var OutcomeUnknownError = class extends SandboxError {
172
166
  this.cause = cause;
173
167
  }
174
168
  };
169
+ var SandboxCreateFailedError = class extends SandboxError {
170
+ constructor(message, recovery) {
171
+ super(message);
172
+ this.name = "SandboxCreateFailedError";
173
+ this.recovery = recovery;
174
+ }
175
+ };
175
176
  var SandboxCreateRejectedError = class extends SandboxError {
176
177
  constructor(message, recovery, reason, spilloverAllowed = false, capacityTier = "shared") {
177
178
  super(message);
@@ -248,7 +249,7 @@ var TemplateTagConflictError = class extends TemplateError {
248
249
  constructor(options) {
249
250
  var _a3;
250
251
  super(
251
- (_a3 = options.message) != null ? _a3 : `Template tag "${options.tag}" conflicted with another mutation. Fetch its current head with Template.getTagHead() before retrying.`
252
+ (_a3 = options.message) != null ? _a3 : `Template tag "${options.tag}" conflicted with another mutation. Read its current head with Template.getTags() before retrying.`
252
253
  );
253
254
  this.name = "TemplateTagConflictError";
254
255
  this.templateId = options.templateId;
@@ -3529,8 +3530,9 @@ var SandboxApi = class {
3529
3530
  return operation.sandbox;
3530
3531
  }
3531
3532
  if (operation.state === "failed") {
3532
- throw new SandboxError(
3533
- (_b = (_a3 = operation.error) == null ? void 0 : _a3.message) != null ? _b : "Sandbox create failed after admission"
3533
+ throw new SandboxCreateFailedError(
3534
+ (_b = (_a3 = operation.error) == null ? void 0 : _a3.message) != null ? _b : "Sandbox create failed after admission",
3535
+ recovery
3534
3536
  );
3535
3537
  }
3536
3538
  await new Promise((resolve) => setTimeout(resolve, 25));
@@ -4561,6 +4563,18 @@ var STACK_TRACE_DEPTH = 3;
4561
4563
  var RESOLVE_SYMLINKS = false;
4562
4564
 
4563
4565
  // src/template/utils.ts
4566
+ async function loadGlob() {
4567
+ if (runtime === "browser") {
4568
+ throw new Error("Browser runtime is not supported for local file copies");
4569
+ }
4570
+ return await import("glob");
4571
+ }
4572
+ async function loadTar() {
4573
+ if (runtime === "browser") {
4574
+ throw new Error("Browser runtime is not supported for local file copies");
4575
+ }
4576
+ return await import("tar");
4577
+ }
4564
4578
  function validateRelativePath(src, stackTrace) {
4565
4579
  if (path.isAbsolute(src)) {
4566
4580
  const error = new TemplateError(
@@ -4591,7 +4605,7 @@ function normalizePath(path2) {
4591
4605
  return path2.replace(/\\/g, "/");
4592
4606
  }
4593
4607
  async function getAllFilesInPath(src, contextPath, ignorePatterns, includeDirectories = true) {
4594
- const { glob } = await dynamicImport("glob");
4608
+ const { glob } = await loadGlob();
4595
4609
  const files = /* @__PURE__ */ new Map();
4596
4610
  const globFiles = await glob(src, {
4597
4611
  ignore: ignorePatterns,
@@ -4708,7 +4722,7 @@ function padOctal(mode) {
4708
4722
  return mode.toString(8).padStart(4, "0");
4709
4723
  }
4710
4724
  async function getTarArchiveInputs(fileName, fileContextPath, ignorePatterns) {
4711
- const { create } = await dynamicImport("tar");
4725
+ const { create } = await loadTar();
4712
4726
  const allFiles = await getAllFilesInPath(
4713
4727
  fileName,
4714
4728
  fileContextPath,
@@ -5032,7 +5046,8 @@ async function getTemplateTags(client, { templateID }) {
5032
5046
  return res.data.map((item) => ({
5033
5047
  tag: item.tag,
5034
5048
  buildId: item.buildID,
5035
- createdAt: new Date(item.createdAt)
5049
+ createdAt: new Date(item.createdAt),
5050
+ version: item.version
5036
5051
  }));
5037
5052
  }
5038
5053
 
@@ -5258,126 +5273,10 @@ function handleCmdEntrypointInstruction(instruction, templateBuilder) {
5258
5273
  }
5259
5274
  }
5260
5275
 
5261
- // src/template/activationApi.ts
5262
- async function activateTemplate(build, options = {}) {
5263
- assertBuildIdentity(build);
5264
- assertExpectedVersion(options.expectedVersion);
5265
- const region = resolveRegion(options.region);
5266
- const config = ConnectionConfig.forGlobal(options);
5267
- const client = new ApiClient(config);
5268
- const response = await client.api.POST(
5269
- "/templates/{templateID}/activations/{region}",
5270
- {
5271
- params: {
5272
- path: {
5273
- templateID: build.templateId,
5274
- region
5275
- }
5276
- },
5277
- body: {
5278
- buildID: build.buildId,
5279
- active: true,
5280
- requiredReadyNodes: options.requiredReadyNodes,
5281
- allowRemoteFallback: options.allowRemoteFallback,
5282
- expectedVersion: options.expectedVersion
5283
- },
5284
- signal: config.getSignal(options.requestTimeoutMs)
5285
- }
5286
- );
5287
- return responseData(response, "Enclave API returned no template activation");
5288
- }
5289
- async function deactivateTemplate(build, options = {}) {
5290
- assertBuildIdentity(build);
5291
- assertExpectedVersion(options.expectedVersion);
5292
- const region = resolveRegion(options.region);
5293
- const config = ConnectionConfig.forGlobal(options);
5294
- const client = new ApiClient(config);
5295
- const response = await client.api.POST(
5296
- "/templates/{templateID}/activations/{region}",
5297
- {
5298
- params: {
5299
- path: {
5300
- templateID: build.templateId,
5301
- region
5302
- }
5303
- },
5304
- body: {
5305
- buildID: build.buildId,
5306
- active: false,
5307
- expectedVersion: options.expectedVersion
5308
- },
5309
- signal: config.getSignal(options.requestTimeoutMs)
5310
- }
5311
- );
5312
- return responseData(response, "Enclave API returned no template activation");
5313
- }
5314
- async function getTemplateActivation(templateId, options = {}) {
5315
- if (!templateId.trim()) {
5316
- throw new InvalidArgumentError("templateId is required");
5317
- }
5318
- if (options.buildId !== void 0 && !options.buildId.trim()) {
5319
- throw new InvalidArgumentError("buildId must not be empty");
5320
- }
5321
- const region = resolveRegion(options.region);
5322
- const config = ConnectionConfig.forSandbox(__spreadProps(__spreadValues({}, options), { region }));
5323
- const client = new ApiClient(config);
5324
- const response = await client.api.GET(
5325
- "/templates/{templateID}/activations/{region}",
5326
- {
5327
- params: {
5328
- path: {
5329
- templateID: templateId,
5330
- region
5331
- },
5332
- query: {
5333
- buildID: options.buildId
5334
- }
5335
- },
5336
- signal: config.getSignal(options.requestTimeoutMs)
5337
- }
5338
- );
5339
- return responseData(response, "Enclave API returned no template activation");
5340
- }
5341
- function assertBuildIdentity(build) {
5342
- if (!build.templateId.trim() || !build.buildId.trim()) {
5343
- throw new InvalidArgumentError("templateId and buildId are required");
5344
- }
5345
- }
5346
- function resolveRegion(region) {
5347
- return ConnectionConfig.resolveRegion(region);
5348
- }
5349
- function assertExpectedVersion(expectedVersion) {
5350
- if (expectedVersion !== void 0 && (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)) {
5351
- throw new InvalidArgumentError(
5352
- "expectedVersion must be a non-negative safe integer"
5353
- );
5354
- }
5355
- }
5356
-
5357
5276
  // src/template/tagHeadApi.ts
5358
- async function getTemplateTagHead(client, templateId, tag, signal) {
5359
- assertTemplateAndTag(templateId, tag);
5360
- const response = await client.api.GET("/templates/{templateID}/tags/{tag}", {
5361
- params: {
5362
- path: {
5363
- templateID: templateId,
5364
- tag
5365
- }
5366
- },
5367
- signal
5368
- });
5369
- const error = handleApiError(response, TemplateError);
5370
- if (error) {
5371
- throw error;
5372
- }
5373
- if (!response.data) {
5374
- throw new TemplateError("Enclave API returned no template tag head");
5375
- }
5376
- return mapTagHead(response.data);
5377
- }
5378
5277
  async function promoteTemplateTag(client, candidate, tag, expected, signal) {
5379
5278
  var _a3, _b, _c, _d, _e, _f;
5380
- assertBuildIdentity2(candidate);
5279
+ assertBuildIdentity(candidate);
5381
5280
  assertTemplateAndTag(candidate.templateId, tag);
5382
5281
  assertExpectation(expected);
5383
5282
  const response = await client.api.PUT("/templates/{templateID}/tags/{tag}", {
@@ -5403,7 +5302,7 @@ async function promoteTemplateTag(client, candidate, tag, expected, signal) {
5403
5302
  expectedBuildId: expected == null ? void 0 : expected.buildId,
5404
5303
  expectedVersion: (_f = expected == null ? void 0 : expected.version) != null ? _f : 0,
5405
5304
  reason: response.error.code,
5406
- message: `409: ${message}. Fetch its current head with Template.getTagHead() before retrying.`
5305
+ message: `409: ${message}. Read its current head with Template.getTags() before retrying.`
5407
5306
  });
5408
5307
  }
5409
5308
  const error = handleApiError(response, TemplateError);
@@ -5413,14 +5312,10 @@ async function promoteTemplateTag(client, candidate, tag, expected, signal) {
5413
5312
  if (!response.data) {
5414
5313
  throw new TemplateError("Enclave API returned no promoted template tag");
5415
5314
  }
5416
- return mapTagHead(response.data);
5417
- }
5418
- function mapTagHead(head) {
5419
5315
  return {
5420
- tag: head.tag,
5421
- buildId: head.buildID,
5422
- version: head.version,
5423
- createdAt: new Date(head.createdAt)
5316
+ buildId: response.data.buildID,
5317
+ tags: [response.data.tag],
5318
+ version: response.data.version
5424
5319
  };
5425
5320
  }
5426
5321
  function assertTemplateAndTag(templateId, tag) {
@@ -5428,7 +5323,7 @@ function assertTemplateAndTag(templateId, tag) {
5428
5323
  throw new InvalidArgumentError("templateId and tag are required");
5429
5324
  }
5430
5325
  }
5431
- function assertBuildIdentity2(candidate) {
5326
+ function assertBuildIdentity(candidate) {
5432
5327
  if (!candidate.templateId.trim() || !candidate.buildId.trim()) {
5433
5328
  throw new InvalidArgumentError("templateId and buildId are required");
5434
5329
  }
@@ -5583,29 +5478,6 @@ var TemplateBase = class {
5583
5478
  logsOffset: options == null ? void 0 : options.logsOffset
5584
5479
  });
5585
5480
  }
5586
- /**
5587
- * Materialize one immutable template build in a region before create.
5588
- *
5589
- * The request is recorded on the global control plane; hydration then runs
5590
- * asynchronously inside the selected region. Poll {@link getActivation}
5591
- * until the returned status is `ready`.
5592
- */
5593
- static async activate(data, options) {
5594
- return activateTemplate(data, options);
5595
- }
5596
- /**
5597
- * Return desired state plus exact-generation evidence from the selected
5598
- * regional cell.
5599
- */
5600
- static async getActivation(templateId, options) {
5601
- return getTemplateActivation(templateId, options);
5602
- }
5603
- /**
5604
- * Stop pinning and maintaining one exact build generation in a region.
5605
- */
5606
- static async deactivate(data, options) {
5607
- return deactivateTemplate(data, options);
5608
- }
5609
5481
  /**
5610
5482
  * Check if a template with the given name exists.
5611
5483
  *
@@ -5643,10 +5515,25 @@ var TemplateBase = class {
5643
5515
  * await Template.assignTags('my-template:v1.0', ['production', 'stable'])
5644
5516
  * ```
5645
5517
  */
5646
- static async assignTags(targetName, tags, options) {
5518
+ static async assignTags(target, tags, options) {
5647
5519
  const config = ConnectionConfig.forGlobal(options);
5648
5520
  const client = new ApiClient(config);
5649
5521
  const normalizedTags = Array.isArray(tags) ? tags : [tags];
5522
+ if ((options == null ? void 0 : options.expect) !== void 0) {
5523
+ if (typeof target === "string" || normalizedTags.length !== 1) {
5524
+ throw new InvalidArgumentError(
5525
+ "assignTags with expect requires an exact build ({ templateId, buildId }) and exactly one tag"
5526
+ );
5527
+ }
5528
+ return promoteTemplateTag(
5529
+ client,
5530
+ target,
5531
+ normalizedTags[0],
5532
+ options.expect,
5533
+ config.getSignal(options.requestTimeoutMs)
5534
+ );
5535
+ }
5536
+ const targetName = typeof target === "string" ? target : `${target.templateId}:${target.buildId}`;
5650
5537
  return assignTags(client, { targetName, tags: normalizedTags });
5651
5538
  }
5652
5539
  /**
@@ -5691,42 +5578,6 @@ var TemplateBase = class {
5691
5578
  const client = new ApiClient(config);
5692
5579
  return getTemplateTags(client, { templateID: templateId });
5693
5580
  }
5694
- /**
5695
- * Get the authoritative traffic-selection token for one template tag.
5696
- *
5697
- * Pass the returned head directly to {@link promoteTag}; its monotonic
5698
- * version prevents concurrent releasers from silently overwriting each
5699
- * other.
5700
- */
5701
- static async getTagHead(templateId, tag, options) {
5702
- const config = ConnectionConfig.forGlobal(options);
5703
- const client = new ApiClient(config);
5704
- return getTemplateTagHead(
5705
- client,
5706
- templateId,
5707
- tag,
5708
- config.getSignal(options == null ? void 0 : options.requestTimeoutMs)
5709
- );
5710
- }
5711
- /**
5712
- * Atomically move one template tag to an exact ready, durable build.
5713
- *
5714
- * Use a head returned by {@link getTagHead} as `expected`. Pass `null` only
5715
- * when creating a tag that must not already exist. A concurrent change throws
5716
- * `TemplateTagConflictError`; fetch the head again before deciding whether to
5717
- * retry.
5718
- */
5719
- static async promoteTag(candidate, tag, expected, options) {
5720
- const config = ConnectionConfig.forGlobal(options);
5721
- const client = new ApiClient(config);
5722
- return promoteTemplateTag(
5723
- client,
5724
- candidate,
5725
- tag,
5726
- expected,
5727
- config.getSignal(options == null ? void 0 : options.requestTimeoutMs)
5728
- );
5729
- }
5730
5581
  fromDebianImage(variant = "stable") {
5731
5582
  return this.fromImage(`debian:${variant}`);
5732
5583
  }
@@ -6404,15 +6255,10 @@ function Template(options) {
6404
6255
  Template.build = TemplateBase.build;
6405
6256
  Template.buildInBackground = TemplateBase.buildInBackground;
6406
6257
  Template.getBuildStatus = TemplateBase.getBuildStatus;
6407
- Template.activate = TemplateBase.activate;
6408
- Template.getActivation = TemplateBase.getActivation;
6409
- Template.deactivate = TemplateBase.deactivate;
6410
6258
  Template.exists = TemplateBase.exists;
6411
6259
  Template.assignTags = TemplateBase.assignTags;
6412
6260
  Template.removeTags = TemplateBase.removeTags;
6413
6261
  Template.getTags = TemplateBase.getTags;
6414
- Template.getTagHead = TemplateBase.getTagHead;
6415
- Template.promoteTag = TemplateBase.promoteTag;
6416
6262
  Template.toJSON = TemplateBase.toJSON;
6417
6263
  Template.toDockerfile = TemplateBase.toDockerfile;
6418
6264
 
@@ -6444,6 +6290,7 @@ export {
6444
6290
  ReadyCmd,
6445
6291
  RegionCapacityError,
6446
6292
  Sandbox,
6293
+ SandboxCreateFailedError,
6447
6294
  SandboxCreateRejectedError,
6448
6295
  SandboxError,
6449
6296
  SandboxRegionScope,