@getexception/cli 0.1.23 → 0.1.25

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.
@@ -31,10 +31,10 @@ declare function validateGitLabContext(value: unknown, env: NodeJS.ProcessEnv, o
31
31
  release: string;
32
32
  assetPrefix: string;
33
33
  deployment: {
34
- environment: "production" | "staging" | "development";
34
+ environment: string;
35
35
  review?: {
36
- provider: "gitlab";
37
- repositoryId: number;
36
+ provider: "gitlab" | "github" | "other";
37
+ repositoryId: string | number;
38
38
  number: number;
39
39
  } | undefined;
40
40
  };
@@ -60,4 +60,44 @@ declare function assertPublicOutput(root: string, options?: {
60
60
  mapsEnabled?: boolean;
61
61
  }): Promise<void>;
62
62
 
63
- export { type GitLabDeploymentOptions, type GitLabDeploymentResult, assertPublicOutput, deployWithGetException, validateGitLabContext };
63
+ type PrepareSourceMapsOptions = {
64
+ directory: string;
65
+ output: string;
66
+ release: string;
67
+ buildId: string;
68
+ urlPrefix?: string;
69
+ format?: "esm" | "classic";
70
+ credentials?: string[];
71
+ signal?: AbortSignal;
72
+ };
73
+ declare function prepareSourceMaps(options: PrepareSourceMapsOptions): Promise<{
74
+ directory: string;
75
+ release: string;
76
+ buildId: string;
77
+ }>;
78
+ type SourceMapDeliveryOptions = {
79
+ directory: string;
80
+ url: string;
81
+ projectId: string;
82
+ token: string | undefined;
83
+ environment: string;
84
+ timeoutMs?: number;
85
+ signal?: AbortSignal;
86
+ };
87
+ declare function uploadSourceMaps(options: SourceMapDeliveryOptions, transport?: typeof fetch): Promise<{
88
+ status: "ready";
89
+ batches: number;
90
+ diagnostic?: undefined;
91
+ } | {
92
+ status: "unavailable";
93
+ diagnostic: string;
94
+ batches?: undefined;
95
+ }>;
96
+
97
+ type CiCredential = string | {
98
+ gitlabIdToken: string;
99
+ };
100
+
101
+ declare function registerRelease(address: string, project: string, token: CiCredential, value: unknown, transport?: typeof fetch): Promise<void>;
102
+
103
+ export { type GitLabDeploymentOptions, type GitLabDeploymentResult, type PrepareSourceMapsOptions, type SourceMapDeliveryOptions, assertPublicOutput, deployWithGetException, prepareSourceMaps, registerRelease, uploadSourceMaps, validateGitLabContext };
@@ -1820,18 +1820,18 @@ var validateAsync = async (schema, value, _ctx) => {
1820
1820
  return result.issues.length === 0;
1821
1821
  };
1822
1822
  var _encode = (_Err) => {
1823
- const parse4 = _parse(_Err);
1823
+ const parse5 = _parse(_Err);
1824
1824
  const fn = (schema, value, _ctx, _params) => {
1825
1825
  const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
1826
- return parse4(schema, value, ctx, finalizeParams(fn, _params));
1826
+ return parse5(schema, value, ctx, finalizeParams(fn, _params));
1827
1827
  };
1828
1828
  return fn;
1829
1829
  };
1830
1830
  var encode = /* @__PURE__ */ _encode($ZodRealError);
1831
1831
  var _decode = (_Err) => {
1832
- const parse4 = _parse(_Err);
1832
+ const parse5 = _parse(_Err);
1833
1833
  const fn = (schema, value, _ctx, _params) => {
1834
- return parse4(schema, value, _ctx, finalizeParams(fn, _params));
1834
+ return parse5(schema, value, _ctx, finalizeParams(fn, _params));
1835
1835
  };
1836
1836
  return fn;
1837
1837
  };
@@ -18885,7 +18885,12 @@ var SOURCE_MAP_LIMITS = {
18885
18885
  diskReserveBytes: 5 * 1024 * 1024 * 1024,
18886
18886
  manifestBytes: 64 * 1024
18887
18887
  };
18888
- var releaseNameSchema = external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,79}@[a-f0-9]{40}$/);
18888
+ var releaseNameSchema = external_exports.string().max(160).regex(/^[A-Za-z0-9][A-Za-z0-9._+-]*(?:@[A-Za-z0-9][A-Za-z0-9._+-]*)?$/).refine((value) => !/^[^@]+@[a-zA-Z][^@]*\.[a-zA-Z]{2,}$/.test(value));
18889
+ var environmentNameSchema = external_exports.string().max(64).regex(/^[a-z][a-z0-9_-]{0,63}$/).refine(
18890
+ (value) => !["all", "constructor", "prototype", "__proto__"].includes(value)
18891
+ );
18892
+ var buildIdSchema = external_exports.string().max(64).regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/);
18893
+ var environmentListSchema = external_exports.array(environmentNameSchema).max(20).refine((values) => new Set(values).size === values.length);
18889
18894
  var artifactPathSchema = external_exports.string().max(512).regex(/^[a-zA-Z0-9_@~.-]+(?:\/[a-zA-Z0-9_@~.-]+)*\.(?:js|mjs)$/).refine(
18890
18895
  (value) => !value.split("/").some((part) => part === "." || part === "..")
18891
18896
  );
@@ -18897,9 +18902,13 @@ var sourceArtifactSchema = external_exports.object({
18897
18902
  }).strict();
18898
18903
  var sourceUploadSchema = external_exports.object({
18899
18904
  release: releaseNameSchema,
18905
+ environment: environmentNameSchema.optional(),
18906
+ buildId: buildIdSchema.optional(),
18907
+ batchIndex: external_exports.number().int().min(0).max(4095).optional(),
18908
+ batchCount: external_exports.number().int().min(1).max(4096).optional(),
18900
18909
  artifacts: external_exports.array(sourceArtifactSchema).min(1).max(SOURCE_MAP_LIMITS.files)
18901
18910
  }).strict().superRefine((value, ctx) => {
18902
- if (value.artifacts.reduce((sum, file2) => sum + file2.size, 0) > SOURCE_MAP_LIMITS.releaseBytes || new Set(value.artifacts.map((file2) => file2.path)).size !== value.artifacts.length || new Set(value.artifacts.map((file2) => file2.debugId)).size !== value.artifacts.length) {
18911
+ if ((value.batchIndex !== void 0 || value.batchCount !== void 0) && (value.batchIndex === void 0 || value.batchCount === void 0 || value.batchIndex >= value.batchCount) || value.artifacts.reduce((sum, file2) => sum + file2.size, 0) > SOURCE_MAP_LIMITS.releaseBytes || new Set(value.artifacts.map((file2) => file2.path)).size !== value.artifacts.length || new Set(value.artifacts.map((file2) => file2.debugId)).size !== value.artifacts.length) {
18903
18912
  ctx.addIssue({ code: "custom", message: "Invalid artifact manifest" });
18904
18913
  }
18905
18914
  });
@@ -18924,20 +18933,18 @@ function sanitizeAppVersion(value) {
18924
18933
  const parsed = appVersionSchema.safeParse(value);
18925
18934
  return parsed.success ? parsed.data : void 0;
18926
18935
  }
18927
- var RELEASE_ENVIRONMENTS = [
18928
- "production",
18929
- "staging",
18930
- "development"
18931
- ];
18932
18936
  var deploymentSchema = external_exports.object({
18933
- environment: external_exports.enum(RELEASE_ENVIRONMENTS),
18937
+ environment: environmentNameSchema,
18934
18938
  review: external_exports.object({
18935
- provider: external_exports.literal("gitlab"),
18936
- repositoryId: external_exports.number().int().min(1).max(2147483647),
18939
+ provider: external_exports.enum(["gitlab", "github", "other"]),
18940
+ repositoryId: external_exports.union([
18941
+ external_exports.number().int().min(1).max(2147483647),
18942
+ external_exports.string().max(200).regex(/^[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)+$/)
18943
+ ]),
18937
18944
  number: external_exports.number().int().min(1).max(2147483647)
18938
18945
  }).strict().optional()
18939
- }).strict().refine((value) => !value.review || value.environment === "staging", {
18940
- message: "Merge requests belong to staging"
18946
+ }).strict().refine((value) => !value.review || value.environment !== "production", {
18947
+ message: "Reviews belong to non-production environments"
18941
18948
  });
18942
18949
  var releaseRegistrationSchema = external_exports.object({
18943
18950
  release: releaseNameSchema,
@@ -19061,7 +19068,7 @@ var safeEventSchema = external_exports.object({
19061
19068
  message: external_exports.string().max(1024),
19062
19069
  exceptionType: external_exports.string().max(120),
19063
19070
  handled: external_exports.boolean(),
19064
- environment: external_exports.enum(["production", "staging", "development"]),
19071
+ environment: environmentNameSchema,
19065
19072
  release: external_exports.string().max(160).optional(),
19066
19073
  appVersion: appVersionSchema.optional(),
19067
19074
  dist: external_exports.string().max(64).optional(),
@@ -19088,7 +19095,13 @@ var codeSchema = external_exports.enum([
19088
19095
  "HTTP_ERROR",
19089
19096
  "CONTRACT_JSON",
19090
19097
  "CONTRACT_RESPONSE",
19091
- "COMMAND_FAILED"
19098
+ "COMMAND_FAILED",
19099
+ "ENVIRONMENT_FORBIDDEN",
19100
+ "BUILD_CONFLICT",
19101
+ "INVALID_UPLOAD",
19102
+ "STORAGE_FULL",
19103
+ "RATE_LIMITED",
19104
+ "UPLOAD_UNAVAILABLE"
19092
19105
  ]);
19093
19106
  var diagnosticSchema = external_exports.object({
19094
19107
  version: external_exports.literal(1),
@@ -19107,6 +19120,17 @@ var CliError = class extends Error {
19107
19120
  httpStatus;
19108
19121
  requestId;
19109
19122
  };
19123
+ function formatDiagnostic(error61) {
19124
+ const safe = diagnosticSchema.safeParse({
19125
+ version: 1,
19126
+ code: error61 instanceof CliError ? error61.code : "COMMAND_FAILED",
19127
+ ...error61 instanceof CliError ? { httpStatus: error61.httpStatus, requestId: error61.requestId } : {}
19128
+ });
19129
+ return `GETEXCEPTION_DIAGNOSTIC ${JSON.stringify(
19130
+ safe.success ? safe.data : { version: 1, code: "COMMAND_FAILED" }
19131
+ )}
19132
+ `;
19133
+ }
19110
19134
  function networkError(error61, httpStatus) {
19111
19135
  let current = error61;
19112
19136
  for (let depth = 0; depth < 4 && current instanceof Error; depth++) {
@@ -19159,6 +19183,17 @@ function authorizationHeader(credential) {
19159
19183
  }
19160
19184
 
19161
19185
  // packages/cli/src/api-response.ts
19186
+ var uploadFailureSchema = external_exports.object({
19187
+ code: external_exports.enum([
19188
+ "ENVIRONMENT_FORBIDDEN",
19189
+ "BUILD_CONFLICT",
19190
+ "INVALID_UPLOAD",
19191
+ "STORAGE_FULL",
19192
+ "RATE_LIMITED",
19193
+ "UPLOAD_UNAVAILABLE"
19194
+ ]),
19195
+ requestId: external_exports.string().uuid()
19196
+ });
19162
19197
  async function responseJson(response) {
19163
19198
  const reader = response.body?.getReader();
19164
19199
  const chunks = [];
@@ -19208,6 +19243,14 @@ async function httpError(response) {
19208
19243
  result.data.requestId
19209
19244
  );
19210
19245
  }
19246
+ const upload = uploadFailureSchema.safeParse(candidate);
19247
+ if (upload.success) {
19248
+ return new CliError(
19249
+ upload.data.code,
19250
+ response.status,
19251
+ upload.data.requestId
19252
+ );
19253
+ }
19211
19254
  }
19212
19255
  } catch {
19213
19256
  }
@@ -19242,6 +19285,9 @@ function projectApi(address, project, token, transport = fetch, options = {}) {
19242
19285
  const requestTimeout = options.requestTimeoutMs ?? 3e4;
19243
19286
  return async function request(path, method = "GET", body, contentEncoding) {
19244
19287
  for (let attempt = 0; attempt < 3; attempt++) {
19288
+ if (options.signal?.aborted) {
19289
+ throw new CliError("NETWORK_TIMEOUT");
19290
+ }
19245
19291
  if (Date.now() >= deadline) {
19246
19292
  throw new CliError("NETWORK_TIMEOUT");
19247
19293
  }
@@ -19257,14 +19303,21 @@ function projectApi(address, project, token, transport = fetch, options = {}) {
19257
19303
  body,
19258
19304
  redirect: "error",
19259
19305
  credentials: "omit",
19260
- signal: AbortSignal.timeout(
19261
- Math.min(requestTimeout, deadline - Date.now())
19262
- )
19306
+ signal: AbortSignal.any([
19307
+ AbortSignal.timeout(
19308
+ Math.min(requestTimeout, deadline - Date.now())
19309
+ ),
19310
+ ...options.signal ? [options.signal] : []
19311
+ ])
19263
19312
  });
19264
19313
  } catch (error61) {
19265
19314
  const failure = networkError(error61);
19266
19315
  if (retryableNetworkError(failure) && attempt < 2) {
19267
- await delay(1e3 * 2 ** attempt);
19316
+ await delay(
19317
+ Math.min(1e3 * 2 ** attempt, Math.max(1, deadline - Date.now())),
19318
+ void 0,
19319
+ { signal: options.signal }
19320
+ );
19268
19321
  continue;
19269
19322
  }
19270
19323
  throw failure;
@@ -19274,7 +19327,11 @@ function projectApi(address, project, token, transport = fetch, options = {}) {
19274
19327
  }
19275
19328
  if ((response.status === 429 || response.status >= 500) && attempt < 2) {
19276
19329
  await response.body?.cancel().catch(() => void 0);
19277
- await delay(1e3 * 2 ** attempt);
19330
+ await delay(
19331
+ Math.min(1e3 * 2 ** attempt, Math.max(1, deadline - Date.now())),
19332
+ void 0,
19333
+ { signal: options.signal }
19334
+ );
19278
19335
  continue;
19279
19336
  }
19280
19337
  throw await httpError(response);
@@ -19314,6 +19371,7 @@ import { dirname as dirname2, join as join3, relative as relative3 } from "path"
19314
19371
 
19315
19372
  // packages/cli/src/prepare.ts
19316
19373
  import { createHash, randomUUID } from "crypto";
19374
+ import { parse as parse3 } from "acorn";
19317
19375
  import {
19318
19376
  lstat,
19319
19377
  mkdir,
@@ -19359,7 +19417,7 @@ async function files(root, directory = root, result = []) {
19359
19417
  }
19360
19418
  return result;
19361
19419
  }
19362
- async function prepareMaps(directory, output2, release, prefix = "") {
19420
+ async function prepareMaps(directory, output2, release, prefix = "", options = {}) {
19363
19421
  const root = await realpath(directory);
19364
19422
  const destination = join(
19365
19423
  await realpath(dirname(resolve(output2))),
@@ -19367,6 +19425,9 @@ async function prepareMaps(directory, output2, release, prefix = "") {
19367
19425
  );
19368
19426
  const child = relative(root, destination);
19369
19427
  releaseNameSchema.parse(release);
19428
+ if (options.buildId) {
19429
+ buildIdSchema.parse(options.buildId);
19430
+ }
19370
19431
  if (!child || !isAbsolute(child) && child !== ".." && !child.startsWith(`..${sep}`)) {
19371
19432
  throw new Error(
19372
19433
  "Private artifacts must be outside the public build directory"
@@ -19392,7 +19453,7 @@ async function prepareMaps(directory, output2, release, prefix = "") {
19392
19453
  (await regular(join(root, mapPath), SOURCE_MAP_LIMITS.fileBytes)).toString("utf8")
19393
19454
  );
19394
19455
  const source = (await regular(join(root, jsPath), SOURCE_MAP_LIMITS.fileBytes)).toString("utf8");
19395
- if (map2.version !== 3 || typeof map2.mappings !== "string" || map2.sections || map2.debug_id || source.startsWith(
19456
+ if (map2.version !== 3 || typeof map2.mappings !== "string" || map2.sections || map2.debug_id || source.startsWith("#!") || source.startsWith(
19396
19457
  ";(globalThis.__GETEXCEPTION_DEBUG_IDS__??=Object.create(null))"
19397
19458
  )) {
19398
19459
  throw new Error("Expected a fresh, non-indexed v3 source map");
@@ -19417,12 +19478,29 @@ async function prepareMaps(directory, output2, release, prefix = "") {
19417
19478
  /(?:^|\n)[ \t]*(?:\/\/[#@][ \t]*sourceMappingURL=[^\r\n]*|\/\*[#@][ \t]*sourceMappingURL=[^\r\n]*?\*\/)[ \t]*(?:\r?\n)?$/,
19418
19479
  (comment) => comment.replace(/[^\r\n]/g, " ")
19419
19480
  );
19420
- const js = `;(globalThis.__GETEXCEPTION_DEBUG_IDS__??=Object.create(null))[import.meta.url]=${JSON.stringify(debugId)};
19481
+ const directives = [];
19482
+ if (options.format === "classic") {
19483
+ const program = parse3(source, {
19484
+ ecmaVersion: "latest",
19485
+ sourceType: "script"
19486
+ });
19487
+ for (const statement of program.body) {
19488
+ if (!("directive" in statement) || typeof statement.directive !== "string") {
19489
+ break;
19490
+ }
19491
+ directives.push(statement.directive);
19492
+ }
19493
+ }
19494
+ const injection = options.format === "classic" ? `${directives.map((value) => JSON.stringify(value) + ";").join("")};(()=>{const s=typeof document!=="undefined"?document.currentScript?.src:undefined;if(s)(globalThis.__GETEXCEPTION_DEBUG_IDS__??=Object.create(null))[s]=${JSON.stringify(debugId)};})();` : `;(globalThis.__GETEXCEPTION_DEBUG_IDS__??=Object.create(null))[import.meta.url]=${JSON.stringify(debugId)};`;
19495
+ const js = `${injection}
19421
19496
  ${body}`;
19422
19497
  prepared.push({ mapPath, jsPath, bytes, js, entry });
19423
19498
  }
19424
19499
  const manifest = sourceUploadSchema.parse({
19425
19500
  release,
19501
+ ...options.buildId ? { buildId: options.buildId } : {},
19502
+ ...options.environment ? { environment: options.environment } : {},
19503
+ ...options.batchIndex !== void 0 ? { batchIndex: options.batchIndex, batchCount: options.batchCount } : {},
19426
19504
  artifacts: prepared.map((item) => item.entry)
19427
19505
  });
19428
19506
  await mkdir(destination, { mode: 448 });
@@ -19472,7 +19550,7 @@ import { lstat as lstat2, readFile as readFile2, readdir as readdir2 } from "fs/
19472
19550
  import { basename as basename2, extname, join as join2, relative as relative2, sep as sep2 } from "path";
19473
19551
  import { brotliDecompress, gunzip } from "zlib";
19474
19552
  import { promisify } from "util";
19475
- import { parse as parse3 } from "acorn";
19553
+ import { parse as parse4 } from "acorn";
19476
19554
  import postcss from "postcss";
19477
19555
  var gunzipAsync = promisify(gunzip);
19478
19556
  var brotliAsync = promisify(brotliDecompress);
@@ -19512,7 +19590,7 @@ function hasInlineMap(source, extension) {
19512
19590
  return found2;
19513
19591
  }
19514
19592
  let found = false;
19515
- parse3(source, {
19593
+ parse4(source, {
19516
19594
  ecmaVersion: "latest",
19517
19595
  sourceType: extension === ".cjs" ? "script" : "module",
19518
19596
  onComment: (_block, comment) => {
@@ -19568,7 +19646,7 @@ async function assertPublicOutput(root, options = {}) {
19568
19646
 
19569
19647
  // packages/cli/src/prepare-build.ts
19570
19648
  var maxBuildMaps = 4096;
19571
- async function prepareBuild(output2, privateRoot, release, signal = AbortSignal.timeout(5 * 6e4)) {
19649
+ async function prepareBuild(output2, privateRoot, release, signal = AbortSignal.timeout(5 * 6e4), options = {}) {
19572
19650
  signal.throwIfAborted();
19573
19651
  const paths = await listPublicFiles(output2);
19574
19652
  const maps = paths.filter((file2) => /\.(?:m?js)\.map$/i.test(file2)).sort();
@@ -19618,7 +19696,10 @@ async function prepareBuild(output2, privateRoot, release, signal = AbortSignal.
19618
19696
  await copyFile(file2, copy);
19619
19697
  }
19620
19698
  }
19621
- await prepareMaps(staging, destination, release);
19699
+ await prepareMaps(staging, destination, release, options.urlPrefix, {
19700
+ ...options,
19701
+ ...options.buildId ? { batchIndex: index, batchCount: batches.length } : {}
19702
+ });
19622
19703
  signal.throwIfAborted();
19623
19704
  for (const map2 of batch) {
19624
19705
  const js = map2.slice(0, -4);
@@ -19676,11 +19757,16 @@ var receiptSchema = external_exports.object({
19676
19757
  var uploadConcurrency = 8;
19677
19758
  var uploadDeadlineMs = 20 * 6e4;
19678
19759
  var gzipAsync = promisify2(gzip);
19679
- async function uploadMaps(directory, address, project, token, transport = fetch) {
19680
- const manifest = await readPrepared(directory);
19760
+ async function uploadMaps(directory, address, project, token, transport = fetch, options = {}) {
19761
+ const prepared = await readPrepared(directory);
19762
+ const manifest = sourceUploadSchema.parse({
19763
+ ...prepared,
19764
+ ...options.environment ? { environment: options.environment } : {}
19765
+ });
19681
19766
  const api = projectApi(address, project, token, transport, {
19682
- deadlineMs: uploadDeadlineMs,
19683
- requestTimeoutMs: 6e4
19767
+ deadlineMs: options.deadlineMs ?? uploadDeadlineMs,
19768
+ requestTimeoutMs: 6e4,
19769
+ signal: options.signal
19684
19770
  });
19685
19771
  const request = (path, method = "GET", body, contentEncoding) => api("/source-maps" + path, method, body, contentEncoding);
19686
19772
  const receipt = receiptSchema.parse(
@@ -19728,7 +19814,7 @@ async function uploadMaps(directory, address, project, token, transport = fetch)
19728
19814
  if (result.status === "failed") {
19729
19815
  throw new Error("Source map validation failed; rebuild the artifacts");
19730
19816
  }
19731
- await delay2(1e3);
19817
+ await delay2(1e3, void 0, { signal: options.signal });
19732
19818
  }
19733
19819
  }
19734
19820
 
@@ -19936,8 +20022,102 @@ async function deployWithGetException(options) {
19936
20022
  }
19937
20023
  }
19938
20024
  }
20025
+
20026
+ // packages/cli/src/source-map-delivery.ts
20027
+ import { mkdir as mkdir3, realpath as realpath2, readdir as readdir4, rm as rm3 } from "fs/promises";
20028
+ import { dirname as dirname3, resolve as resolve2, relative as relative4, isAbsolute as isAbsolute2, sep as sep3, join as join5 } from "path";
20029
+ async function prepareSourceMaps(options) {
20030
+ releaseNameSchema.parse(options.release);
20031
+ buildIdSchema.parse(options.buildId);
20032
+ const directory = await realpath2(options.directory);
20033
+ const target = resolve2(options.output);
20034
+ const output2 = join5(
20035
+ await realpath2(dirname3(target)),
20036
+ target.slice(dirname3(target).length + 1)
20037
+ );
20038
+ const child = relative4(directory, output2);
20039
+ if (!child || !isAbsolute2(child) && child !== ".." && !child.startsWith(`..${sep3}`)) {
20040
+ throw new CliError("CLI_CONFIGURATION");
20041
+ }
20042
+ await mkdir3(output2, { mode: 448 });
20043
+ try {
20044
+ const maps = await prepareBuild(
20045
+ directory,
20046
+ output2,
20047
+ options.release,
20048
+ options.signal,
20049
+ options
20050
+ );
20051
+ await assertPublicOutput(directory, {
20052
+ mapsEnabled: true,
20053
+ credentials: options.credentials
20054
+ });
20055
+ await rm3(join5(output2, "work"), { recursive: true });
20056
+ return {
20057
+ directory: maps,
20058
+ release: options.release,
20059
+ buildId: options.buildId
20060
+ };
20061
+ } catch (error61) {
20062
+ await rm3(output2, { recursive: true, force: true });
20063
+ throw error61;
20064
+ }
20065
+ }
20066
+ async function uploadSourceMaps(options, transport = fetch) {
20067
+ try {
20068
+ options.signal?.throwIfAborted();
20069
+ if (typeof options.token !== "string") {
20070
+ throw new CliError("CLI_CONFIGURATION");
20071
+ }
20072
+ authorizationHeader(options.token);
20073
+ const environment = environmentNameSchema.parse(options.environment);
20074
+ const budget = options.timeoutMs ?? 30 * 6e4;
20075
+ if (!Number.isInteger(budget) || budget < 1e3 || budget > 60 * 6e4) {
20076
+ throw new CliError("CLI_CONFIGURATION");
20077
+ }
20078
+ const deadline = Date.now() + budget;
20079
+ const entries = await readdir4(options.directory, { withFileTypes: true });
20080
+ const batches = entries.filter((entry) => /^batch-[0-9]{3,4}$/.test(entry.name)).sort((a, b) => Number(a.name.slice(6)) - Number(b.name.slice(6)));
20081
+ if (!batches.length || batches.length > 4096 || batches.some((entry) => !entry.isDirectory() || entry.isSymbolicLink()) || batches.length !== entries.length) {
20082
+ throw new CliError("CLI_CONFIGURATION");
20083
+ }
20084
+ const manifests = await Promise.all(
20085
+ batches.map((entry) => readPrepared(join5(options.directory, entry.name)))
20086
+ );
20087
+ const first = manifests[0];
20088
+ if (!first.buildId || manifests.some(
20089
+ (manifest, index) => manifest.buildId !== first.buildId || manifest.release !== first.release || manifest.batchCount !== batches.length || manifest.batchIndex !== index
20090
+ )) {
20091
+ throw new CliError("CLI_CONFIGURATION");
20092
+ }
20093
+ for (const batch of batches) {
20094
+ options.signal?.throwIfAborted();
20095
+ const remaining = deadline - Date.now();
20096
+ if (remaining < 1) {
20097
+ throw new CliError("NETWORK_TIMEOUT");
20098
+ }
20099
+ await uploadMaps(
20100
+ join5(options.directory, batch.name),
20101
+ options.url,
20102
+ options.projectId,
20103
+ options.token,
20104
+ transport,
20105
+ { environment, deadlineMs: remaining, signal: options.signal }
20106
+ );
20107
+ }
20108
+ return { status: "ready", batches: batches.length };
20109
+ } catch (error61) {
20110
+ return {
20111
+ status: "unavailable",
20112
+ diagnostic: formatDiagnostic(error61).trim()
20113
+ };
20114
+ }
20115
+ }
19939
20116
  export {
19940
20117
  assertPublicOutput,
19941
20118
  deployWithGetException,
20119
+ prepareSourceMaps,
20120
+ registerRelease,
20121
+ uploadSourceMaps,
19942
20122
  validateGitLabContext
19943
20123
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getexception/cli",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "Private source map uploads for GetException",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "repository": {
33
33
  "type": "git",
34
- "url": "git+https://github.com/GetException/GetException.git",
34
+ "url": "git+https://gitlab.sndsy.ru/sendsay-ru/frontend/getexception.git",
35
35
  "directory": "packages/cli"
36
36
  },
37
37
  "dependencies": {