@caelo-cms/provisioning 0.11.1 → 0.11.3
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/agent-db.js +458 -62
- package/package.json +2 -2
package/dist/agent-db.js
CHANGED
|
@@ -6509,6 +6509,98 @@ function decodeEscapedLineBreaks(value, language) {
|
|
|
6509
6509
|
${"\t".repeat(tabs.length / 2)}`);
|
|
6510
6510
|
}
|
|
6511
6511
|
|
|
6512
|
+
// ../shared/src/lists/default-types.ts
|
|
6513
|
+
var DEFAULT_LIST_TYPES = [
|
|
6514
|
+
{
|
|
6515
|
+
slug: "texts",
|
|
6516
|
+
name: "Texts",
|
|
6517
|
+
purpose: "A flat list of short texts inside one module: feature bullets, chips, steps.",
|
|
6518
|
+
role: "content",
|
|
6519
|
+
root: { allow: ["text"] },
|
|
6520
|
+
nodes: {
|
|
6521
|
+
text: {
|
|
6522
|
+
label: "Text",
|
|
6523
|
+
fields: [{ name: "text", label: "Text", type: "text", required: true }]
|
|
6524
|
+
}
|
|
6525
|
+
}
|
|
6526
|
+
},
|
|
6527
|
+
{
|
|
6528
|
+
slug: "links",
|
|
6529
|
+
name: "Links",
|
|
6530
|
+
purpose: "A flat group of links: legal links, social links, a footer column.",
|
|
6531
|
+
role: "content",
|
|
6532
|
+
root: { allow: ["link"] },
|
|
6533
|
+
nodes: {
|
|
6534
|
+
link: {
|
|
6535
|
+
label: "Link",
|
|
6536
|
+
fields: [
|
|
6537
|
+
{ name: "label", label: "Label", type: "text", required: true },
|
|
6538
|
+
{ name: "link", label: "Link", type: "link", required: true }
|
|
6539
|
+
],
|
|
6540
|
+
current_from: "link"
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
},
|
|
6544
|
+
{
|
|
6545
|
+
slug: "menu",
|
|
6546
|
+
name: "Menu",
|
|
6547
|
+
purpose: "Site navigation with up to three levels: header menu, footer menu, mobile menu. Use a custom type for mega menus with columns or teasers.",
|
|
6548
|
+
role: "navigation",
|
|
6549
|
+
root: { allow: ["entry"] },
|
|
6550
|
+
nodes: {
|
|
6551
|
+
entry: {
|
|
6552
|
+
label: "Menu entry",
|
|
6553
|
+
fields: [
|
|
6554
|
+
{ name: "label", label: "Label", type: "text", required: true },
|
|
6555
|
+
{ name: "link", label: "Link", type: "link" }
|
|
6556
|
+
],
|
|
6557
|
+
children: { name: "children", allow: ["entry"] },
|
|
6558
|
+
current_from: "link"
|
|
6559
|
+
}
|
|
6560
|
+
},
|
|
6561
|
+
max_depth: 3
|
|
6562
|
+
},
|
|
6563
|
+
{
|
|
6564
|
+
slug: "categories",
|
|
6565
|
+
name: "Categories",
|
|
6566
|
+
purpose: "A category tree pages are assigned to: blog sections, product groups, doc areas.",
|
|
6567
|
+
role: "vocabulary",
|
|
6568
|
+
root: { allow: ["category"] },
|
|
6569
|
+
nodes: {
|
|
6570
|
+
category: {
|
|
6571
|
+
label: "Category",
|
|
6572
|
+
fields: [
|
|
6573
|
+
{ name: "name", label: "Name", type: "text", required: true },
|
|
6574
|
+
{ name: "slug", label: "Slug", type: "text", required: true },
|
|
6575
|
+
{ name: "description", label: "Description", type: "richtext" },
|
|
6576
|
+
{ name: "landing_page", label: "Landing page", type: "link" }
|
|
6577
|
+
],
|
|
6578
|
+
children: { name: "children", allow: ["category"] },
|
|
6579
|
+
current_from: "landing_page"
|
|
6580
|
+
}
|
|
6581
|
+
},
|
|
6582
|
+
max_depth: 6
|
|
6583
|
+
},
|
|
6584
|
+
{
|
|
6585
|
+
slug: "tags",
|
|
6586
|
+
name: "Tags",
|
|
6587
|
+
purpose: "Flat keywords pages are tagged with, for filters, tag clouds and related content.",
|
|
6588
|
+
role: "vocabulary",
|
|
6589
|
+
root: { allow: ["tag"] },
|
|
6590
|
+
nodes: {
|
|
6591
|
+
tag: {
|
|
6592
|
+
label: "Tag",
|
|
6593
|
+
fields: [
|
|
6594
|
+
{ name: "name", label: "Name", type: "text", required: true },
|
|
6595
|
+
{ name: "slug", label: "Slug", type: "text", required: true },
|
|
6596
|
+
{ name: "color", label: "Color", type: "text", maxLength: 9 }
|
|
6597
|
+
]
|
|
6598
|
+
}
|
|
6599
|
+
}
|
|
6600
|
+
}
|
|
6601
|
+
];
|
|
6602
|
+
var SITE_TEXTS_LIST_TYPE = "site-texts";
|
|
6603
|
+
|
|
6512
6604
|
// ../shared/src/lists/fields.ts
|
|
6513
6605
|
var LIST_RESERVED_NAMES = new Set([
|
|
6514
6606
|
"id",
|
|
@@ -6769,11 +6861,14 @@ var moduleFieldModuleListSchema = object({
|
|
|
6769
6861
|
min: number2().int().nonnegative().optional(),
|
|
6770
6862
|
max: number2().int().positive().max(256).optional()
|
|
6771
6863
|
}).strict();
|
|
6864
|
+
var SHIPPED_LIST_TYPE_SLUGS = [...DEFAULT_LIST_TYPES.map((t) => t.slug), SITE_TEXTS_LIST_TYPE].map((slug) => `"${slug}"`).join(", ");
|
|
6772
6865
|
var moduleFieldListSchema = object({
|
|
6773
6866
|
name: moduleFieldName,
|
|
6774
6867
|
kind: literal("list"),
|
|
6775
6868
|
label: moduleFieldLabel,
|
|
6776
|
-
listType:
|
|
6869
|
+
listType: string2({
|
|
6870
|
+
error: (iss) => iss.input === undefined ? `a list field needs listType: ${SHIPPED_LIST_TYPE_SLUGS} or a custom type's slug (list_list_types shows them)` : undefined
|
|
6871
|
+
}).regex(/^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/, "slug must be lowercase letters, digits, or hyphens (1\u201364 chars, no leading/trailing hyphen)"),
|
|
6777
6872
|
bind: _enum(["local", "shared", "source"]).optional(),
|
|
6778
6873
|
list: string2().regex(LIST_REF_RE, "list must be caelo:list/<id>").optional(),
|
|
6779
6874
|
source: sourceDefSchema.optional(),
|
|
@@ -6968,8 +7063,9 @@ var pageSetModulesSchema = object({
|
|
|
6968
7063
|
expectedVersion: number2().int().nonnegative().optional(),
|
|
6969
7064
|
blocks: array(object({
|
|
6970
7065
|
blockName: slugSchema,
|
|
6971
|
-
moduleIds: array(string2().uuid())
|
|
6972
|
-
|
|
7066
|
+
moduleIds: array(string2().uuid()),
|
|
7067
|
+
contentInstanceIds: array(string2().uuid().nullable()).optional()
|
|
7068
|
+
}).strict().refine((b) => b.contentInstanceIds === undefined || b.contentInstanceIds.length === b.moduleIds.length, { message: "contentInstanceIds needs one entry (or null) per moduleIds entry" }))
|
|
6973
7069
|
}).strict();
|
|
6974
7070
|
var syncModeSchema = _enum(["synced", "unsynced"]);
|
|
6975
7071
|
var contentValuesSchema = record(string2(), unknown());
|
|
@@ -7382,6 +7478,8 @@ var movePositionInputSchema = preprocess(stripSurroundingQuotes, union([
|
|
|
7382
7478
|
var moveModuleToolInput = object({
|
|
7383
7479
|
pageId: string2().uuid(),
|
|
7384
7480
|
moduleId: string2().uuid(),
|
|
7481
|
+
fromBlockName: string2().min(1).max(80).optional(),
|
|
7482
|
+
fromPosition: preprocess((v) => typeof v === "string" && /^\d+$/.test(v) ? Number.parseInt(v, 10) : v, number2().int().min(0).max(1000).optional()),
|
|
7385
7483
|
toBlockName: string2().min(1).max(80).optional(),
|
|
7386
7484
|
position: movePositionInputSchema
|
|
7387
7485
|
}).strict();
|
|
@@ -7588,20 +7686,42 @@ var bugIntakeRegisterRequest = object({
|
|
|
7588
7686
|
publicKey: string2().regex(/^[A-Za-z0-9+/]{43}=$/, "publicKey must be a base64 Ed25519 key"),
|
|
7589
7687
|
caeloVersion: string2().min(1).max(64)
|
|
7590
7688
|
}).strict();
|
|
7689
|
+
var bugReportKind = _enum(["defect", "suggestion"]);
|
|
7690
|
+
var BUG_REPORT_KIND_BEFORE_1192 = "defect";
|
|
7691
|
+
var bugReportSeverity = _enum(["blocking", "degraded", "cosmetic"]);
|
|
7591
7692
|
var bugIntakeReport = object({
|
|
7592
7693
|
protocolVersion: literal(BUG_INTAKE_PROTOCOL_VERSION),
|
|
7593
7694
|
reportId: string2().uuid(),
|
|
7594
7695
|
caeloVersion: string2().min(1).max(64),
|
|
7595
7696
|
fingerprint: fingerprintSchema,
|
|
7596
7697
|
source: _enum(["ai", "auto"]),
|
|
7597
|
-
|
|
7698
|
+
kind: bugReportKind.default(BUG_REPORT_KIND_BEFORE_1192),
|
|
7699
|
+
severity: bugReportSeverity.nullable(),
|
|
7598
7700
|
blockedTask: boolean2(),
|
|
7599
7701
|
suspectedTool: string2().max(200).nullable(),
|
|
7600
7702
|
title: string2().min(1).max(BUG_INTAKE_LIMITS.title),
|
|
7601
7703
|
whatHappened: string2().min(1).max(BUG_INTAKE_LIMITS.whatHappened),
|
|
7602
7704
|
expected: string2().min(1).max(BUG_INTAKE_LIMITS.expected),
|
|
7603
7705
|
evidence: string2().max(BUG_INTAKE_LIMITS.evidence).nullable()
|
|
7604
|
-
}).strict()
|
|
7706
|
+
}).strict().superRefine((r, ctx) => {
|
|
7707
|
+
if (r.kind === "defect" && r.severity === null) {
|
|
7708
|
+
ctx.addIssue({ code: "custom", path: ["severity"], message: "a defect needs a severity" });
|
|
7709
|
+
}
|
|
7710
|
+
if (r.kind === "suggestion" && r.severity !== null) {
|
|
7711
|
+
ctx.addIssue({
|
|
7712
|
+
code: "custom",
|
|
7713
|
+
path: ["severity"],
|
|
7714
|
+
message: "a suggestion has no severity; send null"
|
|
7715
|
+
});
|
|
7716
|
+
}
|
|
7717
|
+
if (r.kind === "suggestion" && r.source === "auto") {
|
|
7718
|
+
ctx.addIssue({
|
|
7719
|
+
code: "custom",
|
|
7720
|
+
path: ["kind"],
|
|
7721
|
+
message: "an auto-captured report is always a defect"
|
|
7722
|
+
});
|
|
7723
|
+
}
|
|
7724
|
+
});
|
|
7605
7725
|
var bugClusterStatus = _enum(["open", "fixed", "regression", "wontfix"]);
|
|
7606
7726
|
var bugIntakeClusterInfo = object({
|
|
7607
7727
|
clusterId: string2().min(1).max(100),
|
|
@@ -7758,7 +7878,7 @@ var buildPageTargetSchema = object({
|
|
|
7758
7878
|
if (createKeys.length > 0) {
|
|
7759
7879
|
ctx.addIssue({
|
|
7760
7880
|
code: ZodIssueCode.custom,
|
|
7761
|
-
message: `pageId targets an EXISTING page \u2014 drop ${createKeys.join(", ")}. ` + "To create a new page instead, omit pageId and pass slug + title."
|
|
7881
|
+
message: `pageId targets an EXISTING page \u2014 drop ${createKeys.join(", ")}. ` + (createKeys.includes("status") ? "`status` only applies to a page this call creates; publish an existing page with set_pages_status_many. " : "") + "To create a new page instead, omit pageId and pass slug + title."
|
|
7762
7882
|
});
|
|
7763
7883
|
}
|
|
7764
7884
|
return;
|
|
@@ -8926,6 +9046,16 @@ var PAGE_PROP_RE = new RegExp(`^page/(${SEG2})/props/(${SEG2})$`);
|
|
|
8926
9046
|
var LIST_HIDDEN_RE = new RegExp(`^list/(${SEG2})/item/(${SEG2})$`);
|
|
8927
9047
|
var INSTANCE_HIDDEN_RE = new RegExp(`^instance/(${SEG2})/(${SEG2})/item/(${SEG2})$`);
|
|
8928
9048
|
var STRUCTURAL_TYPES = new Set(["module", "term"]);
|
|
9049
|
+
// ../shared/src/live-events.ts
|
|
9050
|
+
var LIVE_TOPICS = [
|
|
9051
|
+
"agents",
|
|
9052
|
+
"pending",
|
|
9053
|
+
"credentials",
|
|
9054
|
+
"quality",
|
|
9055
|
+
"crawl",
|
|
9056
|
+
"deploys"
|
|
9057
|
+
];
|
|
9058
|
+
var TOPIC_SET = new Set(LIVE_TOPICS);
|
|
8929
9059
|
// ../shared/src/markup-structure.ts
|
|
8930
9060
|
var LEAF_TAGS = new Set(["svg", "math", "script", "style", "noscript", "iframe"]);
|
|
8931
9061
|
// ../shared/src/page-log.ts
|
|
@@ -18539,6 +18669,40 @@ function isRlsDenial(error) {
|
|
|
18539
18669
|
return false;
|
|
18540
18670
|
}
|
|
18541
18671
|
|
|
18672
|
+
// ../query-api/src/operation.ts
|
|
18673
|
+
import { appendFileSync, mkdirSync } from "fs";
|
|
18674
|
+
import { dirname } from "path";
|
|
18675
|
+
function isReadOperation(op) {
|
|
18676
|
+
return "kind" in op && op.kind === "reads";
|
|
18677
|
+
}
|
|
18678
|
+
var OP_COVERAGE_FILE_DEFAULT = "coverage/op-coverage.jsonl";
|
|
18679
|
+
var recordedNames = new Set;
|
|
18680
|
+
var coverageDirEnsured = false;
|
|
18681
|
+
function recordOpInvocation(name) {
|
|
18682
|
+
if (recordedNames.has(name))
|
|
18683
|
+
return;
|
|
18684
|
+
recordedNames.add(name);
|
|
18685
|
+
const file = process.env.CAELO_OP_COVERAGE_FILE ?? OP_COVERAGE_FILE_DEFAULT;
|
|
18686
|
+
if (!coverageDirEnsured) {
|
|
18687
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
18688
|
+
coverageDirEnsured = true;
|
|
18689
|
+
}
|
|
18690
|
+
appendFileSync(file, `${name}
|
|
18691
|
+
`, { flag: "a" });
|
|
18692
|
+
}
|
|
18693
|
+
function defineOperation(def) {
|
|
18694
|
+
if (process.env.CAELO_OP_COVERAGE !== "1")
|
|
18695
|
+
return def;
|
|
18696
|
+
const original = def.handler;
|
|
18697
|
+
return {
|
|
18698
|
+
...def,
|
|
18699
|
+
handler: (ctx, input, tx) => {
|
|
18700
|
+
recordOpInvocation(def.name);
|
|
18701
|
+
return original(ctx, input, tx);
|
|
18702
|
+
}
|
|
18703
|
+
};
|
|
18704
|
+
}
|
|
18705
|
+
|
|
18542
18706
|
// ../query-api/src/plugin-schema-provision.ts
|
|
18543
18707
|
import { createHash } from "crypto";
|
|
18544
18708
|
var DROPPED_COLUMNS_SETTING = "caelo.plugin_dropped_columns";
|
|
@@ -18577,6 +18741,119 @@ async function provisionPluginSchemaInTx(tx, caller, opts) {
|
|
|
18577
18741
|
};
|
|
18578
18742
|
}
|
|
18579
18743
|
|
|
18744
|
+
// ../query-api/src/pool-guard.ts
|
|
18745
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
18746
|
+
var POOL_ACQUIRE_TIMEOUT_MS = 1e4;
|
|
18747
|
+
var ALLOWLIST = [
|
|
18748
|
+
{ holder: "deploy.promote", issue: 1225, nestedCheckouts: true, noSessionTimeouts: true },
|
|
18749
|
+
{
|
|
18750
|
+
holder: "quality_audits.publish_anyway",
|
|
18751
|
+
issue: 1225,
|
|
18752
|
+
nestedCheckouts: true,
|
|
18753
|
+
noSessionTimeouts: true
|
|
18754
|
+
},
|
|
18755
|
+
{
|
|
18756
|
+
holder: "quality_audits.execute_proposal",
|
|
18757
|
+
issue: 1225,
|
|
18758
|
+
nestedCheckouts: true,
|
|
18759
|
+
noSessionTimeouts: true
|
|
18760
|
+
},
|
|
18761
|
+
{
|
|
18762
|
+
holder: "deploy.execute_proposal",
|
|
18763
|
+
issue: 1225,
|
|
18764
|
+
nestedCheckouts: true,
|
|
18765
|
+
noSessionTimeouts: true
|
|
18766
|
+
},
|
|
18767
|
+
{
|
|
18768
|
+
holder: "deploy.build_plugin_data",
|
|
18769
|
+
issue: 1220,
|
|
18770
|
+
nestedCheckouts: true,
|
|
18771
|
+
noSessionTimeouts: true
|
|
18772
|
+
},
|
|
18773
|
+
{
|
|
18774
|
+
holder: "plugins.activation_lock",
|
|
18775
|
+
issue: 1220,
|
|
18776
|
+
nestedCheckouts: true,
|
|
18777
|
+
noSessionTimeouts: false
|
|
18778
|
+
},
|
|
18779
|
+
{ holder: "static-generator.build", issue: 1220, nestedCheckouts: true, noSessionTimeouts: true },
|
|
18780
|
+
{ holder: "plugins.render_hook", issue: 1220, nestedCheckouts: true, noSessionTimeouts: false }
|
|
18781
|
+
];
|
|
18782
|
+
var NESTED_CHECKOUT_ALLOWLIST = new Map(ALLOWLIST.map((entry) => [entry.holder, entry]));
|
|
18783
|
+
|
|
18784
|
+
class NestedPoolCheckoutError extends Error {
|
|
18785
|
+
pool;
|
|
18786
|
+
holder;
|
|
18787
|
+
requester;
|
|
18788
|
+
name = "NestedPoolCheckoutError";
|
|
18789
|
+
constructor(pool, holder, requester) {
|
|
18790
|
+
super(`${requester} asked the ${pool} database pool for a second connection while ${holder} holds a transaction of that pool in the same call chain. ` + "Enough of these at once deadlock the whole pool (issue #1210), so it is refused. Nothing of this call ran. " + `Fix in the code: pass ${holder}'s transaction to the inner work (op.handler(ctx, input, tx)) or move the inner work out of the transaction (transaction: "none").`);
|
|
18791
|
+
this.pool = pool;
|
|
18792
|
+
this.holder = holder;
|
|
18793
|
+
this.requester = requester;
|
|
18794
|
+
}
|
|
18795
|
+
}
|
|
18796
|
+
|
|
18797
|
+
class PoolAcquireTimeoutError extends Error {
|
|
18798
|
+
pool;
|
|
18799
|
+
requester;
|
|
18800
|
+
timeoutMs;
|
|
18801
|
+
name = "PoolAcquireTimeoutError";
|
|
18802
|
+
constructor(pool, requester, timeoutMs) {
|
|
18803
|
+
super(`the ${pool} database pool had no free connection for ${requester} within ${timeoutMs} ms: every connection is busy. ` + "Nothing was changed. Retry in a few seconds; if it keeps happening the admin is overloaded or a request holds its connections \u2014 the server log names it.");
|
|
18804
|
+
this.pool = pool;
|
|
18805
|
+
this.requester = requester;
|
|
18806
|
+
this.timeoutMs = timeoutMs;
|
|
18807
|
+
}
|
|
18808
|
+
}
|
|
18809
|
+
var allowances = new AsyncLocalStorage;
|
|
18810
|
+
class PoolGuard {
|
|
18811
|
+
#stores = {
|
|
18812
|
+
admin: new AsyncLocalStorage,
|
|
18813
|
+
public: new AsyncLocalStorage
|
|
18814
|
+
};
|
|
18815
|
+
enter(pool, holder) {
|
|
18816
|
+
const allowedBy = this.assertMayCheckout(pool, holder);
|
|
18817
|
+
return { holder, active: true, allowedBy };
|
|
18818
|
+
}
|
|
18819
|
+
assertMayCheckout(pool, requester) {
|
|
18820
|
+
const outer = this.#stores[pool].getStore();
|
|
18821
|
+
if (outer === undefined || !outer.active)
|
|
18822
|
+
return null;
|
|
18823
|
+
const allowedBy = outer.allowedBy ?? (NESTED_CHECKOUT_ALLOWLIST.get(outer.holder)?.nestedCheckouts ? outer.holder : null) ?? allowances.getStore() ?? null;
|
|
18824
|
+
if (allowedBy === null)
|
|
18825
|
+
throw new NestedPoolCheckoutError(pool, outer.holder, requester);
|
|
18826
|
+
return allowedBy;
|
|
18827
|
+
}
|
|
18828
|
+
async run(pool, marker, fn) {
|
|
18829
|
+
try {
|
|
18830
|
+
return await this.#stores[pool].run(marker, fn);
|
|
18831
|
+
} finally {
|
|
18832
|
+
marker.active = false;
|
|
18833
|
+
}
|
|
18834
|
+
}
|
|
18835
|
+
}
|
|
18836
|
+
function exemptFromSessionTimeouts(holder) {
|
|
18837
|
+
return NESTED_CHECKOUT_ALLOWLIST.get(holder)?.noSessionTimeouts === true;
|
|
18838
|
+
}
|
|
18839
|
+
async function liftSessionTimeouts(tx) {
|
|
18840
|
+
await tx.execute(sql`SELECT set_config('statement_timeout', '0', true)`);
|
|
18841
|
+
await tx.execute(sql`SELECT set_config('lock_timeout', '0', true)`);
|
|
18842
|
+
await tx.execute(sql`SELECT set_config('idle_in_transaction_session_timeout', '0', true)`);
|
|
18843
|
+
}
|
|
18844
|
+
function detachedRunner(operation, open) {
|
|
18845
|
+
const transaction = (fn) => open(fn);
|
|
18846
|
+
return new Proxy({}, {
|
|
18847
|
+
get(_target, property) {
|
|
18848
|
+
if (property === "transaction")
|
|
18849
|
+
return transaction;
|
|
18850
|
+
if (property === "then")
|
|
18851
|
+
return;
|
|
18852
|
+
throw new Error(`${operation} is a detached operation (transaction: "none") and holds no transaction; it used tx.${String(property)}. Wrap the step in tx.transaction(async (t) => \u2026) or run it as its own operation.`);
|
|
18853
|
+
}
|
|
18854
|
+
});
|
|
18855
|
+
}
|
|
18856
|
+
|
|
18580
18857
|
// ../query-api/src/post-commit.ts
|
|
18581
18858
|
var pendingByTx = new WeakMap;
|
|
18582
18859
|
function collectPostCommitEffects(tx) {
|
|
@@ -18598,6 +18875,16 @@ async function runPostCommitEffects(effects) {
|
|
|
18598
18875
|
}
|
|
18599
18876
|
return failures;
|
|
18600
18877
|
}
|
|
18878
|
+
var committedListeners = new Set;
|
|
18879
|
+
function notifyOperationCommitted(operationName) {
|
|
18880
|
+
for (const listener of committedListeners) {
|
|
18881
|
+
try {
|
|
18882
|
+
listener(operationName);
|
|
18883
|
+
} catch (thrown) {
|
|
18884
|
+
console.error(`[query-api] committed-operation listener failed for ${operationName}`, thrown);
|
|
18885
|
+
}
|
|
18886
|
+
}
|
|
18887
|
+
}
|
|
18601
18888
|
|
|
18602
18889
|
// ../query-api/src/adapter.ts
|
|
18603
18890
|
var SQL3 = globalThis.Bun?.SQL;
|
|
@@ -18674,8 +18961,12 @@ class DatabaseAdapter {
|
|
|
18674
18961
|
#publicRaw;
|
|
18675
18962
|
#skipVerify;
|
|
18676
18963
|
#roles;
|
|
18964
|
+
#acquireTimeoutMs;
|
|
18965
|
+
#guard = new PoolGuard;
|
|
18677
18966
|
#verifyPromise = null;
|
|
18678
18967
|
#projectionPublisher = null;
|
|
18968
|
+
#onStatement;
|
|
18969
|
+
#drizzleOptions;
|
|
18679
18970
|
constructor(config) {
|
|
18680
18971
|
this.#roles = config.expectedRoles ?? DEFAULT_ROLES;
|
|
18681
18972
|
if (config.adminDatabaseUrl === null !== (this.#roles.admin === null)) {
|
|
@@ -18687,9 +18978,47 @@ class DatabaseAdapter {
|
|
|
18687
18978
|
const open = (url) => new SQL3(url, poolMax === undefined ? { idleTimeout } : { max: poolMax, idleTimeout });
|
|
18688
18979
|
this.#adminRaw = config.adminDatabaseUrl === null ? null : open(config.adminDatabaseUrl);
|
|
18689
18980
|
this.#publicRaw = open(config.publicDatabaseUrl);
|
|
18690
|
-
this.#
|
|
18691
|
-
|
|
18981
|
+
this.#onStatement = config.onStatement ?? null;
|
|
18982
|
+
const observe = this.#onStatement;
|
|
18983
|
+
this.#drizzleOptions = observe ? { logger: { logQuery: (query) => observe(query) } } : {};
|
|
18984
|
+
this.#admin = this.#adminRaw === null ? null : drizzle(this.#adminRaw, this.#drizzleOptions);
|
|
18985
|
+
this.#public = drizzle(this.#publicRaw, this.#drizzleOptions);
|
|
18692
18986
|
this.#skipVerify = config.skipRoleVerification === true;
|
|
18987
|
+
this.#acquireTimeoutMs = config.poolAcquireTimeoutMs ?? POOL_ACQUIRE_TIMEOUT_MS;
|
|
18988
|
+
}
|
|
18989
|
+
async#transaction(pool, holder, fn) {
|
|
18990
|
+
const raw = pool === "admin" ? this.#adminRaw : this.#publicRaw;
|
|
18991
|
+
if (raw === null)
|
|
18992
|
+
throw new AdminDatabaseUnavailableError(holder);
|
|
18993
|
+
const marker = this.#guard.enter(pool, holder);
|
|
18994
|
+
const reserved = await this.#reserve(pool, raw, holder);
|
|
18995
|
+
try {
|
|
18996
|
+
const db = drizzle({ client: reserved, ...this.#drizzleOptions });
|
|
18997
|
+
this.#onStatement?.("BEGIN");
|
|
18998
|
+
const out = await db.transaction((tx) => this.#guard.run(pool, marker, async () => {
|
|
18999
|
+
if (exemptFromSessionTimeouts(holder))
|
|
19000
|
+
await liftSessionTimeouts(tx);
|
|
19001
|
+
return fn(tx);
|
|
19002
|
+
}));
|
|
19003
|
+
this.#onStatement?.("COMMIT");
|
|
19004
|
+
return out;
|
|
19005
|
+
} finally {
|
|
19006
|
+
reserved.release();
|
|
19007
|
+
}
|
|
19008
|
+
}
|
|
19009
|
+
async#reserve(pool, raw, requester) {
|
|
19010
|
+
const deadline = new AbortController;
|
|
19011
|
+
const timer = setTimeout(() => deadline.abort(), this.#acquireTimeoutMs);
|
|
19012
|
+
try {
|
|
19013
|
+
return await raw.reserve({ signal: deadline.signal });
|
|
19014
|
+
} catch (e) {
|
|
19015
|
+
if (deadline.signal.aborted) {
|
|
19016
|
+
throw new PoolAcquireTimeoutError(pool, requester, this.#acquireTimeoutMs);
|
|
19017
|
+
}
|
|
19018
|
+
throw e;
|
|
19019
|
+
} finally {
|
|
19020
|
+
clearTimeout(timer);
|
|
19021
|
+
}
|
|
18693
19022
|
}
|
|
18694
19023
|
get hasAdminDatabase() {
|
|
18695
19024
|
return this.#admin !== null;
|
|
@@ -18777,15 +19106,22 @@ class DatabaseAdapter {
|
|
|
18777
19106
|
return row;
|
|
18778
19107
|
}
|
|
18779
19108
|
async runOperation(op, ctx, validatedInput) {
|
|
19109
|
+
const pool = op.database === "cms_admin" ? "admin" : "public";
|
|
19110
|
+
this.#guard.assertMayCheckout(pool, op.name);
|
|
19111
|
+
if (op.database === "cms_admin")
|
|
19112
|
+
this.#adminDb(`operation ${op.name}`);
|
|
18780
19113
|
if (!this.#skipVerify)
|
|
18781
19114
|
await this.verifyRoles();
|
|
18782
|
-
|
|
19115
|
+
if (isReadOperation(op))
|
|
19116
|
+
return this.#runReadOperation(op, ctx, validatedInput);
|
|
19117
|
+
if (op.transaction === "none")
|
|
19118
|
+
return this.#runDetached(op, ctx, validatedInput);
|
|
18783
19119
|
let publishAfterCommit = false;
|
|
18784
19120
|
let postCommit = [];
|
|
18785
19121
|
let result;
|
|
18786
19122
|
let handlerError = null;
|
|
18787
19123
|
try {
|
|
18788
|
-
result = await
|
|
19124
|
+
result = await this.#transaction(pool, op.name, async (tx) => {
|
|
18789
19125
|
postCommit = collectPostCommitEffects(tx);
|
|
18790
19126
|
await this.#setIdentity(tx, ctx);
|
|
18791
19127
|
if (op.database === "cms_admin") {
|
|
@@ -18802,6 +19138,8 @@ class DatabaseAdapter {
|
|
|
18802
19138
|
return out;
|
|
18803
19139
|
});
|
|
18804
19140
|
} catch (thrown) {
|
|
19141
|
+
if (thrown instanceof NestedPoolCheckoutError)
|
|
19142
|
+
throw thrown;
|
|
18805
19143
|
if (thrown instanceof OperationAbortError) {
|
|
18806
19144
|
return err(thrown.queryError);
|
|
18807
19145
|
}
|
|
@@ -18832,6 +19170,8 @@ class DatabaseAdapter {
|
|
|
18832
19170
|
publishFailure = `The change is saved, but the public site does not serve it yet: publishing it failed (${thrown instanceof Error ? thrown.message : String(thrown)}). Do not repeat the change; it is published automatically within seconds once the public database answers.`;
|
|
18833
19171
|
}
|
|
18834
19172
|
}
|
|
19173
|
+
if (result.ok)
|
|
19174
|
+
notifyOperationCommitted(op.name);
|
|
18835
19175
|
if (effectFailures.length > 0) {
|
|
18836
19176
|
const effects = postCommitFailureMessage(effectFailures);
|
|
18837
19177
|
return err({
|
|
@@ -18845,12 +19185,80 @@ class DatabaseAdapter {
|
|
|
18845
19185
|
}
|
|
18846
19186
|
return result;
|
|
18847
19187
|
}
|
|
19188
|
+
async#runDetached(op, ctx, validatedInput) {
|
|
19189
|
+
try {
|
|
19190
|
+
const branches = op.database === "cms_admin" ? namedBranches(ctx, validatedInput) : [];
|
|
19191
|
+
if (branches.length > 0) {
|
|
19192
|
+
const denied = await this.#transaction("admin", op.name, async (tx) => {
|
|
19193
|
+
await this.#setIdentity(tx, ctx);
|
|
19194
|
+
return firstInvisibleBranch(tx, branches);
|
|
19195
|
+
});
|
|
19196
|
+
if (denied !== null)
|
|
19197
|
+
return err(branchNotFound(op.name, denied));
|
|
19198
|
+
}
|
|
19199
|
+
const options = { holder: op.name };
|
|
19200
|
+
const runner = detachedRunner(op.name, (fn) => op.database === "cms_admin" ? this.withAdminTransaction(ctx, fn, options) : this.withPublicTransaction(ctx, fn, options));
|
|
19201
|
+
return await op.handler(ctx, validatedInput, runner);
|
|
19202
|
+
} catch (thrown) {
|
|
19203
|
+
if (thrown instanceof NestedPoolCheckoutError)
|
|
19204
|
+
throw thrown;
|
|
19205
|
+
if (thrown instanceof OperationAbortError)
|
|
19206
|
+
return err(thrown.queryError);
|
|
19207
|
+
const pgDetail = extractPgFields(thrown);
|
|
19208
|
+
return err({
|
|
19209
|
+
kind: "HandlerError",
|
|
19210
|
+
operation: op.name,
|
|
19211
|
+
message: thrown instanceof Error ? thrown.message : String(thrown),
|
|
19212
|
+
...pgDetail ? { pgDetail } : {}
|
|
19213
|
+
});
|
|
19214
|
+
}
|
|
19215
|
+
}
|
|
18848
19216
|
async#setIdentity(tx, ctx) {
|
|
18849
|
-
await tx.execute(sql`SELECT
|
|
18850
|
-
|
|
18851
|
-
|
|
18852
|
-
|
|
18853
|
-
|
|
19217
|
+
await tx.execute(sql`SELECT
|
|
19218
|
+
set_config('caelo.actor_id', ${ctx.actorId}, true),
|
|
19219
|
+
set_config('caelo.actor_kind', ${ctx.actorKind}, true),
|
|
19220
|
+
set_config('caelo.plugin_id', ${ctx.pluginId ?? ""}, true),
|
|
19221
|
+
set_config('caelo.chat_branch_id', ${ctx.chatBranchId ?? ""}, true),
|
|
19222
|
+
set_config('caelo.chat_task_id', ${ctx.chatTaskId ?? ""}, true)`);
|
|
19223
|
+
}
|
|
19224
|
+
async#runReadOperation(op, ctx, validatedInput) {
|
|
19225
|
+
try {
|
|
19226
|
+
const branches = namedBranches(ctx, validatedInput);
|
|
19227
|
+
if (branches.length > 0) {
|
|
19228
|
+
const denied = await this.#shortRead(ctx, op.name, (tx) => firstInvisibleBranch(tx, branches));
|
|
19229
|
+
if (denied !== null)
|
|
19230
|
+
return err(branchNotFound(op.name, denied));
|
|
19231
|
+
}
|
|
19232
|
+
return await op.handler(ctx, validatedInput, this.readScope(ctx, op.name));
|
|
19233
|
+
} catch (thrown) {
|
|
19234
|
+
if (thrown instanceof NestedPoolCheckoutError)
|
|
19235
|
+
throw thrown;
|
|
19236
|
+
if (thrown instanceof OperationAbortError)
|
|
19237
|
+
return err(thrown.queryError);
|
|
19238
|
+
if (isRlsDenial(thrown)) {
|
|
19239
|
+
return err({
|
|
19240
|
+
kind: "RLSDenied",
|
|
19241
|
+
operation: op.name,
|
|
19242
|
+
detail: thrown.message ?? "RLS policy denied the read"
|
|
19243
|
+
});
|
|
19244
|
+
}
|
|
19245
|
+
const pgDetail = extractPgFields(thrown);
|
|
19246
|
+
return err({
|
|
19247
|
+
kind: "HandlerError",
|
|
19248
|
+
operation: op.name,
|
|
19249
|
+
message: thrown instanceof Error ? thrown.message : String(thrown),
|
|
19250
|
+
...pgDetail ? { pgDetail } : {}
|
|
19251
|
+
});
|
|
19252
|
+
}
|
|
19253
|
+
}
|
|
19254
|
+
readScope(ctx, holder = "reads.read") {
|
|
19255
|
+
return { read: (fn) => this.#shortRead(ctx, holder, fn) };
|
|
19256
|
+
}
|
|
19257
|
+
#shortRead(ctx, holder, fn) {
|
|
19258
|
+
return this.#transaction("admin", holder, async (tx) => {
|
|
19259
|
+
await this.#setIdentity(tx, ctx);
|
|
19260
|
+
return fn(tx);
|
|
19261
|
+
});
|
|
18854
19262
|
}
|
|
18855
19263
|
async#settlePostCommit(operation, ctx, effects) {
|
|
18856
19264
|
if (effects.length === 0)
|
|
@@ -18866,7 +19274,7 @@ class DatabaseAdapter {
|
|
|
18866
19274
|
if (this.#admin === null)
|
|
18867
19275
|
continue;
|
|
18868
19276
|
try {
|
|
18869
|
-
await this.#admin.
|
|
19277
|
+
await this.#transaction("admin", `${operation}.post_commit`, async (tx) => {
|
|
18870
19278
|
await this.#setIdentity(tx, ctx);
|
|
18871
19279
|
await recordAudit(tx, {
|
|
18872
19280
|
actorId: ctx.actorId,
|
|
@@ -18891,13 +19299,15 @@ class DatabaseAdapter {
|
|
|
18891
19299
|
async close() {
|
|
18892
19300
|
await Promise.all([this.#adminRaw?.end(), this.#publicRaw.end()]);
|
|
18893
19301
|
}
|
|
18894
|
-
async withAdminTransaction(ctx, fn) {
|
|
18895
|
-
const
|
|
19302
|
+
async withAdminTransaction(ctx, fn, options = {}) {
|
|
19303
|
+
const holder = options.holder ?? "withAdminTransaction";
|
|
19304
|
+
this.#guard.assertMayCheckout("admin", holder);
|
|
19305
|
+
this.#adminDb(holder);
|
|
18896
19306
|
if (!this.#skipVerify)
|
|
18897
19307
|
await this.verifyRoles();
|
|
18898
19308
|
let publishAfterCommit = false;
|
|
18899
19309
|
let postCommit = [];
|
|
18900
|
-
const out = await
|
|
19310
|
+
const out = await this.#transaction("admin", holder, async (tx) => {
|
|
18901
19311
|
postCommit = collectPostCommitEffects(tx);
|
|
18902
19312
|
await this.#setIdentity(tx, ctx);
|
|
18903
19313
|
const denied = await firstInvisibleBranch(tx, namedBranches(ctx, undefined));
|
|
@@ -18908,25 +19318,27 @@ class DatabaseAdapter {
|
|
|
18908
19318
|
publishAfterCommit = await this.#projectionDirty(tx);
|
|
18909
19319
|
return result;
|
|
18910
19320
|
});
|
|
18911
|
-
const effectFailures = await this.#settlePostCommit(
|
|
19321
|
+
const effectFailures = await this.#settlePostCommit(holder, ctx, postCommit);
|
|
18912
19322
|
if (publishAfterCommit)
|
|
18913
19323
|
await this.#publishAfterCommit();
|
|
18914
19324
|
if (effectFailures.length > 0)
|
|
18915
19325
|
throw new Error(postCommitFailureMessage(effectFailures));
|
|
18916
19326
|
return out;
|
|
18917
19327
|
}
|
|
18918
|
-
async withPublicTransaction(ctx, fn) {
|
|
19328
|
+
async withPublicTransaction(ctx, fn, options = {}) {
|
|
19329
|
+
const holder = options.holder ?? "withPublicTransaction";
|
|
19330
|
+
this.#guard.assertMayCheckout("public", holder);
|
|
18919
19331
|
if (!this.#skipVerify)
|
|
18920
19332
|
await this.verifyRoles();
|
|
18921
19333
|
let postCommit = [];
|
|
18922
|
-
const out = await this.#
|
|
19334
|
+
const out = await this.#transaction("public", holder, async (tx) => {
|
|
18923
19335
|
postCommit = collectPostCommitEffects(tx);
|
|
18924
19336
|
await tx.execute(sql`SELECT set_config('caelo.actor_id', ${ctx.actorId}, true)`);
|
|
18925
19337
|
await tx.execute(sql`SELECT set_config('caelo.actor_kind', ${ctx.actorKind}, true)`);
|
|
18926
19338
|
await tx.execute(sql`SELECT set_config('caelo.plugin_id', ${ctx.pluginId ?? ""}, true)`);
|
|
18927
19339
|
return await fn(tx);
|
|
18928
19340
|
});
|
|
18929
|
-
const effectFailures = await this.#settlePostCommit(
|
|
19341
|
+
const effectFailures = await this.#settlePostCommit(holder, ctx, postCommit);
|
|
18930
19342
|
if (effectFailures.length > 0)
|
|
18931
19343
|
throw new Error(postCommitFailureMessage(effectFailures));
|
|
18932
19344
|
return out;
|
|
@@ -18934,9 +19346,11 @@ class DatabaseAdapter {
|
|
|
18934
19346
|
rawAdmin() {
|
|
18935
19347
|
if (this.#adminRaw === null)
|
|
18936
19348
|
throw new AdminDatabaseUnavailableError("rawAdmin");
|
|
19349
|
+
this.#guard.assertMayCheckout("admin", "rawAdmin()");
|
|
18937
19350
|
return this.#adminRaw;
|
|
18938
19351
|
}
|
|
18939
19352
|
rawPublic() {
|
|
19353
|
+
this.#guard.assertMayCheckout("public", "rawPublic()");
|
|
18940
19354
|
return this.#publicRaw;
|
|
18941
19355
|
}
|
|
18942
19356
|
async provisionPluginPublicSchema(opts) {
|
|
@@ -18945,12 +19359,11 @@ class DatabaseAdapter {
|
|
|
18945
19359
|
}
|
|
18946
19360
|
if (!this.#skipVerify)
|
|
18947
19361
|
await this.verifyRoles();
|
|
18948
|
-
const outcome = await this.#
|
|
19362
|
+
const outcome = await this.#transaction("public", "provisionPluginPublicSchema", async (tx) => {
|
|
18949
19363
|
return provisionPluginSchemaInTx(tx, "provisionPluginPublicSchema", opts);
|
|
18950
19364
|
});
|
|
18951
19365
|
if (outcome.droppedColumns.length > 0) {
|
|
18952
|
-
|
|
18953
|
-
await admin.transaction(async (tx) => {
|
|
19366
|
+
await this.#transaction("admin", "provisionPluginPublicSchema", async (tx) => {
|
|
18954
19367
|
await tx.execute(sql.raw("SELECT set_config('caelo.actor_kind', 'system', true)"));
|
|
18955
19368
|
await auditDroppedColumns(tx, "cms_public", opts.pluginId, outcome);
|
|
18956
19369
|
});
|
|
@@ -18960,10 +19373,10 @@ class DatabaseAdapter {
|
|
|
18960
19373
|
if (!/^[0-9a-f-]{36}$/i.test(opts.pluginId)) {
|
|
18961
19374
|
throw new Error(`provisionPluginAdminSchema: pluginId "${opts.pluginId}" is not a UUID`);
|
|
18962
19375
|
}
|
|
18963
|
-
|
|
19376
|
+
this.#adminDb("provisionPluginAdminSchema");
|
|
18964
19377
|
if (!this.#skipVerify)
|
|
18965
19378
|
await this.verifyRoles();
|
|
18966
|
-
await
|
|
19379
|
+
await this.#transaction("admin", "provisionPluginAdminSchema", async (tx) => {
|
|
18967
19380
|
const outcome = await provisionPluginSchemaInTx(tx, "provisionPluginAdminSchema", opts);
|
|
18968
19381
|
if (outcome.droppedColumns.length > 0) {
|
|
18969
19382
|
await auditDroppedColumns(tx, "cms_admin", opts.pluginId, outcome);
|
|
@@ -18971,13 +19384,13 @@ class DatabaseAdapter {
|
|
|
18971
19384
|
});
|
|
18972
19385
|
}
|
|
18973
19386
|
async dropPluginAdminSchema(opts) {
|
|
18974
|
-
|
|
19387
|
+
this.#adminDb("dropPluginAdminSchema");
|
|
18975
19388
|
if (!this.#skipVerify)
|
|
18976
19389
|
await this.verifyRoles();
|
|
18977
19390
|
if (!/^plugin_[a-z][a-z0-9_]*$/.test(opts.schemaName)) {
|
|
18978
19391
|
throw new Error(`dropPluginAdminSchema: refusing to drop schema "${opts.schemaName}" \u2014 name doesn't match plugin_<slug> pattern`);
|
|
18979
19392
|
}
|
|
18980
|
-
await
|
|
19393
|
+
await this.#transaction("admin", "dropPluginAdminSchema", async (tx) => {
|
|
18981
19394
|
await tx.execute(sql.raw("SELECT set_config('caelo.actor_kind', 'system', true)"));
|
|
18982
19395
|
await tx.execute(sql.raw(`DROP SCHEMA IF EXISTS "${opts.schemaName}" CASCADE`));
|
|
18983
19396
|
await tx.execute(sql`DELETE FROM plugin_schema_provisions WHERE schema_name = ${opts.schemaName}`);
|
|
@@ -18989,16 +19402,19 @@ class DatabaseAdapter {
|
|
|
18989
19402
|
if (!/^plugin_[a-z][a-z0-9_]*$/.test(opts.schemaName)) {
|
|
18990
19403
|
throw new Error(`dropPluginPublicSchema: refusing to drop schema "${opts.schemaName}" \u2014 name doesn't match plugin_<slug> pattern`);
|
|
18991
19404
|
}
|
|
18992
|
-
await this.#
|
|
19405
|
+
await this.#transaction("public", "dropPluginPublicSchema", async (tx) => {
|
|
18993
19406
|
await tx.execute(sql.raw("SELECT set_config('caelo.actor_kind', 'system', true)"));
|
|
18994
19407
|
await tx.execute(sql.raw(`DROP SCHEMA IF EXISTS "${opts.schemaName}" CASCADE`));
|
|
18995
19408
|
await tx.execute(sql`DELETE FROM plugin_schema_provisions WHERE schema_name = ${opts.schemaName}`);
|
|
18996
19409
|
});
|
|
18997
19410
|
}
|
|
18998
19411
|
get admin() {
|
|
18999
|
-
|
|
19412
|
+
const db = this.#adminDb("admin pool");
|
|
19413
|
+
this.#guard.assertMayCheckout("admin", "adapter.admin");
|
|
19414
|
+
return db;
|
|
19000
19415
|
}
|
|
19001
19416
|
get public() {
|
|
19417
|
+
this.#guard.assertMayCheckout("public", "adapter.public");
|
|
19002
19418
|
return this.#public;
|
|
19003
19419
|
}
|
|
19004
19420
|
}
|
|
@@ -19041,37 +19457,17 @@ async function execute(registry, adapter, ctx, name, rawInput, options = {}) {
|
|
|
19041
19457
|
if (!parsed.success) {
|
|
19042
19458
|
return err({ kind: "ValidationFailed", issues: parsed.error.issues });
|
|
19043
19459
|
}
|
|
19044
|
-
|
|
19045
|
-
|
|
19046
|
-
|
|
19047
|
-
|
|
19048
|
-
|
|
19049
|
-
|
|
19050
|
-
|
|
19051
|
-
|
|
19052
|
-
|
|
19053
|
-
if (recordedNames.has(name))
|
|
19054
|
-
return;
|
|
19055
|
-
recordedNames.add(name);
|
|
19056
|
-
const file = process.env.CAELO_OP_COVERAGE_FILE ?? OP_COVERAGE_FILE_DEFAULT;
|
|
19057
|
-
if (!coverageDirEnsured) {
|
|
19058
|
-
mkdirSync(dirname(file), { recursive: true });
|
|
19059
|
-
coverageDirEnsured = true;
|
|
19460
|
+
if (!isReadOperation(op) && op.stepwise) {
|
|
19461
|
+
const result = await op.stepwise(ctx, parsed.data, {
|
|
19462
|
+
registry,
|
|
19463
|
+
adapter,
|
|
19464
|
+
...options.signal ? { signal: options.signal } : {}
|
|
19465
|
+
});
|
|
19466
|
+
if (result.ok)
|
|
19467
|
+
notifyOperationCommitted(op.name);
|
|
19468
|
+
return result;
|
|
19060
19469
|
}
|
|
19061
|
-
|
|
19062
|
-
`, { flag: "a" });
|
|
19063
|
-
}
|
|
19064
|
-
function defineOperation(def) {
|
|
19065
|
-
if (process.env.CAELO_OP_COVERAGE !== "1")
|
|
19066
|
-
return def;
|
|
19067
|
-
const original = def.handler;
|
|
19068
|
-
return {
|
|
19069
|
-
...def,
|
|
19070
|
-
handler: (ctx, input, tx) => {
|
|
19071
|
-
recordOpInvocation(def.name);
|
|
19072
|
-
return original(ctx, input, tx);
|
|
19073
|
-
}
|
|
19074
|
-
};
|
|
19470
|
+
return adapter.runOperation(op, ctx, parsed.data);
|
|
19075
19471
|
}
|
|
19076
19472
|
// ../query-api/src/registry.ts
|
|
19077
19473
|
class OperationRegistry {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caelo-cms/provisioning",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"description": "Pulumi-driven provisioning for Caelo CMS — `bunx @caelo-cms/provisioning --provider <self-hosted|gcp|aws|azure>` brings up a TLS-served install with Postgres + storage + secrets manager + the admin + the API gateway.",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"prepublishOnly": "tsc -b --force && bun build ../platform-updater/src/agent-db.ts --target=bun --outfile=dist/agent-db.js && tsc --project stacks/gcp/tsconfig.json && tsc --project stacks/gcp-firebase/tsconfig.json"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@caelo-cms/shared": "^0.11.
|
|
43
|
+
"@caelo-cms/shared": "^0.11.3",
|
|
44
44
|
"@clack/prompts": "1.8.1",
|
|
45
45
|
"@pulumi/command": "^1",
|
|
46
46
|
"@pulumi/gcp": "^10",
|