@glasstrace/sdk 0.4.1 → 0.7.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/{chunk-STECO33B.js → chunk-PLJVIWHN.js} +1 -1
- package/dist/chunk-PLJVIWHN.js.map +1 -0
- package/dist/{chunk-EC5IINUT.js → chunk-QW6W4CSA.js} +64 -5
- package/dist/chunk-QW6W4CSA.js.map +1 -0
- package/dist/{chunk-LAMTBURS.js → chunk-SALPGSWK.js} +2 -2
- package/dist/cli/init.cjs +46 -2
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +3 -3
- package/dist/cli/mcp-add.cjs +45 -1
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.js +2 -2
- package/dist/index.cjs +291 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -5
- package/dist/index.d.ts +74 -5
- package/dist/index.js +231 -49
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
- package/dist/chunk-EC5IINUT.js.map +0 -1
- package/dist/chunk-STECO33B.js.map +0 -1
- /package/dist/{chunk-LAMTBURS.js.map → chunk-SALPGSWK.js.map} +0 -0
package/dist/cli/mcp-add.js
CHANGED
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
scaffoldMcpMarker,
|
|
7
7
|
updateGitignore,
|
|
8
8
|
writeMcpConfig
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-PLJVIWHN.js";
|
|
10
10
|
import {
|
|
11
11
|
readAnonKey
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-QW6W4CSA.js";
|
|
13
13
|
import "../chunk-PZ5AY32C.js";
|
|
14
14
|
|
|
15
15
|
// src/cli/mcp-add.ts
|
package/dist/index.cjs
CHANGED
|
@@ -1617,6 +1617,7 @@ var src_exports = {};
|
|
|
1617
1617
|
__export(src_exports, {
|
|
1618
1618
|
GlasstraceExporter: () => GlasstraceExporter,
|
|
1619
1619
|
GlasstraceSpanProcessor: () => GlasstraceSpanProcessor,
|
|
1620
|
+
PRESIGNED_THRESHOLD_BYTES: () => PRESIGNED_THRESHOLD_BYTES,
|
|
1620
1621
|
SdkError: () => SdkError,
|
|
1621
1622
|
SessionManager: () => SessionManager,
|
|
1622
1623
|
buildImportGraph: () => buildImportGraph,
|
|
@@ -1644,6 +1645,8 @@ __export(src_exports, {
|
|
|
1644
1645
|
saveCachedConfig: () => saveCachedConfig,
|
|
1645
1646
|
sendInitRequest: () => sendInitRequest,
|
|
1646
1647
|
uploadSourceMaps: () => uploadSourceMaps,
|
|
1648
|
+
uploadSourceMapsAuto: () => uploadSourceMapsAuto,
|
|
1649
|
+
uploadSourceMapsPresigned: () => uploadSourceMapsPresigned,
|
|
1647
1650
|
withGlasstraceConfig: () => withGlasstraceConfig
|
|
1648
1651
|
});
|
|
1649
1652
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -15556,7 +15559,12 @@ var SdkInitResponseSchema = external_exports.object({
|
|
|
15556
15559
|
linkedAccountId: external_exports.string().uuid().optional(),
|
|
15557
15560
|
minimumSdkVersion: external_exports.string(),
|
|
15558
15561
|
apiVersion: external_exports.string(),
|
|
15559
|
-
tierLimits: TierLimitsSchema
|
|
15562
|
+
tierLimits: TierLimitsSchema,
|
|
15563
|
+
claimResult: external_exports.object({
|
|
15564
|
+
newApiKey: DevApiKeySchema,
|
|
15565
|
+
accountId: external_exports.string().uuid(),
|
|
15566
|
+
graceExpiresAt: external_exports.number().int().positive()
|
|
15567
|
+
}).optional()
|
|
15560
15568
|
});
|
|
15561
15569
|
var DiscoveryResponseSchema = external_exports.object({
|
|
15562
15570
|
key: AnonApiKeySchema,
|
|
@@ -15568,6 +15576,45 @@ var SourceMapUploadResponseSchema = external_exports.object({
|
|
|
15568
15576
|
fileCount: external_exports.number().int().nonnegative(),
|
|
15569
15577
|
totalSizeBytes: external_exports.number().int().nonnegative()
|
|
15570
15578
|
});
|
|
15579
|
+
var PresignedUploadRequestSchema = external_exports.object({
|
|
15580
|
+
buildHash: BuildHashSchema,
|
|
15581
|
+
files: external_exports.array(
|
|
15582
|
+
external_exports.object({
|
|
15583
|
+
filePath: external_exports.string().min(1),
|
|
15584
|
+
sizeBytes: external_exports.number().int().positive()
|
|
15585
|
+
})
|
|
15586
|
+
).min(1).max(100)
|
|
15587
|
+
});
|
|
15588
|
+
var PresignedUploadResponseSchema = external_exports.object({
|
|
15589
|
+
uploadId: external_exports.string().uuid(),
|
|
15590
|
+
expiresAt: external_exports.number().int().positive(),
|
|
15591
|
+
files: external_exports.array(
|
|
15592
|
+
external_exports.object({
|
|
15593
|
+
filePath: external_exports.string().min(1),
|
|
15594
|
+
clientToken: external_exports.string().min(1),
|
|
15595
|
+
pathname: external_exports.string().min(1),
|
|
15596
|
+
maxBytes: external_exports.number().int().positive()
|
|
15597
|
+
})
|
|
15598
|
+
).min(1).max(100)
|
|
15599
|
+
});
|
|
15600
|
+
var SourceMapManifestRequestSchema = external_exports.object({
|
|
15601
|
+
uploadId: external_exports.string().uuid(),
|
|
15602
|
+
buildHash: BuildHashSchema,
|
|
15603
|
+
files: external_exports.array(
|
|
15604
|
+
external_exports.object({
|
|
15605
|
+
filePath: external_exports.string().min(1),
|
|
15606
|
+
sizeBytes: external_exports.number().int().positive(),
|
|
15607
|
+
blobUrl: external_exports.string().url()
|
|
15608
|
+
})
|
|
15609
|
+
).min(1).max(100)
|
|
15610
|
+
});
|
|
15611
|
+
var SourceMapManifestResponseSchema = external_exports.object({
|
|
15612
|
+
success: external_exports.literal(true),
|
|
15613
|
+
buildHash: BuildHashSchema,
|
|
15614
|
+
fileCount: external_exports.number().int().nonnegative(),
|
|
15615
|
+
totalSizeBytes: external_exports.number().int().nonnegative(),
|
|
15616
|
+
activatedAt: external_exports.number().int().positive()
|
|
15617
|
+
});
|
|
15571
15618
|
var GLASSTRACE_ATTRIBUTE_NAMES = {
|
|
15572
15619
|
// Server-side attributes
|
|
15573
15620
|
TRACE_TYPE: "glasstrace.trace.type",
|
|
@@ -15741,15 +15788,28 @@ async function getOrCreateAnonKey(projectRoot) {
|
|
|
15741
15788
|
const newKey = createAnonApiKey();
|
|
15742
15789
|
try {
|
|
15743
15790
|
await (0, import_promises.mkdir)(dirPath, { recursive: true, mode: 448 });
|
|
15744
|
-
await (0, import_promises.writeFile)(keyPath, newKey, "
|
|
15745
|
-
|
|
15791
|
+
await (0, import_promises.writeFile)(keyPath, newKey, { flag: "wx", mode: 384 });
|
|
15792
|
+
return newKey;
|
|
15746
15793
|
} catch (err) {
|
|
15794
|
+
const code = err.code;
|
|
15795
|
+
if (code === "EEXIST") {
|
|
15796
|
+
const winnerKey = await readAnonKey(root);
|
|
15797
|
+
if (winnerKey !== null) {
|
|
15798
|
+
return winnerKey;
|
|
15799
|
+
}
|
|
15800
|
+
try {
|
|
15801
|
+
await (0, import_promises.writeFile)(keyPath, newKey, { mode: 384 });
|
|
15802
|
+
await (0, import_promises.chmod)(keyPath, 384);
|
|
15803
|
+
return newKey;
|
|
15804
|
+
} catch {
|
|
15805
|
+
}
|
|
15806
|
+
}
|
|
15747
15807
|
ephemeralKeyCache.set(root, newKey);
|
|
15748
15808
|
console.warn(
|
|
15749
15809
|
`[glasstrace] Failed to persist anonymous key to ${keyPath}: ${err instanceof Error ? err.message : String(err)}. Using ephemeral key.`
|
|
15750
15810
|
);
|
|
15811
|
+
return newKey;
|
|
15751
15812
|
}
|
|
15752
|
-
return newKey;
|
|
15753
15813
|
}
|
|
15754
15814
|
|
|
15755
15815
|
// src/init-client.ts
|
|
@@ -15851,13 +15911,13 @@ async function sendInitRequest(config2, anonKey, sdkVersion, importGraph, health
|
|
|
15851
15911
|
async function performInit(config2, anonKey, sdkVersion) {
|
|
15852
15912
|
if (rateLimitBackoff) {
|
|
15853
15913
|
rateLimitBackoff = false;
|
|
15854
|
-
return;
|
|
15914
|
+
return null;
|
|
15855
15915
|
}
|
|
15856
15916
|
try {
|
|
15857
15917
|
const effectiveKey = config2.apiKey || anonKey;
|
|
15858
15918
|
if (!effectiveKey) {
|
|
15859
15919
|
console.warn("[glasstrace] No API key available for init request.");
|
|
15860
|
-
return;
|
|
15920
|
+
return null;
|
|
15861
15921
|
}
|
|
15862
15922
|
const controller = new AbortController();
|
|
15863
15923
|
const timeoutId = setTimeout(() => controller.abort(), INIT_TIMEOUT_MS);
|
|
@@ -15874,45 +15934,61 @@ async function performInit(config2, anonKey, sdkVersion) {
|
|
|
15874
15934
|
clearTimeout(timeoutId);
|
|
15875
15935
|
currentConfig = result;
|
|
15876
15936
|
await saveCachedConfig(result);
|
|
15937
|
+
if (result.claimResult) {
|
|
15938
|
+
try {
|
|
15939
|
+
process.stderr.write(
|
|
15940
|
+
`[glasstrace] Account claimed! Update GLASSTRACE_API_KEY=${result.claimResult.newApiKey} in your .env file.
|
|
15941
|
+
`
|
|
15942
|
+
);
|
|
15943
|
+
} catch (logErr) {
|
|
15944
|
+
console.warn(
|
|
15945
|
+
`[glasstrace] Failed to write claim migration message: ${logErr instanceof Error ? logErr.message : String(logErr)}`
|
|
15946
|
+
);
|
|
15947
|
+
}
|
|
15948
|
+
return { claimResult: result.claimResult };
|
|
15949
|
+
}
|
|
15950
|
+
return null;
|
|
15877
15951
|
} catch (err) {
|
|
15878
15952
|
clearTimeout(timeoutId);
|
|
15879
15953
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
15880
15954
|
console.warn("[glasstrace] ingestion_unreachable: Init request timed out.");
|
|
15881
|
-
return;
|
|
15955
|
+
return null;
|
|
15882
15956
|
}
|
|
15883
15957
|
const status = err.status;
|
|
15884
15958
|
if (status === 401) {
|
|
15885
15959
|
console.warn(
|
|
15886
15960
|
"[glasstrace] ingestion_auth_failed: Check your GLASSTRACE_API_KEY."
|
|
15887
15961
|
);
|
|
15888
|
-
return;
|
|
15962
|
+
return null;
|
|
15889
15963
|
}
|
|
15890
15964
|
if (status === 429) {
|
|
15891
15965
|
console.warn("[glasstrace] ingestion_rate_limited: Backing off.");
|
|
15892
15966
|
rateLimitBackoff = true;
|
|
15893
|
-
return;
|
|
15967
|
+
return null;
|
|
15894
15968
|
}
|
|
15895
15969
|
if (typeof status === "number" && status >= 400) {
|
|
15896
15970
|
console.warn(
|
|
15897
15971
|
`[glasstrace] Init request failed with status ${status}. Using cached config.`
|
|
15898
15972
|
);
|
|
15899
|
-
return;
|
|
15973
|
+
return null;
|
|
15900
15974
|
}
|
|
15901
15975
|
if (err instanceof Error && err.name === "ZodError") {
|
|
15902
15976
|
console.warn(
|
|
15903
15977
|
"[glasstrace] Init response failed validation (schema version mismatch?). Using cached config."
|
|
15904
15978
|
);
|
|
15905
|
-
return;
|
|
15979
|
+
return null;
|
|
15906
15980
|
}
|
|
15907
15981
|
console.warn(
|
|
15908
15982
|
`[glasstrace] ingestion_unreachable: ${err instanceof Error ? err.message : String(err)}`
|
|
15909
15983
|
);
|
|
15984
|
+
return null;
|
|
15910
15985
|
}
|
|
15911
15986
|
} catch (err) {
|
|
15912
15987
|
console.warn(
|
|
15913
15988
|
`[glasstrace] Unexpected init error: ${err instanceof Error ? err.message : String(err)}`
|
|
15914
15989
|
);
|
|
15915
15990
|
}
|
|
15991
|
+
return null;
|
|
15916
15992
|
}
|
|
15917
15993
|
function getActiveConfig() {
|
|
15918
15994
|
if (currentConfig) {
|
|
@@ -16023,9 +16099,13 @@ var GlasstraceExporter = class {
|
|
|
16023
16099
|
* Enriches a ReadableSpan with all glasstrace.* attributes.
|
|
16024
16100
|
* Returns a new ReadableSpan wrapper; the original span is not mutated.
|
|
16025
16101
|
*
|
|
16026
|
-
*
|
|
16027
|
-
*
|
|
16028
|
-
*
|
|
16102
|
+
* Only {@link SessionManager.getSessionId} is individually guarded because
|
|
16103
|
+
* it calls into crypto and schema validation — a session ID failure should
|
|
16104
|
+
* not prevent the rest of enrichment. The other helper calls
|
|
16105
|
+
* ({@link deriveErrorCategory}, {@link deriveOrmProvider},
|
|
16106
|
+
* {@link classifyFetchTarget}) are pure functions on typed string inputs
|
|
16107
|
+
* and rely on the outer catch for any unexpected failure.
|
|
16108
|
+
*
|
|
16029
16109
|
* On total failure, returns the original span unchanged.
|
|
16030
16110
|
*/
|
|
16031
16111
|
enrichSpan(span) {
|
|
@@ -16068,44 +16148,39 @@ var GlasstraceExporter = class {
|
|
|
16068
16148
|
}
|
|
16069
16149
|
}
|
|
16070
16150
|
const errorMessage = attrs["exception.message"];
|
|
16071
|
-
if (errorMessage) {
|
|
16151
|
+
if (typeof errorMessage === "string") {
|
|
16072
16152
|
extra[ATTR.ERROR_MESSAGE] = errorMessage;
|
|
16073
16153
|
}
|
|
16074
|
-
|
|
16075
|
-
|
|
16076
|
-
|
|
16077
|
-
|
|
16078
|
-
extra[ATTR.ERROR_CATEGORY] = deriveErrorCategory(errorType);
|
|
16079
|
-
}
|
|
16080
|
-
} catch {
|
|
16154
|
+
const errorType = attrs["exception.type"];
|
|
16155
|
+
if (typeof errorType === "string") {
|
|
16156
|
+
extra[ATTR.ERROR_CODE] = errorType;
|
|
16157
|
+
extra[ATTR.ERROR_CATEGORY] = deriveErrorCategory(errorType);
|
|
16081
16158
|
}
|
|
16082
16159
|
const errorField = attrs["error.field"];
|
|
16083
|
-
if (errorField) {
|
|
16160
|
+
if (typeof errorField === "string") {
|
|
16084
16161
|
extra[ATTR.ERROR_FIELD] = errorField;
|
|
16085
16162
|
}
|
|
16086
|
-
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
|
|
16095
|
-
|
|
16096
|
-
const operation = attrs["db.operation"];
|
|
16097
|
-
if (operation) {
|
|
16098
|
-
extra[ATTR.ORM_OPERATION] = operation;
|
|
16099
|
-
}
|
|
16163
|
+
const spanAny = span;
|
|
16164
|
+
const instrumentationName = spanAny.instrumentationScope?.name ?? spanAny.instrumentationLibrary?.name ?? "";
|
|
16165
|
+
const ormProvider = deriveOrmProvider(instrumentationName);
|
|
16166
|
+
if (ormProvider) {
|
|
16167
|
+
extra[ATTR.ORM_PROVIDER] = ormProvider;
|
|
16168
|
+
const table = attrs["db.sql.table"];
|
|
16169
|
+
const prismaModel = attrs["db.prisma.model"];
|
|
16170
|
+
const model = typeof table === "string" ? table : typeof prismaModel === "string" ? prismaModel : void 0;
|
|
16171
|
+
if (model) {
|
|
16172
|
+
extra[ATTR.ORM_MODEL] = model;
|
|
16100
16173
|
}
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
const url2 = attrs["http.url"] ?? attrs["url.full"];
|
|
16105
|
-
if (url2 && span.kind === SpanKind.CLIENT) {
|
|
16106
|
-
extra[ATTR.FETCH_TARGET] = classifyFetchTarget(url2);
|
|
16174
|
+
const operation = attrs["db.operation"];
|
|
16175
|
+
if (typeof operation === "string") {
|
|
16176
|
+
extra[ATTR.ORM_OPERATION] = operation;
|
|
16107
16177
|
}
|
|
16108
|
-
}
|
|
16178
|
+
}
|
|
16179
|
+
const httpUrl2 = attrs["http.url"];
|
|
16180
|
+
const fullUrl = attrs["url.full"];
|
|
16181
|
+
const url2 = typeof httpUrl2 === "string" ? httpUrl2 : typeof fullUrl === "string" ? fullUrl : void 0;
|
|
16182
|
+
if (url2 && span.kind === SpanKind.CLIENT) {
|
|
16183
|
+
extra[ATTR.FETCH_TARGET] = classifyFetchTarget(url2);
|
|
16109
16184
|
}
|
|
16110
16185
|
return createEnrichedSpan(span, extra);
|
|
16111
16186
|
} catch {
|
|
@@ -19054,6 +19129,14 @@ async function installConsoleCapture() {
|
|
|
19054
19129
|
}
|
|
19055
19130
|
};
|
|
19056
19131
|
}
|
|
19132
|
+
function sdkLog(level, message) {
|
|
19133
|
+
isGlasstraceLog = true;
|
|
19134
|
+
try {
|
|
19135
|
+
console[level](message);
|
|
19136
|
+
} finally {
|
|
19137
|
+
isGlasstraceLog = false;
|
|
19138
|
+
}
|
|
19139
|
+
}
|
|
19057
19140
|
|
|
19058
19141
|
// src/register.ts
|
|
19059
19142
|
var consoleCaptureInstalled = false;
|
|
@@ -19143,7 +19226,11 @@ function registerGlasstrace(options) {
|
|
|
19143
19226
|
if (config2.verbose) {
|
|
19144
19227
|
console.info("[glasstrace] Background init firing.");
|
|
19145
19228
|
}
|
|
19146
|
-
await performInit(config2, anonKey, "0.
|
|
19229
|
+
const initResult = await performInit(config2, anonKey, "0.7.0");
|
|
19230
|
+
if (initResult?.claimResult) {
|
|
19231
|
+
setResolvedApiKey(initResult.claimResult.newApiKey);
|
|
19232
|
+
notifyApiKeyResolved();
|
|
19233
|
+
}
|
|
19147
19234
|
maybeInstallConsoleCapture();
|
|
19148
19235
|
} catch (err) {
|
|
19149
19236
|
console.warn(
|
|
@@ -19163,7 +19250,11 @@ function registerGlasstrace(options) {
|
|
|
19163
19250
|
if (config2.verbose) {
|
|
19164
19251
|
console.info("[glasstrace] Background init firing.");
|
|
19165
19252
|
}
|
|
19166
|
-
await performInit(config2, anonKey, "0.
|
|
19253
|
+
const initResult = await performInit(config2, anonKey, "0.7.0");
|
|
19254
|
+
if (initResult?.claimResult) {
|
|
19255
|
+
setResolvedApiKey(initResult.claimResult.newApiKey);
|
|
19256
|
+
notifyApiKeyResolved();
|
|
19257
|
+
}
|
|
19167
19258
|
maybeInstallConsoleCapture();
|
|
19168
19259
|
} catch (err) {
|
|
19169
19260
|
console.warn(
|
|
@@ -19185,7 +19276,7 @@ function registerGlasstrace(options) {
|
|
|
19185
19276
|
if (config2.verbose) {
|
|
19186
19277
|
console.info("[glasstrace] Background init firing.");
|
|
19187
19278
|
}
|
|
19188
|
-
await performInit(config2, anonKeyForInit, "0.
|
|
19279
|
+
await performInit(config2, anonKeyForInit, "0.7.0");
|
|
19189
19280
|
maybeInstallConsoleCapture();
|
|
19190
19281
|
} catch (err) {
|
|
19191
19282
|
console.warn(
|
|
@@ -19284,10 +19375,7 @@ async function uploadSourceMaps(apiKey, endpoint, buildHash, maps) {
|
|
|
19284
19375
|
sourceMap: m.content
|
|
19285
19376
|
}))
|
|
19286
19377
|
};
|
|
19287
|
-
|
|
19288
|
-
while (baseUrl.endsWith("/")) {
|
|
19289
|
-
baseUrl = baseUrl.slice(0, -1);
|
|
19290
|
-
}
|
|
19378
|
+
const baseUrl = stripTrailingSlashes(endpoint);
|
|
19291
19379
|
const response = await fetch(`${baseUrl}/v1/source-maps`, {
|
|
19292
19380
|
method: "POST",
|
|
19293
19381
|
headers: {
|
|
@@ -19308,6 +19396,155 @@ async function uploadSourceMaps(apiKey, endpoint, buildHash, maps) {
|
|
|
19308
19396
|
const json2 = await response.json();
|
|
19309
19397
|
return SourceMapUploadResponseSchema.parse(json2);
|
|
19310
19398
|
}
|
|
19399
|
+
var PRESIGNED_THRESHOLD_BYTES = 45e5;
|
|
19400
|
+
function stripTrailingSlashes(url2) {
|
|
19401
|
+
let result = url2;
|
|
19402
|
+
while (result.endsWith("/")) {
|
|
19403
|
+
result = result.slice(0, -1);
|
|
19404
|
+
}
|
|
19405
|
+
return result;
|
|
19406
|
+
}
|
|
19407
|
+
async function requestPresignedTokens(apiKey, endpoint, buildHash, files) {
|
|
19408
|
+
const baseUrl = stripTrailingSlashes(endpoint);
|
|
19409
|
+
const response = await fetch(`${baseUrl}/v1/source-maps/presign`, {
|
|
19410
|
+
method: "POST",
|
|
19411
|
+
headers: {
|
|
19412
|
+
"Content-Type": "application/json",
|
|
19413
|
+
Authorization: `Bearer ${apiKey}`
|
|
19414
|
+
},
|
|
19415
|
+
body: JSON.stringify({ buildHash, files })
|
|
19416
|
+
});
|
|
19417
|
+
if (!response.ok) {
|
|
19418
|
+
try {
|
|
19419
|
+
await response.text();
|
|
19420
|
+
} catch {
|
|
19421
|
+
}
|
|
19422
|
+
throw new Error(
|
|
19423
|
+
`Presigned token request failed: ${String(response.status)} ${response.statusText}`
|
|
19424
|
+
);
|
|
19425
|
+
}
|
|
19426
|
+
const json2 = await response.json();
|
|
19427
|
+
return PresignedUploadResponseSchema.parse(json2);
|
|
19428
|
+
}
|
|
19429
|
+
async function uploadToBlob(clientToken, pathname, content) {
|
|
19430
|
+
let mod;
|
|
19431
|
+
try {
|
|
19432
|
+
mod = await import("@vercel/blob/client");
|
|
19433
|
+
} catch (err) {
|
|
19434
|
+
const code = err.code;
|
|
19435
|
+
if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") {
|
|
19436
|
+
throw new Error(
|
|
19437
|
+
"Presigned upload requires @vercel/blob. Install it: npm install @vercel/blob"
|
|
19438
|
+
);
|
|
19439
|
+
}
|
|
19440
|
+
throw err;
|
|
19441
|
+
}
|
|
19442
|
+
const result = await mod.put(pathname, new Blob([content]), {
|
|
19443
|
+
access: "public",
|
|
19444
|
+
token: clientToken
|
|
19445
|
+
});
|
|
19446
|
+
return { url: result.url, size: Buffer.byteLength(content, "utf-8") };
|
|
19447
|
+
}
|
|
19448
|
+
async function submitManifest(apiKey, endpoint, uploadId, buildHash, files) {
|
|
19449
|
+
const baseUrl = stripTrailingSlashes(endpoint);
|
|
19450
|
+
const response = await fetch(`${baseUrl}/v1/source-maps/manifest`, {
|
|
19451
|
+
method: "POST",
|
|
19452
|
+
headers: {
|
|
19453
|
+
"Content-Type": "application/json",
|
|
19454
|
+
Authorization: `Bearer ${apiKey}`
|
|
19455
|
+
},
|
|
19456
|
+
body: JSON.stringify({ uploadId, buildHash, files })
|
|
19457
|
+
});
|
|
19458
|
+
if (!response.ok) {
|
|
19459
|
+
try {
|
|
19460
|
+
await response.text();
|
|
19461
|
+
} catch {
|
|
19462
|
+
}
|
|
19463
|
+
throw new Error(
|
|
19464
|
+
`Source map manifest submission failed: ${String(response.status)} ${response.statusText}`
|
|
19465
|
+
);
|
|
19466
|
+
}
|
|
19467
|
+
const json2 = await response.json();
|
|
19468
|
+
return SourceMapManifestResponseSchema.parse(json2);
|
|
19469
|
+
}
|
|
19470
|
+
async function uploadSourceMapsPresigned(apiKey, endpoint, buildHash, maps, blobUploader = uploadToBlob) {
|
|
19471
|
+
if (maps.length === 0) {
|
|
19472
|
+
throw new Error("No source maps to upload");
|
|
19473
|
+
}
|
|
19474
|
+
const presigned = await requestPresignedTokens(
|
|
19475
|
+
apiKey,
|
|
19476
|
+
endpoint,
|
|
19477
|
+
buildHash,
|
|
19478
|
+
maps.map((m) => ({
|
|
19479
|
+
filePath: m.filePath,
|
|
19480
|
+
sizeBytes: Buffer.byteLength(m.content, "utf-8")
|
|
19481
|
+
}))
|
|
19482
|
+
);
|
|
19483
|
+
const mapsByPath = new Map(maps.map((m) => [m.filePath, m]));
|
|
19484
|
+
if (mapsByPath.size !== maps.length) {
|
|
19485
|
+
throw new Error("Duplicate filePath entries in source maps");
|
|
19486
|
+
}
|
|
19487
|
+
for (const token of presigned.files) {
|
|
19488
|
+
if (!mapsByPath.has(token.filePath)) {
|
|
19489
|
+
throw new Error(
|
|
19490
|
+
`Presigned token for "${token.filePath}" has no matching source map entry`
|
|
19491
|
+
);
|
|
19492
|
+
}
|
|
19493
|
+
}
|
|
19494
|
+
const CONCURRENCY = 5;
|
|
19495
|
+
const uploadResults = [];
|
|
19496
|
+
for (let i = 0; i < presigned.files.length; i += CONCURRENCY) {
|
|
19497
|
+
const chunk = presigned.files.slice(i, i + CONCURRENCY);
|
|
19498
|
+
const chunkResults = await Promise.all(
|
|
19499
|
+
chunk.map(async (token) => {
|
|
19500
|
+
const entry = mapsByPath.get(token.filePath);
|
|
19501
|
+
const result = await blobUploader(token.clientToken, token.pathname, entry.content);
|
|
19502
|
+
return {
|
|
19503
|
+
filePath: token.filePath,
|
|
19504
|
+
sizeBytes: result.size,
|
|
19505
|
+
blobUrl: result.url
|
|
19506
|
+
};
|
|
19507
|
+
})
|
|
19508
|
+
);
|
|
19509
|
+
uploadResults.push(...chunkResults);
|
|
19510
|
+
}
|
|
19511
|
+
return submitManifest(apiKey, endpoint, presigned.uploadId, buildHash, uploadResults);
|
|
19512
|
+
}
|
|
19513
|
+
async function uploadSourceMapsAuto(apiKey, endpoint, buildHash, maps, options) {
|
|
19514
|
+
if (maps.length === 0) {
|
|
19515
|
+
throw new Error("No source maps to upload");
|
|
19516
|
+
}
|
|
19517
|
+
const totalBytes = maps.reduce(
|
|
19518
|
+
(sum, m) => sum + Buffer.byteLength(m.content, "utf-8"),
|
|
19519
|
+
0
|
|
19520
|
+
);
|
|
19521
|
+
if (totalBytes < PRESIGNED_THRESHOLD_BYTES) {
|
|
19522
|
+
return uploadSourceMaps(apiKey, endpoint, buildHash, maps);
|
|
19523
|
+
}
|
|
19524
|
+
const checkAvailable = options?.checkBlobAvailable ?? (async () => {
|
|
19525
|
+
try {
|
|
19526
|
+
await import("@vercel/blob/client");
|
|
19527
|
+
return true;
|
|
19528
|
+
} catch {
|
|
19529
|
+
return false;
|
|
19530
|
+
}
|
|
19531
|
+
});
|
|
19532
|
+
const blobAvailable = await checkAvailable();
|
|
19533
|
+
if (blobAvailable) {
|
|
19534
|
+
return uploadSourceMapsPresigned(
|
|
19535
|
+
apiKey,
|
|
19536
|
+
endpoint,
|
|
19537
|
+
buildHash,
|
|
19538
|
+
maps,
|
|
19539
|
+
options?.blobUploader
|
|
19540
|
+
);
|
|
19541
|
+
}
|
|
19542
|
+
sdkLog(
|
|
19543
|
+
"warn",
|
|
19544
|
+
`[glasstrace] Build exceeds 4.5MB (${totalBytes} bytes). Install @vercel/blob for presigned uploads to avoid serverless body size limits. Falling back to legacy upload.`
|
|
19545
|
+
);
|
|
19546
|
+
return uploadSourceMaps(apiKey, endpoint, buildHash, maps);
|
|
19547
|
+
}
|
|
19311
19548
|
|
|
19312
19549
|
// src/config-wrapper.ts
|
|
19313
19550
|
function withGlasstraceConfig(nextConfig) {
|
|
@@ -19597,6 +19834,7 @@ async function buildImportGraph(projectRoot) {
|
|
|
19597
19834
|
0 && (module.exports = {
|
|
19598
19835
|
GlasstraceExporter,
|
|
19599
19836
|
GlasstraceSpanProcessor,
|
|
19837
|
+
PRESIGNED_THRESHOLD_BYTES,
|
|
19600
19838
|
SdkError,
|
|
19601
19839
|
SessionManager,
|
|
19602
19840
|
buildImportGraph,
|
|
@@ -19624,6 +19862,8 @@ async function buildImportGraph(projectRoot) {
|
|
|
19624
19862
|
saveCachedConfig,
|
|
19625
19863
|
sendInitRequest,
|
|
19626
19864
|
uploadSourceMaps,
|
|
19865
|
+
uploadSourceMapsAuto,
|
|
19866
|
+
uploadSourceMapsPresigned,
|
|
19627
19867
|
withGlasstraceConfig
|
|
19628
19868
|
});
|
|
19629
19869
|
//# sourceMappingURL=index.cjs.map
|