@objectstack/runtime 7.0.0 → 7.2.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/index.cjs +162 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +162 -14
- package/dist/index.js.map +1 -1
- package/package.json +18 -18
package/dist/index.cjs
CHANGED
|
@@ -1709,7 +1709,8 @@ var init_app_plugin = __esm({
|
|
|
1709
1709
|
"translations",
|
|
1710
1710
|
"sharingRules",
|
|
1711
1711
|
"ragPipelines",
|
|
1712
|
-
"data"
|
|
1712
|
+
"data",
|
|
1713
|
+
"emailTemplates"
|
|
1713
1714
|
];
|
|
1714
1715
|
const hasAppPayload = APP_CATEGORY_KEYS.some((k) => {
|
|
1715
1716
|
const v = (bundle && bundle[k]) ?? (sys && sys[k]);
|
|
@@ -8474,6 +8475,36 @@ function resolveCloudUrl(explicit) {
|
|
|
8474
8475
|
return picked.replace(/\/+$/, "");
|
|
8475
8476
|
}
|
|
8476
8477
|
|
|
8478
|
+
// src/cloud/marketplace-public-url.ts
|
|
8479
|
+
function resolveMarketplacePublicBaseUrl(explicit) {
|
|
8480
|
+
const raw = (explicit ?? process.env.OS_MARKETPLACE_PUBLIC_BASE_URL ?? "").trim();
|
|
8481
|
+
const lower = raw.toLowerCase();
|
|
8482
|
+
if (!raw || lower === "off" || lower === "none" || lower === "disabled" || lower === "false") {
|
|
8483
|
+
return "";
|
|
8484
|
+
}
|
|
8485
|
+
return raw.replace(/\/+$/, "");
|
|
8486
|
+
}
|
|
8487
|
+
function publicMarketplaceKeyForApiPath(pathname) {
|
|
8488
|
+
const prefix = "/api/v1/marketplace/packages";
|
|
8489
|
+
if (pathname === prefix) return "packages.json";
|
|
8490
|
+
if (!pathname.startsWith(`${prefix}/`)) return null;
|
|
8491
|
+
const tail = pathname.slice(prefix.length + 1);
|
|
8492
|
+
if (!tail) return null;
|
|
8493
|
+
const parts = tail.split("/");
|
|
8494
|
+
if (parts.length === 1) {
|
|
8495
|
+
const id = decodeURIComponent(parts[0] ?? "");
|
|
8496
|
+
if (!id) return null;
|
|
8497
|
+
return `packages/${encodeURIComponent(id)}.json`;
|
|
8498
|
+
}
|
|
8499
|
+
if (parts.length === 4 && parts[1] === "versions" && parts[3] === "manifest") {
|
|
8500
|
+
const id = decodeURIComponent(parts[0] ?? "");
|
|
8501
|
+
const versionId = decodeURIComponent(parts[2] ?? "");
|
|
8502
|
+
if (!id || !versionId) return null;
|
|
8503
|
+
return `packages/${encodeURIComponent(id)}/versions/${encodeURIComponent(versionId)}/manifest.json`;
|
|
8504
|
+
}
|
|
8505
|
+
return null;
|
|
8506
|
+
}
|
|
8507
|
+
|
|
8477
8508
|
// src/cloud/marketplace-proxy-plugin.ts
|
|
8478
8509
|
var MARKETPLACE_PREFIX = "/api/v1/marketplace";
|
|
8479
8510
|
var DEFAULT_LRU_MAX = 200;
|
|
@@ -8513,7 +8544,7 @@ var LruTtlCache = class {
|
|
|
8513
8544
|
var MarketplaceProxyPlugin = class _MarketplaceProxyPlugin {
|
|
8514
8545
|
constructor(config = {}) {
|
|
8515
8546
|
this.name = "com.objectstack.runtime.marketplace-proxy";
|
|
8516
|
-
this.version = "1.
|
|
8547
|
+
this.version = "1.1.0";
|
|
8517
8548
|
this.init = async (_ctx) => {
|
|
8518
8549
|
};
|
|
8519
8550
|
this.start = async (ctx) => {
|
|
@@ -8531,7 +8562,11 @@ var MarketplaceProxyPlugin = class _MarketplaceProxyPlugin {
|
|
|
8531
8562
|
}
|
|
8532
8563
|
const rawApp = httpServer.getRawApp();
|
|
8533
8564
|
const cloudUrl = this.cloudUrl;
|
|
8565
|
+
const publicBaseUrl = this.publicBaseUrl;
|
|
8534
8566
|
const cache = this.cache;
|
|
8567
|
+
if (publicBaseUrl) {
|
|
8568
|
+
ctx.logger?.info?.(`[MarketplaceProxyPlugin] public R2 fast-path enabled \u2192 ${publicBaseUrl}`);
|
|
8569
|
+
}
|
|
8535
8570
|
const handler = async (c, next) => {
|
|
8536
8571
|
if (!cloudUrl) {
|
|
8537
8572
|
return c.json({
|
|
@@ -8547,8 +8582,18 @@ var MarketplaceProxyPlugin = class _MarketplaceProxyPlugin {
|
|
|
8547
8582
|
if (incomingUrl.pathname.startsWith(`${MARKETPLACE_PREFIX}/install-local`)) {
|
|
8548
8583
|
return next();
|
|
8549
8584
|
}
|
|
8550
|
-
const target = `${cloudUrl}${incomingUrl.pathname}${incomingUrl.search}`;
|
|
8551
8585
|
const method = String(c.req.method ?? "GET").toUpperCase();
|
|
8586
|
+
if (publicBaseUrl && (method === "GET" || method === "HEAD")) {
|
|
8587
|
+
const r2Resp = await tryPublicMarketplaceFetch(
|
|
8588
|
+
publicBaseUrl,
|
|
8589
|
+
incomingUrl,
|
|
8590
|
+
method,
|
|
8591
|
+
c.req.header("accept"),
|
|
8592
|
+
ctx.logger
|
|
8593
|
+
);
|
|
8594
|
+
if (r2Resp) return r2Resp;
|
|
8595
|
+
}
|
|
8596
|
+
const target = `${cloudUrl}${incomingUrl.pathname}${incomingUrl.search}`;
|
|
8552
8597
|
if (method !== "GET" && method !== "HEAD") {
|
|
8553
8598
|
return c.json({
|
|
8554
8599
|
success: false,
|
|
@@ -8629,12 +8674,82 @@ var MarketplaceProxyPlugin = class _MarketplaceProxyPlugin {
|
|
|
8629
8674
|
});
|
|
8630
8675
|
};
|
|
8631
8676
|
this.cloudUrl = resolveCloudUrl(config.controlPlaneUrl);
|
|
8677
|
+
this.publicBaseUrl = resolveMarketplacePublicBaseUrl(config.publicMarketplaceBaseUrl);
|
|
8632
8678
|
const envFlag = (process.env.OS_MARKETPLACE_CACHE ?? "").trim().toLowerCase();
|
|
8633
8679
|
const envDisabled = ["off", "false", "0", "no", "disable", "disabled"].includes(envFlag);
|
|
8634
8680
|
const disabled = config.cacheDisabled ?? envDisabled;
|
|
8635
8681
|
this.cache = disabled ? null : new LruTtlCache(Math.max(8, config.cacheMaxEntries ?? DEFAULT_LRU_MAX));
|
|
8636
8682
|
}
|
|
8637
8683
|
};
|
|
8684
|
+
async function tryPublicMarketplaceFetch(publicBaseUrl, incomingUrl, method, acceptHeader, logger) {
|
|
8685
|
+
const key = publicMarketplaceKeyForApiPath(incomingUrl.pathname);
|
|
8686
|
+
if (!key) return null;
|
|
8687
|
+
const target = `${publicBaseUrl}/${key}`;
|
|
8688
|
+
let resp;
|
|
8689
|
+
try {
|
|
8690
|
+
resp = await fetch(target, {
|
|
8691
|
+
method: "GET",
|
|
8692
|
+
headers: {
|
|
8693
|
+
"Accept": acceptHeader || "application/json",
|
|
8694
|
+
"User-Agent": `objectos-marketplace-proxy/public-r2`
|
|
8695
|
+
}
|
|
8696
|
+
});
|
|
8697
|
+
} catch (err) {
|
|
8698
|
+
logger?.warn?.(`[MarketplaceProxyPlugin] public R2 fetch failed (${target}): ${err?.message ?? err}`);
|
|
8699
|
+
return null;
|
|
8700
|
+
}
|
|
8701
|
+
if (resp.status === 404) return null;
|
|
8702
|
+
if (!resp.ok) {
|
|
8703
|
+
logger?.warn?.(`[MarketplaceProxyPlugin] public R2 ${target} returned ${resp.status} \u2014 falling back to cloud`);
|
|
8704
|
+
return null;
|
|
8705
|
+
}
|
|
8706
|
+
const isList = key === "packages.json";
|
|
8707
|
+
const hasFilters = isList && (incomingUrl.searchParams.has("q") || incomingUrl.searchParams.has("category") || incomingUrl.searchParams.has("limit") || incomingUrl.searchParams.has("offset"));
|
|
8708
|
+
if (!hasFilters) {
|
|
8709
|
+
const headers2 = new Headers();
|
|
8710
|
+
const ct = resp.headers.get("content-type") ?? "application/json; charset=utf-8";
|
|
8711
|
+
headers2.set("content-type", ct);
|
|
8712
|
+
const cc = resp.headers.get("cache-control");
|
|
8713
|
+
if (cc) headers2.set("cache-control", cc);
|
|
8714
|
+
const etag = resp.headers.get("etag");
|
|
8715
|
+
if (etag) headers2.set("etag", etag);
|
|
8716
|
+
headers2.set("x-cache", "PUBLIC-R2");
|
|
8717
|
+
const body2 = method === "HEAD" ? null : resp.body;
|
|
8718
|
+
return new Response(body2, { status: 200, headers: headers2 });
|
|
8719
|
+
}
|
|
8720
|
+
let snapshot;
|
|
8721
|
+
try {
|
|
8722
|
+
snapshot = await resp.json();
|
|
8723
|
+
} catch (err) {
|
|
8724
|
+
logger?.warn?.(`[MarketplaceProxyPlugin] public R2 list snapshot parse failed: ${err?.message ?? err}`);
|
|
8725
|
+
return null;
|
|
8726
|
+
}
|
|
8727
|
+
const items = Array.isArray(snapshot?.data?.items) ? snapshot.data.items : [];
|
|
8728
|
+
const q = (incomingUrl.searchParams.get("q") ?? "").trim().toLowerCase();
|
|
8729
|
+
const category = (incomingUrl.searchParams.get("category") ?? "").trim();
|
|
8730
|
+
const limit = Math.min(Math.max(Number(incomingUrl.searchParams.get("limit") ?? 50), 1), 100);
|
|
8731
|
+
const offset = Math.max(Number(incomingUrl.searchParams.get("offset") ?? 0), 0);
|
|
8732
|
+
let filtered = items;
|
|
8733
|
+
if (q) {
|
|
8734
|
+
filtered = filtered.filter((r) => {
|
|
8735
|
+
const dn = String(r?.display_name ?? "").toLowerCase();
|
|
8736
|
+
const mid = String(r?.manifest_id ?? "").toLowerCase();
|
|
8737
|
+
return dn.includes(q) || mid.includes(q);
|
|
8738
|
+
});
|
|
8739
|
+
}
|
|
8740
|
+
if (category) {
|
|
8741
|
+
filtered = filtered.filter((r) => String(r?.category ?? "") === category);
|
|
8742
|
+
}
|
|
8743
|
+
const total = filtered.length;
|
|
8744
|
+
const page = filtered.slice(offset, offset + limit);
|
|
8745
|
+
const body = JSON.stringify({ success: true, data: { items: page, total, limit, offset } });
|
|
8746
|
+
const headers = new Headers({
|
|
8747
|
+
"content-type": "application/json; charset=utf-8",
|
|
8748
|
+
"cache-control": "public, max-age=30",
|
|
8749
|
+
"x-cache": "PUBLIC-R2-FILTERED"
|
|
8750
|
+
});
|
|
8751
|
+
return new Response(method === "HEAD" ? null : body, { status: 200, headers });
|
|
8752
|
+
}
|
|
8638
8753
|
var PASSTHROUGH_HEADERS = ["content-type", "cache-control", "etag", "last-modified", "vary"];
|
|
8639
8754
|
function collectHeaders(src) {
|
|
8640
8755
|
const out = {};
|
|
@@ -9118,22 +9233,55 @@ var MarketplaceInstallLocalPlugin = class {
|
|
|
9118
9233
|
return c.json({ success: false, error: { code: "bad_request", message: "packageId is required." } }, 400);
|
|
9119
9234
|
}
|
|
9120
9235
|
let payload;
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9236
|
+
const publicBase = resolveMarketplacePublicBaseUrl();
|
|
9237
|
+
const fetchAttempts = [];
|
|
9238
|
+
if (publicBase) {
|
|
9239
|
+
fetchAttempts.push({
|
|
9240
|
+
label: "public-r2",
|
|
9241
|
+
url: `${publicBase}/packages/${encodeURIComponent(packageId)}/versions/${encodeURIComponent(versionId)}/manifest.json`
|
|
9242
|
+
});
|
|
9243
|
+
}
|
|
9244
|
+
fetchAttempts.push({
|
|
9245
|
+
label: "cloud",
|
|
9246
|
+
url: `${this.cloudUrl}/api/v1/marketplace/packages/${encodeURIComponent(packageId)}/versions/${encodeURIComponent(versionId)}/manifest`
|
|
9247
|
+
});
|
|
9248
|
+
let lastErrStatus = 0;
|
|
9249
|
+
let lastErrText = "";
|
|
9250
|
+
for (const attempt of fetchAttempts) {
|
|
9251
|
+
try {
|
|
9252
|
+
const resp = await fetch(attempt.url, { headers: { "Accept": "application/json" } });
|
|
9253
|
+
if (!resp.ok) {
|
|
9254
|
+
lastErrStatus = resp.status;
|
|
9255
|
+
lastErrText = (await resp.text().catch(() => "")).slice(0, 200);
|
|
9256
|
+
if (attempt.label === "public-r2" && resp.status === 404) {
|
|
9257
|
+
ctx.logger?.info?.(`[MarketplaceInstallLocal] public-r2 miss for ${packageId}@${versionId}, falling back to cloud`);
|
|
9258
|
+
continue;
|
|
9259
|
+
}
|
|
9260
|
+
if (attempt.label === "public-r2" && resp.status >= 500) {
|
|
9261
|
+
ctx.logger?.warn?.(`[MarketplaceInstallLocal] public-r2 ${resp.status}, falling back to cloud`);
|
|
9262
|
+
continue;
|
|
9263
|
+
}
|
|
9264
|
+
break;
|
|
9265
|
+
}
|
|
9266
|
+
payload = await resp.json();
|
|
9267
|
+
lastErrStatus = 0;
|
|
9268
|
+
break;
|
|
9269
|
+
} catch (err) {
|
|
9270
|
+
if (attempt.label === "public-r2") {
|
|
9271
|
+
ctx.logger?.warn?.(`[MarketplaceInstallLocal] public-r2 fetch error: ${err?.message ?? err}, falling back to cloud`);
|
|
9272
|
+
continue;
|
|
9273
|
+
}
|
|
9126
9274
|
return c.json({
|
|
9127
9275
|
success: false,
|
|
9128
|
-
error: { code: "cloud_fetch_failed", message:
|
|
9129
|
-
},
|
|
9276
|
+
error: { code: "cloud_fetch_failed", message: err?.message ?? String(err) }
|
|
9277
|
+
}, 502);
|
|
9130
9278
|
}
|
|
9131
|
-
|
|
9132
|
-
|
|
9279
|
+
}
|
|
9280
|
+
if (!payload) {
|
|
9133
9281
|
return c.json({
|
|
9134
9282
|
success: false,
|
|
9135
|
-
error: { code: "cloud_fetch_failed", message:
|
|
9136
|
-
}, 502);
|
|
9283
|
+
error: { code: "cloud_fetch_failed", message: `Cloud returned ${lastErrStatus}: ${lastErrText}` }
|
|
9284
|
+
}, lastErrStatus === 404 ? 404 : 502);
|
|
9137
9285
|
}
|
|
9138
9286
|
const data = payload?.data ?? payload;
|
|
9139
9287
|
const manifest = data?.manifest;
|