@blotout/qinto-cli 0.1.16 → 0.1.17
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/README.md +13 -2
- package/dist/index.js +4188 -3802
- package/dist/index.js.map +1 -1
- package/dist/worker-artifact/app-runtime/index.js +89 -13
- package/dist/worker-artifact/main/index.js +2906 -1568
- package/dist/worker-artifact/proxy/index.js +22410 -0
- package/dist/worker-artifact/proxy-wfp/index.js +1311 -0
- package/dist/worker-artifact/version.json +40 -4
- package/package.json +6 -6
- package/templates/project/package.json +2 -1
- package/templates/project/tsconfig.json +1 -1
|
@@ -18115,10 +18115,10 @@ var stringbool = (...args) => _stringbool({
|
|
|
18115
18115
|
String: ZodString
|
|
18116
18116
|
}, ...args);
|
|
18117
18117
|
function json(params) {
|
|
18118
|
-
const
|
|
18119
|
-
return union([string2(params), number2(), boolean2(), _null3(), array(
|
|
18118
|
+
const jsonSchema2 = lazy(() => {
|
|
18119
|
+
return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema2), record(string2(), jsonSchema2)]);
|
|
18120
18120
|
});
|
|
18121
|
-
return
|
|
18121
|
+
return jsonSchema2;
|
|
18122
18122
|
}
|
|
18123
18123
|
function preprocess(fn, schema) {
|
|
18124
18124
|
return new ZodPreprocess({
|
|
@@ -18945,6 +18945,7 @@ function date4(params) {
|
|
|
18945
18945
|
var IDENTIFIER = /^[a-z][a-z0-9-]*$/;
|
|
18946
18946
|
var VARIABLE_NAME = /^[A-Z][A-Z0-9_]*$/;
|
|
18947
18947
|
var APP_SLUG_PATTERN = /^[a-z][a-z0-9-]{2,29}$/;
|
|
18948
|
+
var FUNCTION_NAME = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
18948
18949
|
var identifierField = external_exports.string().min(1).max(64).regex(IDENTIFIER);
|
|
18949
18950
|
var httpsUrl = (field2) => {
|
|
18950
18951
|
return external_exports.url().max(2048).refine((value) => value.startsWith("https://"), `${field2} must be an HTTPS URL`);
|
|
@@ -19345,7 +19346,6 @@ var MAX_MANIFEST_MIGRATION_BYTES = 1024 * 1024;
|
|
|
19345
19346
|
var BINDING_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
19346
19347
|
var CLASS_NAME = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
19347
19348
|
var MIGRATION_ID = /^[a-z0-9][a-z0-9-]*$/;
|
|
19348
|
-
var FUNCTION_NAME = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
19349
19349
|
var EVENT_TOPIC = /^[a-z][a-z0-9:_-]*$/;
|
|
19350
19350
|
var QUERY_PARAM_NAME = /^[A-Za-z0-9_.-]+$/;
|
|
19351
19351
|
var COOKIE_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
@@ -19383,6 +19383,7 @@ var PLATFORM_APP_RESOURCE_IDENTIFIERS = {
|
|
|
19383
19383
|
};
|
|
19384
19384
|
var PLATFORM_APP_VARIABLE_IDENTIFIER_PREFIX = "var-";
|
|
19385
19385
|
var PLATFORM_APP_SCOPE_VARIABLE_IDENTIFIER_PREFIX = "appvar-";
|
|
19386
|
+
var STORAGE_LINK_BINDING_PREFIX = "QINTO_LINK_";
|
|
19386
19387
|
var legalUrl = (field2) => {
|
|
19387
19388
|
return httpsUrl(field2).refine((value) => {
|
|
19388
19389
|
const host = new URL(value).hostname;
|
|
@@ -19653,7 +19654,7 @@ var validateBindings = (manifest, ctx) => {
|
|
|
19653
19654
|
"variable name"
|
|
19654
19655
|
);
|
|
19655
19656
|
for (const [index, resource] of manifest.resources.entries()) {
|
|
19656
|
-
if (reserved.has(resource.binding) || resource.binding.startsWith("VAR_") || resource.binding.startsWith("APPVAR_") || resource.binding.startsWith(PLATFORM_APP_OAUTH_BINDING_PREFIX)) {
|
|
19657
|
+
if (reserved.has(resource.binding) || resource.binding.startsWith("VAR_") || resource.binding.startsWith("APPVAR_") || resource.binding.startsWith(PLATFORM_APP_OAUTH_BINDING_PREFIX) || resource.binding.startsWith(STORAGE_LINK_BINDING_PREFIX)) {
|
|
19657
19658
|
ctx.addIssue({ code: "custom", path: ["resources", index, "binding"], message: `Binding ${resource.binding} is reserved` });
|
|
19658
19659
|
}
|
|
19659
19660
|
if (reservedIdentifiers.has(resource.identifier) || resource.identifier.startsWith(PLATFORM_APP_VARIABLE_IDENTIFIER_PREFIX) || resource.identifier.startsWith(PLATFORM_APP_SCOPE_VARIABLE_IDENTIFIER_PREFIX)) {
|
|
@@ -19956,8 +19957,17 @@ var appManifestSchema = baseSchema.superRefine((manifest, ctx) => {
|
|
|
19956
19957
|
var MAX_VENDOR_BODY_BYTES = 64 * 1024;
|
|
19957
19958
|
var MAX_EXPIRES_IN_SECONDS = 365 * 24 * 60 * 60;
|
|
19958
19959
|
|
|
19960
|
+
// ../../../libs/app-manifest/src/rpc-contract.ts
|
|
19961
|
+
var MAX_RPC_CONTRACT_BYTES = 256 * 1024;
|
|
19962
|
+
var jsonSchema = external_exports.record(external_exports.string(), external_exports.unknown());
|
|
19963
|
+
var rpcFunctionContractSchema = external_exports.object({ visibility: external_exports.enum(["public", "private"]), input: jsonSchema, output: jsonSchema }).strict();
|
|
19964
|
+
var appRpcContractSchema = external_exports.record(external_exports.string().regex(FUNCTION_NAME).max(64), rpcFunctionContractSchema).refine((contract) => Object.keys(contract).length <= 32, "An RPC contract carries at most 32 functions").refine((contract) => {
|
|
19965
|
+
return new TextEncoder().encode(JSON.stringify(contract)).length <= MAX_RPC_CONTRACT_BYTES;
|
|
19966
|
+
}, "The RPC contract exceeds the size cap");
|
|
19967
|
+
|
|
19959
19968
|
// ../../../libs/app-envelope/src/envelope.ts
|
|
19960
19969
|
var ENVELOPE_VERSION = 2;
|
|
19970
|
+
var ENVELOPE_ERROR_CODES = ["invalid_arguments"];
|
|
19961
19971
|
var MAX_INSTALLS_PER_APP = 15;
|
|
19962
19972
|
var MAX_EMITS_PER_INSTALL = 10;
|
|
19963
19973
|
var MAX_PUSHES_PER_INSTALL = 10;
|
|
@@ -20056,13 +20066,14 @@ var envelopeResponseSchema = external_exports.object({
|
|
|
20056
20066
|
rpc: external_exports.object({ result: external_exports.unknown() }).strict().refine((rpc) => {
|
|
20057
20067
|
return new TextEncoder().encode(JSON.stringify(rpc.result ?? null)).length <= MAX_RPC_BYTES;
|
|
20058
20068
|
}, "RPC result exceeds the size cap").optional(),
|
|
20059
|
-
error: external_exports.object({ message: external_exports.string().max(2048) }).strict().optional()
|
|
20069
|
+
error: external_exports.object({ message: external_exports.string().max(2048), code: external_exports.enum(ENVELOPE_ERROR_CODES).optional() }).strict().optional()
|
|
20060
20070
|
}).strict();
|
|
20061
20071
|
|
|
20062
20072
|
// ../../../libs/app-envelope/src/control.ts
|
|
20063
20073
|
var CONTROL_ENVELOPE_VERSION = 1;
|
|
20064
20074
|
var MAX_CONTROL_BYTES = 256 * 1024;
|
|
20065
20075
|
var MAX_MIGRATION_CHECKPOINT_BYTES = 16 * 1024;
|
|
20076
|
+
var MIGRATION_DATABASE_LINK_CHANGED = "migration_database_link_changed";
|
|
20066
20077
|
var MAX_TOOL_ARGUMENTS_BYTES = 32 * 1024;
|
|
20067
20078
|
var MAX_TOOL_RESULT_BYTES = 64 * 1024;
|
|
20068
20079
|
var MAX_TOOL_DATA_DEPTH = 8;
|
|
@@ -20868,6 +20879,10 @@ var siteChannel = (env) => {
|
|
|
20868
20879
|
var channelFetch = (env, init) => {
|
|
20869
20880
|
return siteChannel(env).fetch(BROKER_URL, init);
|
|
20870
20881
|
};
|
|
20882
|
+
var brokerFailure = (answer, status) => {
|
|
20883
|
+
const error61 = answer.error ?? `the broker answered ${status}`;
|
|
20884
|
+
return answer.message === void 0 ? error61 : `${error61}: ${answer.message}`;
|
|
20885
|
+
};
|
|
20871
20886
|
var askBroker = async (env, name, body) => {
|
|
20872
20887
|
return traced(name, {}, async () => {
|
|
20873
20888
|
const headers = { "content-type": "application/json" };
|
|
@@ -20891,7 +20906,7 @@ var askBroker = async (env, name, body) => {
|
|
|
20891
20906
|
}
|
|
20892
20907
|
const answer = parsed;
|
|
20893
20908
|
if (answer.error !== void 0 || !response.ok) {
|
|
20894
|
-
throw new Error(answer
|
|
20909
|
+
throw new Error(brokerFailure(answer, response.status));
|
|
20895
20910
|
}
|
|
20896
20911
|
return answer;
|
|
20897
20912
|
});
|
|
@@ -21273,6 +21288,10 @@ var contextKindsOf = (env) => {
|
|
|
21273
21288
|
const context = JSON.parse(env.APP_CONTEXT);
|
|
21274
21289
|
return { variableKinds: context.variableKinds ?? {}, appVariableKinds: context.appVariableKinds ?? {} };
|
|
21275
21290
|
};
|
|
21291
|
+
var linkedDatabasesOf = (env) => {
|
|
21292
|
+
const context = JSON.parse(env.APP_CONTEXT);
|
|
21293
|
+
return context.linkedDatabases ?? [];
|
|
21294
|
+
};
|
|
21276
21295
|
var projectAppValues = (env, kinds) => {
|
|
21277
21296
|
const appVariables = {};
|
|
21278
21297
|
const appSecrets = {};
|
|
@@ -21759,6 +21778,11 @@ var dispatchSchedule = async (envelope, bundle, env) => {
|
|
|
21759
21778
|
data: message.data,
|
|
21760
21779
|
broadcast: message.broadcast
|
|
21761
21780
|
});
|
|
21781
|
+
},
|
|
21782
|
+
context: (userId) => {
|
|
21783
|
+
return asyncContext(env, () => {
|
|
21784
|
+
return userId;
|
|
21785
|
+
});
|
|
21762
21786
|
}
|
|
21763
21787
|
};
|
|
21764
21788
|
try {
|
|
@@ -21998,6 +22022,9 @@ var dispatchLifecycle = async (envelope, bundle, env) => {
|
|
|
21998
22022
|
};
|
|
21999
22023
|
var dispatchMigration = async (envelope, bundle, env) => {
|
|
22000
22024
|
const migration = envelope.migration;
|
|
22025
|
+
if (linkedDatabasesOf(env).includes(migration.resource)) {
|
|
22026
|
+
return json2(200, { v: CONTROL_ENVELOPE_VERSION, ok: false, error: { message: MIGRATION_DATABASE_LINK_CHANGED } });
|
|
22027
|
+
}
|
|
22001
22028
|
try {
|
|
22002
22029
|
if (migration.phase !== "backfill") {
|
|
22003
22030
|
await runStatementMigration(env, migration);
|
|
@@ -22108,8 +22135,8 @@ var buildContext3 = ({
|
|
|
22108
22135
|
geo,
|
|
22109
22136
|
params,
|
|
22110
22137
|
install: { id: install.id, label: install.label },
|
|
22111
|
-
// An endpoint has no visitor, so a workflow it starts cannot push. `push`
|
|
22112
|
-
//
|
|
22138
|
+
// An endpoint has no visitor, so a workflow it starts cannot push or touch context. `push` and
|
|
22139
|
+
// `context` below are the exceptions: they name their subject rather than inheriting one.
|
|
22113
22140
|
startWorkflow: buildStartWorkflow({ ord: install.ord, installId: install.id, installLabel: install.label, anonId: null }),
|
|
22114
22141
|
oauth: buildOauth(env, install.ord),
|
|
22115
22142
|
variables,
|
|
@@ -22128,6 +22155,11 @@ var buildContext3 = ({
|
|
|
22128
22155
|
broadcast: message.broadcast
|
|
22129
22156
|
});
|
|
22130
22157
|
},
|
|
22158
|
+
context: (userId) => {
|
|
22159
|
+
return asyncContext(env, () => {
|
|
22160
|
+
return userId;
|
|
22161
|
+
});
|
|
22162
|
+
},
|
|
22131
22163
|
skip: () => {
|
|
22132
22164
|
return { kind: "skip" };
|
|
22133
22165
|
}
|
|
@@ -22300,6 +22332,42 @@ var withPipelineRetry = (env, bindings) => {
|
|
|
22300
22332
|
return wrapped;
|
|
22301
22333
|
};
|
|
22302
22334
|
|
|
22335
|
+
// src/rpc-definition.ts
|
|
22336
|
+
var isSchema = (candidate) => {
|
|
22337
|
+
return typeof candidate === "object" && candidate !== null && "~standard" in candidate;
|
|
22338
|
+
};
|
|
22339
|
+
var rpcDefinitionOf = (candidate) => {
|
|
22340
|
+
if (typeof candidate !== "object" || candidate === null || !("__qintoRpc" in candidate)) {
|
|
22341
|
+
return void 0;
|
|
22342
|
+
}
|
|
22343
|
+
const marker = candidate.__qintoRpc;
|
|
22344
|
+
if (typeof marker !== "object" || marker === null || !("handler" in marker) || typeof marker.handler !== "function") {
|
|
22345
|
+
return void 0;
|
|
22346
|
+
}
|
|
22347
|
+
const definition = { handler: marker.handler };
|
|
22348
|
+
if ("input" in marker && isSchema(marker.input)) {
|
|
22349
|
+
definition.input = marker.input;
|
|
22350
|
+
}
|
|
22351
|
+
if ("output" in marker && isSchema(marker.output)) {
|
|
22352
|
+
definition.output = marker.output;
|
|
22353
|
+
}
|
|
22354
|
+
return definition;
|
|
22355
|
+
};
|
|
22356
|
+
var checkAgainst = async (schema, value) => {
|
|
22357
|
+
if (schema === void 0) {
|
|
22358
|
+
return { ok: true, value };
|
|
22359
|
+
}
|
|
22360
|
+
const result = await schema["~standard"].validate(value);
|
|
22361
|
+
if (result.issues === void 0) {
|
|
22362
|
+
return { ok: true, value: result.value };
|
|
22363
|
+
}
|
|
22364
|
+
const message = result.issues.map((issue2) => {
|
|
22365
|
+
const path = (issue2.path ?? []).map((segment) => String(typeof segment === "object" ? segment.key : segment)).join(".");
|
|
22366
|
+
return path === "" ? issue2.message : `${path}: ${issue2.message}`;
|
|
22367
|
+
}).join("; ");
|
|
22368
|
+
return { ok: false, message };
|
|
22369
|
+
};
|
|
22370
|
+
|
|
22303
22371
|
// src/traced-fetch.ts
|
|
22304
22372
|
var MAX_BODY_CHARS = 65536;
|
|
22305
22373
|
var TOO_LARGE = `[not recorded: the body is over ${MAX_BODY_CHARS} characters]`;
|
|
@@ -22660,10 +22728,14 @@ var dispatchRpc = async (envelope, bundle, env) => {
|
|
|
22660
22728
|
if (rpc === void 0) {
|
|
22661
22729
|
return jsonError(400, "rpc envelope carries no rpc call");
|
|
22662
22730
|
}
|
|
22663
|
-
const
|
|
22664
|
-
if (
|
|
22731
|
+
const definition = rpcDefinitionOf(bundle?.rpc?.[rpc.fn]);
|
|
22732
|
+
if (definition === void 0) {
|
|
22665
22733
|
return jsonError(200, `missing handler: rpc.${rpc.fn}`);
|
|
22666
22734
|
}
|
|
22735
|
+
const args = await checkAgainst(definition.input, rpc.args);
|
|
22736
|
+
if (!args.ok) {
|
|
22737
|
+
return json2(200, { v: ENVELOPE_VERSION, error: { code: "invalid_arguments", message: failureMessage(args.message) } });
|
|
22738
|
+
}
|
|
22667
22739
|
const install = envelope.installs[0];
|
|
22668
22740
|
const emits = [];
|
|
22669
22741
|
const pushes = [];
|
|
@@ -22686,14 +22758,18 @@ var dispatchRpc = async (envelope, bundle, env) => {
|
|
|
22686
22758
|
let value;
|
|
22687
22759
|
try {
|
|
22688
22760
|
value = await installSpan(install, () => {
|
|
22689
|
-
return handler(
|
|
22761
|
+
return definition.handler(args.value, ctx);
|
|
22690
22762
|
});
|
|
22691
22763
|
} catch (error61) {
|
|
22692
22764
|
const message = failureMessage(error61);
|
|
22693
22765
|
console.warn(`rpc failed for install ${install.id}: ${message}`);
|
|
22694
22766
|
return json2(200, { v: ENVELOPE_VERSION, error: { message } });
|
|
22695
22767
|
}
|
|
22696
|
-
const
|
|
22768
|
+
const checked = await checkAgainst(definition.output, value);
|
|
22769
|
+
if (!checked.ok) {
|
|
22770
|
+
return jsonError(200, failureMessage(`rpc result does not match the output schema: ${checked.message}`));
|
|
22771
|
+
}
|
|
22772
|
+
const result = checked.value === void 0 ? null : checked.value;
|
|
22697
22773
|
if (new TextEncoder().encode(JSON.stringify(result)).length > MAX_RPC_BYTES) {
|
|
22698
22774
|
return jsonError(200, "rpc result exceeds the size cap");
|
|
22699
22775
|
}
|