@blotout/qinto-cli 0.1.7 → 0.1.9
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 +2163 -1416
- package/dist/index.js.map +1 -1
- package/dist/worker-artifact/app-runtime/index.js +388 -38
- package/dist/worker-artifact/main/9026260a7a674b710223f296c5d2e7a01930cfed-q.js.txt +1 -0
- package/dist/worker-artifact/main/index.js +467 -50
- package/dist/worker-artifact/version.json +6 -6
- package/package.json +1 -1
- package/templates/app/full/ui/src/pages/index.astro +0 -2
- package/templates/ui/src/pages/index.astro +1 -2
- package/dist/worker-artifact/main/9dcfd236748459af038da772477100c4bb0223b7-q.js.txt +0 -1
|
@@ -3036,10 +3036,10 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
3036
3036
|
const shape = def.shape;
|
|
3037
3037
|
const propValues = {};
|
|
3038
3038
|
for (const key in shape) {
|
|
3039
|
-
const
|
|
3040
|
-
if (
|
|
3039
|
+
const field2 = shape[key]._zod;
|
|
3040
|
+
if (field2.values) {
|
|
3041
3041
|
propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
|
|
3042
|
-
for (const v of
|
|
3042
|
+
for (const v of field2.values)
|
|
3043
3043
|
propValues[key].add(v);
|
|
3044
3044
|
}
|
|
3045
3045
|
}
|
|
@@ -14692,7 +14692,14 @@ var scheduleSchema = external_exports.object({
|
|
|
14692
14692
|
id: external_exports.string().min(1).max(32),
|
|
14693
14693
|
cron: external_exports.string().min(1).max(MAX_CRON_LENGTH),
|
|
14694
14694
|
scheduledTime: external_exports.number().int().nonnegative().safe(),
|
|
14695
|
-
installs: external_exports.array(
|
|
14695
|
+
installs: external_exports.array(
|
|
14696
|
+
external_exports.object({
|
|
14697
|
+
id: external_exports.string().min(1).max(64),
|
|
14698
|
+
ord: external_exports.number().int().min(1),
|
|
14699
|
+
label: external_exports.string().max(100),
|
|
14700
|
+
catalogQueryTicket: external_exports.string().min(1).max(2048)
|
|
14701
|
+
}).strict()
|
|
14702
|
+
).min(1).max(MAX_INSTALLS_PER_APP)
|
|
14696
14703
|
}).strict();
|
|
14697
14704
|
var controlEnvelopeSchema = external_exports.object({
|
|
14698
14705
|
v: external_exports.literal(CONTROL_ENVELOPE_VERSION),
|
|
@@ -14734,12 +14741,21 @@ var ENDPOINT_CONTEXT_HEADER = "x-qinto-endpoint-context";
|
|
|
14734
14741
|
var ENDPOINT_OUTCOMES_HEADER = "x-qinto-endpoint-outcomes";
|
|
14735
14742
|
var MAX_ENDPOINT_BODY_BYTES = 1024 * 1024;
|
|
14736
14743
|
var MAX_ENDPOINT_OUTCOMES_BYTES = 64 * 1024;
|
|
14744
|
+
var MAX_ENDPOINT_PATH_LENGTH = 16 * 1024;
|
|
14737
14745
|
var installSchema3 = external_exports.object({ id: external_exports.string().min(1).max(64), ord: external_exports.number().int().min(1), label: external_exports.string().max(100) }).strict();
|
|
14738
14746
|
var endpointContextSchema = external_exports.object({
|
|
14739
|
-
path
|
|
14747
|
+
// The declared template, which keys the bundle's handler map; `path` is what the caller asked
|
|
14748
|
+
// for. Only `route` may key the rate limiter — a concrete path gives every parameter value its
|
|
14749
|
+
// own bucket, which is no limit at all.
|
|
14750
|
+
route: external_exports.string().min(1).max(255),
|
|
14751
|
+
path: external_exports.string().min(1).max(MAX_ENDPOINT_PATH_LENGTH),
|
|
14752
|
+
// A name is cut from `route`, so the route's own cap bounds it; anything tighter would reject a
|
|
14753
|
+
// parameter the manifest grammar accepts and the worker already matched.
|
|
14754
|
+
params: external_exports.record(external_exports.string().min(1).max(255), external_exports.string().max(MAX_ENDPOINT_PATH_LENGTH)).default({}),
|
|
14740
14755
|
method: external_exports.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
|
|
14741
14756
|
mode: external_exports.enum(["webhook", "api"]),
|
|
14742
14757
|
version: external_exports.string().min(1).max(32),
|
|
14758
|
+
site: external_exports.object({ origin: external_exports.string().min(1).max(255) }).strict(),
|
|
14743
14759
|
installs: external_exports.array(installSchema3).min(1).max(15)
|
|
14744
14760
|
}).strict().refine((context) => {
|
|
14745
14761
|
return context.mode === "webhook" || context.installs.length === 1;
|
|
@@ -14754,12 +14770,105 @@ var endpointOutcomesSchema = external_exports.object({
|
|
|
14754
14770
|
).max(15)
|
|
14755
14771
|
}).strict();
|
|
14756
14772
|
|
|
14773
|
+
// ../../../libs/app-envelope/src/oauth.ts
|
|
14774
|
+
var APP_OAUTH_BINDING_PREFIX = "OAUTH_";
|
|
14775
|
+
var appOauthBindingName = (providerId, ordinal) => {
|
|
14776
|
+
return `${APP_OAUTH_BINDING_PREFIX}${providerId.toUpperCase().replaceAll("-", "_")}_${ordinal}`;
|
|
14777
|
+
};
|
|
14778
|
+
var parseAppOauthBinding = (raw) => {
|
|
14779
|
+
if (raw === void 0 || raw === "") {
|
|
14780
|
+
return null;
|
|
14781
|
+
}
|
|
14782
|
+
let parsed;
|
|
14783
|
+
try {
|
|
14784
|
+
parsed = JSON.parse(raw);
|
|
14785
|
+
} catch {
|
|
14786
|
+
return null;
|
|
14787
|
+
}
|
|
14788
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
14789
|
+
return null;
|
|
14790
|
+
}
|
|
14791
|
+
const value = parsed;
|
|
14792
|
+
if (value["st"] !== "connected" && value["st"] !== "reconnect_required") {
|
|
14793
|
+
return null;
|
|
14794
|
+
}
|
|
14795
|
+
const expiresAt = value["e"];
|
|
14796
|
+
const token = value["t"];
|
|
14797
|
+
return {
|
|
14798
|
+
...typeof token === "string" && token !== "" ? { t: token } : {},
|
|
14799
|
+
e: typeof expiresAt === "number" ? expiresAt : null,
|
|
14800
|
+
st: value["st"]
|
|
14801
|
+
};
|
|
14802
|
+
};
|
|
14803
|
+
|
|
14804
|
+
// ../../../libs/app-envelope/src/observability.ts
|
|
14805
|
+
var APP_OBSERVABILITY_HEADER = "x-qinto-app-observability";
|
|
14806
|
+
var APP_OBSERVABILITY_VERSION = 1;
|
|
14807
|
+
var MAX_APP_OBSERVABILITY_EVENTS = 20;
|
|
14808
|
+
var MAX_APP_SAVED_ERRORS = 5;
|
|
14809
|
+
var MAX_APP_EVENT_NAME_BYTES = 128;
|
|
14810
|
+
var MAX_APP_ACTION_NAME_BYTES = 256;
|
|
14811
|
+
var MAX_APP_ERROR_DESCRIPTION_BYTES = 2048;
|
|
14812
|
+
var MAX_APP_ERROR_PAYLOAD_BYTES = 4096;
|
|
14813
|
+
var MAX_APP_DATA_POINT_BLOB_BYTES = 16 * 1024;
|
|
14814
|
+
var MAX_APP_OBSERVABILITY_BYTES = 32 * 1024;
|
|
14815
|
+
var APP_OBSERVABILITY_JSON_BUDGET = MAX_APP_OBSERVABILITY_BYTES / 4 * 3;
|
|
14816
|
+
var APP_EVENT_STATUSES = ["success", "error"];
|
|
14817
|
+
var APP_ERROR_CATEGORIES = ["authorization", "configuration", "validation", "rate_limit", "upstream", "internal"];
|
|
14818
|
+
var encoder = new TextEncoder();
|
|
14819
|
+
var decoder = new TextDecoder();
|
|
14820
|
+
var observabilityEventSchema = external_exports.object({ ord: external_exports.number().int().min(1), name: external_exports.string().min(1).max(MAX_APP_EVENT_NAME_BYTES), status: external_exports.enum(APP_EVENT_STATUSES) }).strict();
|
|
14821
|
+
var savedErrorSchema = external_exports.object({
|
|
14822
|
+
ord: external_exports.number().int().min(1),
|
|
14823
|
+
category: external_exports.enum(APP_ERROR_CATEGORIES),
|
|
14824
|
+
action: external_exports.string().min(1).max(MAX_APP_ACTION_NAME_BYTES),
|
|
14825
|
+
description: external_exports.string().min(1).max(MAX_APP_ERROR_DESCRIPTION_BYTES),
|
|
14826
|
+
payload: external_exports.string().max(MAX_APP_ERROR_PAYLOAD_BYTES).optional(),
|
|
14827
|
+
error: external_exports.string().max(MAX_APP_ERROR_PAYLOAD_BYTES).optional()
|
|
14828
|
+
}).strict();
|
|
14829
|
+
var appObservabilityRecordSchema = external_exports.object({
|
|
14830
|
+
v: external_exports.literal(APP_OBSERVABILITY_VERSION),
|
|
14831
|
+
truncated: external_exports.boolean().optional(),
|
|
14832
|
+
events: external_exports.array(observabilityEventSchema).max(MAX_APP_OBSERVABILITY_EVENTS),
|
|
14833
|
+
errors: external_exports.array(savedErrorSchema).max(MAX_APP_SAVED_ERRORS)
|
|
14834
|
+
}).strict();
|
|
14835
|
+
var utf8Length = (value) => {
|
|
14836
|
+
return encoder.encode(value).length;
|
|
14837
|
+
};
|
|
14838
|
+
var truncateUtf8 = (value, maxBytes) => {
|
|
14839
|
+
if (utf8Length(value) <= maxBytes) {
|
|
14840
|
+
return value;
|
|
14841
|
+
}
|
|
14842
|
+
let kept = "";
|
|
14843
|
+
let used = 0;
|
|
14844
|
+
for (const character of value) {
|
|
14845
|
+
const size = utf8Length(character);
|
|
14846
|
+
if (used + size > maxBytes) {
|
|
14847
|
+
break;
|
|
14848
|
+
}
|
|
14849
|
+
kept += character;
|
|
14850
|
+
used += size;
|
|
14851
|
+
}
|
|
14852
|
+
return kept;
|
|
14853
|
+
};
|
|
14854
|
+
var serializeAppObservability = (record2) => {
|
|
14855
|
+
const bytes = encoder.encode(JSON.stringify(record2));
|
|
14856
|
+
let binary = "";
|
|
14857
|
+
for (const byte of bytes) {
|
|
14858
|
+
binary += String.fromCharCode(byte);
|
|
14859
|
+
}
|
|
14860
|
+
return btoa(binary);
|
|
14861
|
+
};
|
|
14862
|
+
|
|
14757
14863
|
// ../../../libs/app-envelope/src/ui.ts
|
|
14758
14864
|
var UI_CONTEXT_HEADER = "x-qinto-ui-context";
|
|
14759
14865
|
var MAX_UI_BODY_BYTES = 1024 * 1024;
|
|
14760
14866
|
var appUiWritePath = (domainId, appSlug2) => {
|
|
14761
14867
|
return `/app-ui/sites/${domainId}/apps/${appSlug2}/install-variables`;
|
|
14762
14868
|
};
|
|
14869
|
+
var appUiCatalogQueryPath = (domainId, appSlug2, resourceIdentifier) => {
|
|
14870
|
+
return `/app-ui/sites/${domainId}/apps/${appSlug2}/catalogs/${resourceIdentifier}/query`;
|
|
14871
|
+
};
|
|
14763
14872
|
var uiInstallSchema = external_exports.object({ id: external_exports.string().min(1).max(64), ord: external_exports.number().int().min(1), label: external_exports.string().max(100), enabled: external_exports.boolean() }).strict();
|
|
14764
14873
|
var uiContextSchema = external_exports.object({
|
|
14765
14874
|
version: external_exports.string().min(1).max(32),
|
|
@@ -14796,10 +14905,10 @@ var formatSpansRecord = (record2) => {
|
|
|
14796
14905
|
};
|
|
14797
14906
|
|
|
14798
14907
|
// ../../../libs/tail-trace/src/app-spans.ts
|
|
14799
|
-
var
|
|
14800
|
-
var
|
|
14908
|
+
var encoder2 = new TextEncoder();
|
|
14909
|
+
var decoder2 = new TextDecoder();
|
|
14801
14910
|
var serializeAppSpans = (record2) => {
|
|
14802
|
-
const bytes =
|
|
14911
|
+
const bytes = encoder2.encode(JSON.stringify(record2));
|
|
14803
14912
|
let binary = "";
|
|
14804
14913
|
for (const byte of bytes) {
|
|
14805
14914
|
binary += String.fromCharCode(byte);
|
|
@@ -14808,12 +14917,12 @@ var serializeAppSpans = (record2) => {
|
|
|
14808
14917
|
};
|
|
14809
14918
|
|
|
14810
14919
|
// ../../../libs/tail-trace/src/budget.ts
|
|
14811
|
-
var
|
|
14920
|
+
var encoder3 = new TextEncoder();
|
|
14812
14921
|
var byteLength = (value) => {
|
|
14813
|
-
return
|
|
14922
|
+
return encoder3.encode(JSON.stringify(value)).length;
|
|
14814
14923
|
};
|
|
14815
14924
|
var fitsBudget = (text, max) => {
|
|
14816
|
-
return text.length * 3 <= max ||
|
|
14925
|
+
return text.length * 3 <= max || encoder3.encode(text).length <= max;
|
|
14817
14926
|
};
|
|
14818
14927
|
var MIN_KEEP = 64;
|
|
14819
14928
|
var halveLongestString = (holders) => {
|
|
@@ -15397,6 +15506,162 @@ var buildAppsClient = (env, envelope) => {
|
|
|
15397
15506
|
};
|
|
15398
15507
|
};
|
|
15399
15508
|
|
|
15509
|
+
// src/oauth.ts
|
|
15510
|
+
var EXPIRY_FLOOR_MS = 1e3;
|
|
15511
|
+
var read = (env, id, ord, now) => {
|
|
15512
|
+
const raw = env[appOauthBindingName(id, ord)];
|
|
15513
|
+
const parsed = parseAppOauthBinding(typeof raw === "string" ? raw : void 0);
|
|
15514
|
+
if (parsed === null) {
|
|
15515
|
+
return null;
|
|
15516
|
+
}
|
|
15517
|
+
const expired = parsed.e !== null && parsed.e - now < EXPIRY_FLOOR_MS;
|
|
15518
|
+
return {
|
|
15519
|
+
id,
|
|
15520
|
+
status: parsed.st === "connected" && !expired ? "connected" : "reconnect_required",
|
|
15521
|
+
expiresAt: parsed.e
|
|
15522
|
+
};
|
|
15523
|
+
};
|
|
15524
|
+
var buildOauth = (env, ord, now = Date.now) => {
|
|
15525
|
+
return {
|
|
15526
|
+
token: (id) => {
|
|
15527
|
+
const raw = env[appOauthBindingName(id, ord)];
|
|
15528
|
+
const parsed = parseAppOauthBinding(typeof raw === "string" ? raw : void 0);
|
|
15529
|
+
if (parsed === null) {
|
|
15530
|
+
throw new Error(`not_connected: this install has no ${id} connection`);
|
|
15531
|
+
}
|
|
15532
|
+
const state = read(env, id, ord, now());
|
|
15533
|
+
if (parsed.t === void 0 || state?.status !== "connected") {
|
|
15534
|
+
throw new Error(`reconnect_required: the ${id} connection has ended and a site manager must reconnect it`);
|
|
15535
|
+
}
|
|
15536
|
+
return parsed.t;
|
|
15537
|
+
},
|
|
15538
|
+
connection: (id) => {
|
|
15539
|
+
return read(env, id, ord, now());
|
|
15540
|
+
}
|
|
15541
|
+
};
|
|
15542
|
+
};
|
|
15543
|
+
var oauthTokenValues = (env) => {
|
|
15544
|
+
const values = /* @__PURE__ */ new Set();
|
|
15545
|
+
for (const [name, raw] of Object.entries(env)) {
|
|
15546
|
+
if (!name.startsWith("OAUTH_") || typeof raw !== "string") {
|
|
15547
|
+
continue;
|
|
15548
|
+
}
|
|
15549
|
+
const token = parseAppOauthBinding(raw)?.t;
|
|
15550
|
+
if (token !== void 0 && token !== "") {
|
|
15551
|
+
values.add(token);
|
|
15552
|
+
}
|
|
15553
|
+
}
|
|
15554
|
+
return [...values];
|
|
15555
|
+
};
|
|
15556
|
+
var buildUiOauth = (env, installs, now = Date.now) => {
|
|
15557
|
+
const ordinalOf = (installId) => {
|
|
15558
|
+
return installs.find((install) => install.id === installId)?.ord ?? null;
|
|
15559
|
+
};
|
|
15560
|
+
return {
|
|
15561
|
+
token: (id, options) => {
|
|
15562
|
+
const ord = ordinalOf(options.installId);
|
|
15563
|
+
if (ord === null) {
|
|
15564
|
+
throw new Error(`not_connected: ${options.installId} is not an install of this app`);
|
|
15565
|
+
}
|
|
15566
|
+
return buildOauth(env, ord, now).token(id);
|
|
15567
|
+
},
|
|
15568
|
+
connection: (id, options) => {
|
|
15569
|
+
const ord = ordinalOf(options.installId);
|
|
15570
|
+
return ord === null ? null : buildOauth(env, ord, now).connection(id);
|
|
15571
|
+
}
|
|
15572
|
+
};
|
|
15573
|
+
};
|
|
15574
|
+
|
|
15575
|
+
// src/observability-collector.ts
|
|
15576
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
15577
|
+
var ENVELOPE_OVERHEAD = 64;
|
|
15578
|
+
var collectors = new AsyncLocalStorage2();
|
|
15579
|
+
var serialized = (value) => {
|
|
15580
|
+
if (value instanceof Error) {
|
|
15581
|
+
const stack = value.stack;
|
|
15582
|
+
return JSON.stringify({ name: value.name, message: value.message, ...stack === void 0 ? {} : { stack } });
|
|
15583
|
+
}
|
|
15584
|
+
let text;
|
|
15585
|
+
try {
|
|
15586
|
+
text = JSON.stringify(value);
|
|
15587
|
+
} catch {
|
|
15588
|
+
return String(value);
|
|
15589
|
+
}
|
|
15590
|
+
return typeof text === "string" ? text : String(value);
|
|
15591
|
+
};
|
|
15592
|
+
var field = (value, redact, maxBytes) => {
|
|
15593
|
+
return truncateUtf8(redact(value), maxBytes);
|
|
15594
|
+
};
|
|
15595
|
+
var optionalField = (value, redact) => {
|
|
15596
|
+
if (value === void 0) {
|
|
15597
|
+
return void 0;
|
|
15598
|
+
}
|
|
15599
|
+
return field(serialized(value), redact, MAX_APP_ERROR_PAYLOAD_BYTES);
|
|
15600
|
+
};
|
|
15601
|
+
var createObservabilityCollector = (redact) => {
|
|
15602
|
+
const events = [];
|
|
15603
|
+
const errors = [];
|
|
15604
|
+
let used = ENVELOPE_OVERHEAD;
|
|
15605
|
+
let truncated = false;
|
|
15606
|
+
const size = (entry) => {
|
|
15607
|
+
return utf8Length(JSON.stringify(entry)) + 1;
|
|
15608
|
+
};
|
|
15609
|
+
return {
|
|
15610
|
+
addEvent: (ord, name, status) => {
|
|
15611
|
+
if (name === "" || !APP_EVENT_STATUSES.includes(status)) {
|
|
15612
|
+
truncated = true;
|
|
15613
|
+
return;
|
|
15614
|
+
}
|
|
15615
|
+
if (events.length >= MAX_APP_OBSERVABILITY_EVENTS) {
|
|
15616
|
+
truncated = true;
|
|
15617
|
+
return;
|
|
15618
|
+
}
|
|
15619
|
+
const entry = { ord, name: field(name, redact, MAX_APP_EVENT_NAME_BYTES), status };
|
|
15620
|
+
used += size(entry);
|
|
15621
|
+
events.push(entry);
|
|
15622
|
+
},
|
|
15623
|
+
addError: (ord, input) => {
|
|
15624
|
+
if (!APP_ERROR_CATEGORIES.includes(input.category) || input.action === "" || input.description === "") {
|
|
15625
|
+
truncated = true;
|
|
15626
|
+
return;
|
|
15627
|
+
}
|
|
15628
|
+
if (errors.length >= MAX_APP_SAVED_ERRORS) {
|
|
15629
|
+
truncated = true;
|
|
15630
|
+
return;
|
|
15631
|
+
}
|
|
15632
|
+
const payload = optionalField(input.payload, redact);
|
|
15633
|
+
const error51 = optionalField(input.error, redact);
|
|
15634
|
+
const entry = {
|
|
15635
|
+
ord,
|
|
15636
|
+
category: input.category,
|
|
15637
|
+
action: field(input.action, redact, MAX_APP_ACTION_NAME_BYTES),
|
|
15638
|
+
description: field(input.description, redact, MAX_APP_ERROR_DESCRIPTION_BYTES),
|
|
15639
|
+
...payload === void 0 ? {} : { payload },
|
|
15640
|
+
...error51 === void 0 ? {} : { error: error51 }
|
|
15641
|
+
};
|
|
15642
|
+
const entrySize = size(entry);
|
|
15643
|
+
if (used + entrySize > APP_OBSERVABILITY_JSON_BUDGET) {
|
|
15644
|
+
truncated = true;
|
|
15645
|
+
return;
|
|
15646
|
+
}
|
|
15647
|
+
used += entrySize;
|
|
15648
|
+
errors.push(entry);
|
|
15649
|
+
},
|
|
15650
|
+
record: () => {
|
|
15651
|
+
if (events.length === 0 && errors.length === 0) {
|
|
15652
|
+
return null;
|
|
15653
|
+
}
|
|
15654
|
+
return { v: APP_OBSERVABILITY_VERSION, ...truncated ? { truncated } : {}, events, errors };
|
|
15655
|
+
}
|
|
15656
|
+
};
|
|
15657
|
+
};
|
|
15658
|
+
var runWithObservability = (collector, run) => {
|
|
15659
|
+
return collectors.run(collector, run);
|
|
15660
|
+
};
|
|
15661
|
+
var currentObservability = () => {
|
|
15662
|
+
return collectors.getStore();
|
|
15663
|
+
};
|
|
15664
|
+
|
|
15400
15665
|
// src/observability.ts
|
|
15401
15666
|
var exceptionAttrs = (error51) => {
|
|
15402
15667
|
const attrs = {
|
|
@@ -15419,7 +15684,7 @@ var consoleText = (error51) => {
|
|
|
15419
15684
|
}
|
|
15420
15685
|
return redactUrlParams(error51 instanceof Error ? error51.stack ?? error51.message : String(error51));
|
|
15421
15686
|
};
|
|
15422
|
-
var buildObservability = () => {
|
|
15687
|
+
var buildObservability = (ord) => {
|
|
15423
15688
|
return {
|
|
15424
15689
|
log: (message, attrs) => {
|
|
15425
15690
|
addSpanEvent(message, attrs === void 0 ? {} : { attrs });
|
|
@@ -15429,6 +15694,21 @@ var buildObservability = () => {
|
|
|
15429
15694
|
addSpanEvent(message, { level: "error", attrs: { ...attrs, ...error51 === void 0 ? {} : exceptionAttrs(error51) } });
|
|
15430
15695
|
console.error(redactUrlParams(message), consoleText(error51), redactAttrs(attrs ?? {}));
|
|
15431
15696
|
},
|
|
15697
|
+
event: (name, status) => {
|
|
15698
|
+
addSpanEvent(name, { attrs: { "app.event.status": status } });
|
|
15699
|
+
if (ord !== null) {
|
|
15700
|
+
currentObservability()?.addEvent(ord, name, status);
|
|
15701
|
+
}
|
|
15702
|
+
},
|
|
15703
|
+
saveError: (input) => {
|
|
15704
|
+
addSpanEvent(input.description, {
|
|
15705
|
+
level: "error",
|
|
15706
|
+
attrs: { "app.error.category": input.category, "app.error.action": input.action }
|
|
15707
|
+
});
|
|
15708
|
+
if (ord !== null) {
|
|
15709
|
+
currentObservability()?.addError(ord, input);
|
|
15710
|
+
}
|
|
15711
|
+
},
|
|
15432
15712
|
span: ((...args) => {
|
|
15433
15713
|
const [name] = args;
|
|
15434
15714
|
const { attrs, run } = spanParts(args);
|
|
@@ -15505,6 +15785,9 @@ var secretValues = (env) => {
|
|
|
15505
15785
|
values.add(value);
|
|
15506
15786
|
}
|
|
15507
15787
|
}
|
|
15788
|
+
for (const value of oauthTokenValues(env)) {
|
|
15789
|
+
values.add(value);
|
|
15790
|
+
}
|
|
15508
15791
|
return [...values];
|
|
15509
15792
|
};
|
|
15510
15793
|
var projectInstallValues = (maps, kinds, ord) => {
|
|
@@ -15581,13 +15864,13 @@ var readOnce = (env, subject) => {
|
|
|
15581
15864
|
};
|
|
15582
15865
|
};
|
|
15583
15866
|
var fetchedContext = (env, subject, collector) => {
|
|
15584
|
-
const
|
|
15867
|
+
const read2 = readOnce(env, () => {
|
|
15585
15868
|
return subject("context.load");
|
|
15586
15869
|
});
|
|
15587
15870
|
return {
|
|
15588
15871
|
private: {
|
|
15589
15872
|
load: async () => {
|
|
15590
|
-
return (await
|
|
15873
|
+
return (await read2()).private;
|
|
15591
15874
|
},
|
|
15592
15875
|
set: (patch) => {
|
|
15593
15876
|
subject("context.set");
|
|
@@ -15596,7 +15879,7 @@ var fetchedContext = (env, subject, collector) => {
|
|
|
15596
15879
|
},
|
|
15597
15880
|
shared: {
|
|
15598
15881
|
load: async () => {
|
|
15599
|
-
return (await
|
|
15882
|
+
return (await read2()).shared;
|
|
15600
15883
|
},
|
|
15601
15884
|
set: (patch) => {
|
|
15602
15885
|
subject("context.set");
|
|
@@ -15606,13 +15889,13 @@ var fetchedContext = (env, subject, collector) => {
|
|
|
15606
15889
|
};
|
|
15607
15890
|
};
|
|
15608
15891
|
var asyncContext = (env, subject) => {
|
|
15609
|
-
const
|
|
15892
|
+
const read2 = readOnce(env, () => {
|
|
15610
15893
|
return subject("context.load");
|
|
15611
15894
|
});
|
|
15612
15895
|
return {
|
|
15613
15896
|
private: {
|
|
15614
15897
|
load: async () => {
|
|
15615
|
-
return (await
|
|
15898
|
+
return (await read2()).private;
|
|
15616
15899
|
},
|
|
15617
15900
|
set: async (patch) => {
|
|
15618
15901
|
assertValidPatch(patch);
|
|
@@ -15624,7 +15907,7 @@ var asyncContext = (env, subject) => {
|
|
|
15624
15907
|
},
|
|
15625
15908
|
shared: {
|
|
15626
15909
|
load: async () => {
|
|
15627
|
-
return (await
|
|
15910
|
+
return (await read2()).shared;
|
|
15628
15911
|
},
|
|
15629
15912
|
set: async (patch) => {
|
|
15630
15913
|
assertValidPatch(patch);
|
|
@@ -15684,12 +15967,13 @@ var buildWorkflowContext = (env, stamp) => {
|
|
|
15684
15967
|
env,
|
|
15685
15968
|
install,
|
|
15686
15969
|
startWorkflow: buildStartWorkflow(stamp),
|
|
15970
|
+
oauth: buildOauth(env, stamp.ord),
|
|
15687
15971
|
variables,
|
|
15688
15972
|
secrets,
|
|
15689
15973
|
appVariables,
|
|
15690
15974
|
appSecrets,
|
|
15691
15975
|
userId: stamp.anonId,
|
|
15692
|
-
observability: buildObservability(),
|
|
15976
|
+
observability: buildObservability(stamp.ord),
|
|
15693
15977
|
context: asyncContext(env, (what) => {
|
|
15694
15978
|
return requireSubject(stamp.anonId, what);
|
|
15695
15979
|
}),
|
|
@@ -15766,6 +16050,7 @@ var buildContext = ({
|
|
|
15766
16050
|
secrets,
|
|
15767
16051
|
appVariables: appScope.appVariables,
|
|
15768
16052
|
appSecrets: appScope.appSecrets,
|
|
16053
|
+
oauth: buildOauth(env, install.ord),
|
|
15769
16054
|
user: envelope.user ?? null,
|
|
15770
16055
|
consent: envelope.consent,
|
|
15771
16056
|
geo: envelope.geo,
|
|
@@ -15820,7 +16105,7 @@ var buildContext = ({
|
|
|
15820
16105
|
}
|
|
15821
16106
|
}
|
|
15822
16107
|
},
|
|
15823
|
-
observability: buildObservability(),
|
|
16108
|
+
observability: buildObservability(install.ord),
|
|
15824
16109
|
apps: buildAppsClient(env, envelope)
|
|
15825
16110
|
};
|
|
15826
16111
|
};
|
|
@@ -15847,6 +16132,48 @@ var failureMessage = (error51) => {
|
|
|
15847
16132
|
return message.slice(0, MAX_ERROR_MESSAGE_LENGTH);
|
|
15848
16133
|
};
|
|
15849
16134
|
|
|
16135
|
+
// src/catalog-query.ts
|
|
16136
|
+
var MAX_CATALOG_RESPONSE_BYTES = 5 * 1024 * 1024;
|
|
16137
|
+
var parseCatalogResponse = async (response) => {
|
|
16138
|
+
const raw = await readBody(response, MAX_CATALOG_RESPONSE_BYTES);
|
|
16139
|
+
if (raw === null) {
|
|
16140
|
+
throw new Error("The catalog query response exceeded the app runtime limit.");
|
|
16141
|
+
}
|
|
16142
|
+
let body;
|
|
16143
|
+
try {
|
|
16144
|
+
body = JSON.parse(raw);
|
|
16145
|
+
} catch {
|
|
16146
|
+
throw new Error(`The catalog query returned an invalid response (${response.status}).`);
|
|
16147
|
+
}
|
|
16148
|
+
if (!response.ok) {
|
|
16149
|
+
const error51 = body;
|
|
16150
|
+
const reason = typeof error51.message === "string" ? error51.message : typeof error51.error === "string" ? error51.error : `request failed with status ${response.status}`;
|
|
16151
|
+
throw new Error(`Catalog query failed: ${reason}`);
|
|
16152
|
+
}
|
|
16153
|
+
return body;
|
|
16154
|
+
};
|
|
16155
|
+
var buildCatalogQuery = ({ env, ticket, installId }) => {
|
|
16156
|
+
return {
|
|
16157
|
+
catalog: async (resourceIdentifier, sql) => {
|
|
16158
|
+
const platform = env;
|
|
16159
|
+
const context = JSON.parse(platform.APP_CONTEXT);
|
|
16160
|
+
const path = appUiCatalogQueryPath(context.domainId, context.slug, resourceIdentifier);
|
|
16161
|
+
return traced(
|
|
16162
|
+
"qinto.catalog.query",
|
|
16163
|
+
{ attrs: { "app.install_id": installId, "app.catalog.resource": resourceIdentifier } },
|
|
16164
|
+
async () => {
|
|
16165
|
+
const response = await fetch(new URL(path, platform.QINTO_PLATFORM_API), {
|
|
16166
|
+
method: "POST",
|
|
16167
|
+
headers: { authorization: `Bearer ${ticket}`, "content-type": "application/json" },
|
|
16168
|
+
body: JSON.stringify({ sql })
|
|
16169
|
+
});
|
|
16170
|
+
return parseCatalogResponse(response);
|
|
16171
|
+
}
|
|
16172
|
+
);
|
|
16173
|
+
}
|
|
16174
|
+
};
|
|
16175
|
+
};
|
|
16176
|
+
|
|
15850
16177
|
// src/schedule.ts
|
|
15851
16178
|
var dispatchSchedule = async (envelope, bundle, env) => {
|
|
15852
16179
|
const schedule = envelope.schedule;
|
|
@@ -15875,12 +16202,14 @@ var dispatchSchedule = async (envelope, bundle, env) => {
|
|
|
15875
16202
|
installLabel: install.label,
|
|
15876
16203
|
anonId: null
|
|
15877
16204
|
}),
|
|
16205
|
+
oauth: buildOauth(env, install.ord),
|
|
15878
16206
|
variables,
|
|
15879
16207
|
secrets,
|
|
15880
16208
|
appVariables: appScope.appVariables,
|
|
15881
16209
|
appSecrets: appScope.appSecrets,
|
|
15882
|
-
observability: buildObservability(),
|
|
16210
|
+
observability: buildObservability(install.ord),
|
|
15883
16211
|
apps: buildAppsClient(env, { depth: 0 }),
|
|
16212
|
+
query: buildCatalogQuery({ env, ticket: install.catalogQueryTicket, installId: install.id }),
|
|
15884
16213
|
push: async (userId, message) => {
|
|
15885
16214
|
await brokerPush(env, {
|
|
15886
16215
|
userId,
|
|
@@ -15940,7 +16269,7 @@ var lifecycleContext = (env, envelope) => {
|
|
|
15940
16269
|
installLabel: install.label,
|
|
15941
16270
|
anonId: null
|
|
15942
16271
|
}),
|
|
15943
|
-
observability: buildObservability()
|
|
16272
|
+
observability: buildObservability(install.ord)
|
|
15944
16273
|
};
|
|
15945
16274
|
};
|
|
15946
16275
|
var migrationContext = (env, envelope) => {
|
|
@@ -15950,7 +16279,9 @@ var migrationContext = (env, envelope) => {
|
|
|
15950
16279
|
site: envelope.site,
|
|
15951
16280
|
appVariables: appScope.appVariables,
|
|
15952
16281
|
appSecrets: appScope.appSecrets,
|
|
15953
|
-
|
|
16282
|
+
// A migration runs once for the site, not once per install, so it has no install to attribute
|
|
16283
|
+
// an event or a saved error to.
|
|
16284
|
+
observability: buildObservability(null)
|
|
15954
16285
|
};
|
|
15955
16286
|
};
|
|
15956
16287
|
var runStatementMigration = async (env, migration) => {
|
|
@@ -16079,19 +16410,22 @@ var handlerRequest = (request, context, body) => {
|
|
|
16079
16410
|
body: body.byteLength === 0 ? void 0 : body
|
|
16080
16411
|
});
|
|
16081
16412
|
};
|
|
16082
|
-
var buildContext2 = ({ env, maps, kinds, appScope, install }) => {
|
|
16413
|
+
var buildContext2 = ({ env, maps, kinds, appScope, install, site, params }) => {
|
|
16083
16414
|
const { variables, secrets } = projectInstallValues(maps, kinds, install.ord);
|
|
16084
16415
|
return {
|
|
16085
16416
|
env,
|
|
16417
|
+
site,
|
|
16418
|
+
params,
|
|
16086
16419
|
install: { id: install.id, label: install.label },
|
|
16087
16420
|
// An endpoint has no visitor, so a workflow it starts cannot push. `push` below is the
|
|
16088
16421
|
// exception: it names its subject rather than inheriting one.
|
|
16089
16422
|
startWorkflow: buildStartWorkflow({ ord: install.ord, installId: install.id, installLabel: install.label, anonId: null }),
|
|
16423
|
+
oauth: buildOauth(env, install.ord),
|
|
16090
16424
|
variables,
|
|
16091
16425
|
secrets,
|
|
16092
16426
|
appVariables: appScope.appVariables,
|
|
16093
16427
|
appSecrets: appScope.appSecrets,
|
|
16094
|
-
observability: buildObservability(),
|
|
16428
|
+
observability: buildObservability(install.ord),
|
|
16095
16429
|
apps: buildAppsClient(env, { depth: 0 }),
|
|
16096
16430
|
push: async (userId, message) => {
|
|
16097
16431
|
await brokerPush(env, {
|
|
@@ -16154,7 +16488,8 @@ var dispatchEndpoint = async ({ request, env, versions }) => {
|
|
|
16154
16488
|
return Response.json({ error: "unknown version" }, { status: 404 });
|
|
16155
16489
|
}
|
|
16156
16490
|
const bundle = versions[context.version];
|
|
16157
|
-
const
|
|
16491
|
+
const endpoints = bundle?.endpoints;
|
|
16492
|
+
const candidate = endpoints !== void 0 && Object.hasOwn(endpoints, context.route) ? endpoints[context.route] : void 0;
|
|
16158
16493
|
if (typeof candidate !== "function") {
|
|
16159
16494
|
return Response.json({ error: "not_found" }, { status: 404 });
|
|
16160
16495
|
}
|
|
@@ -16165,7 +16500,10 @@ var dispatchEndpoint = async ({ request, env, versions }) => {
|
|
|
16165
16500
|
const appScope = projectAppValues(env, appVariableKinds);
|
|
16166
16501
|
const invoke = async (install) => {
|
|
16167
16502
|
return installSpan(install, () => {
|
|
16168
|
-
return handler(
|
|
16503
|
+
return handler(
|
|
16504
|
+
handlerRequest(request, context, body),
|
|
16505
|
+
buildContext2({ env, maps, kinds: variableKinds, appScope, install, site: context.site, params: context.params })
|
|
16506
|
+
);
|
|
16169
16507
|
});
|
|
16170
16508
|
};
|
|
16171
16509
|
const installs = [...context.installs].sort((left, right) => {
|
|
@@ -16188,29 +16526,38 @@ var appSlug = (context) => {
|
|
|
16188
16526
|
return "app";
|
|
16189
16527
|
}
|
|
16190
16528
|
};
|
|
16191
|
-
var withSpans = (response, record2) => {
|
|
16529
|
+
var withSpans = (response, record2, collector) => {
|
|
16192
16530
|
const headers = new Headers(response.headers);
|
|
16193
16531
|
headers.set(APP_SPANS_HEADER, serializeAppSpans(record2));
|
|
16532
|
+
headers.delete(APP_OBSERVABILITY_HEADER);
|
|
16533
|
+
const observability = collector.record();
|
|
16534
|
+
if (observability !== null) {
|
|
16535
|
+
headers.set(APP_OBSERVABILITY_HEADER, serializeAppObservability(observability));
|
|
16536
|
+
}
|
|
16194
16537
|
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
16195
16538
|
};
|
|
16196
16539
|
var runAppInvocation = async (input, handle) => {
|
|
16197
16540
|
let record2 = { spans: [] };
|
|
16541
|
+
const redact = spanRedactor(input.secrets);
|
|
16542
|
+
const collector = createObservabilityCollector(redact);
|
|
16198
16543
|
try {
|
|
16199
16544
|
const response = await runInvocation(
|
|
16200
16545
|
{
|
|
16201
16546
|
name: appSlug(input.context),
|
|
16202
16547
|
trace: parseTraceContext(input.request.headers.get(TRACE_HEADER)),
|
|
16203
16548
|
budget: APP_SPANS_JSON_BUDGET,
|
|
16204
|
-
redact
|
|
16549
|
+
redact,
|
|
16205
16550
|
emit: (emitted) => {
|
|
16206
16551
|
record2 = emitted;
|
|
16207
16552
|
}
|
|
16208
16553
|
},
|
|
16209
|
-
|
|
16554
|
+
() => {
|
|
16555
|
+
return runWithObservability(collector, handle);
|
|
16556
|
+
}
|
|
16210
16557
|
);
|
|
16211
|
-
return withSpans(response, record2);
|
|
16558
|
+
return withSpans(response, record2, collector);
|
|
16212
16559
|
} catch {
|
|
16213
|
-
return withSpans(input.failure(), record2);
|
|
16560
|
+
return withSpans(input.failure(), record2, collector);
|
|
16214
16561
|
}
|
|
16215
16562
|
};
|
|
16216
16563
|
|
|
@@ -16236,21 +16583,21 @@ var capturedBody = async (open) => {
|
|
|
16236
16583
|
return void 0;
|
|
16237
16584
|
}
|
|
16238
16585
|
const reader = body.getReader();
|
|
16239
|
-
const
|
|
16586
|
+
const decoder3 = new TextDecoder();
|
|
16240
16587
|
const expired = new Promise((resolve) => {
|
|
16241
16588
|
timer = setTimeout(() => resolve(null), READ_BUDGET_MS);
|
|
16242
16589
|
});
|
|
16243
16590
|
let text = "";
|
|
16244
16591
|
for (; ; ) {
|
|
16245
|
-
const
|
|
16246
|
-
if (
|
|
16592
|
+
const read2 = await Promise.race([reader.read(), expired]);
|
|
16593
|
+
if (read2 === null) {
|
|
16247
16594
|
abandon(reader);
|
|
16248
16595
|
return INCOMPLETE;
|
|
16249
16596
|
}
|
|
16250
|
-
if (
|
|
16597
|
+
if (read2.done) {
|
|
16251
16598
|
break;
|
|
16252
16599
|
}
|
|
16253
|
-
text +=
|
|
16600
|
+
text += decoder3.decode(read2.value, { stream: true });
|
|
16254
16601
|
if (text.length > MAX_BODY_CHARS) {
|
|
16255
16602
|
abandon(reader);
|
|
16256
16603
|
return TOO_LARGE;
|
|
@@ -16362,6 +16709,9 @@ var dispatchUi = async ({ request, env, versions }) => {
|
|
|
16362
16709
|
env,
|
|
16363
16710
|
install: { id: context.install.id, label: context.install.label },
|
|
16364
16711
|
installs: projectAllInstallValues(maps, variableKinds, context.installs),
|
|
16712
|
+
// The install is named rather than inherited: one panel serves every install, and reading the
|
|
16713
|
+
// subject install's token while showing another account's UI would be silently wrong.
|
|
16714
|
+
oauth: buildUiOauth(env, context.installs),
|
|
16365
16715
|
settings: buildSettings({ env, ticket: context.writeTicket }),
|
|
16366
16716
|
// The panel's viewer is a portal user, not a visitor, so a workflow it starts carries no subject.
|
|
16367
16717
|
startWorkflow: buildUiStartWorkflow(
|
|
@@ -16373,7 +16723,7 @@ var dispatchUi = async ({ request, env, versions }) => {
|
|
|
16373
16723
|
appVariables,
|
|
16374
16724
|
appSecrets,
|
|
16375
16725
|
viewer: context.viewer,
|
|
16376
|
-
observability: buildObservability(),
|
|
16726
|
+
observability: buildObservability(context.install.ord),
|
|
16377
16727
|
apps: buildAppsClient(env, { depth: 0 })
|
|
16378
16728
|
};
|
|
16379
16729
|
let response;
|