@objectstack/runtime 9.10.0 → 10.0.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 +59 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +59 -5
- package/dist/index.js.map +1 -1
- package/package.json +20 -19
package/dist/index.cjs
CHANGED
|
@@ -987,6 +987,35 @@ var init_app_plugin = __esm({
|
|
|
987
987
|
error: err?.message ?? String(err)
|
|
988
988
|
});
|
|
989
989
|
}
|
|
990
|
+
try {
|
|
991
|
+
const metadata = ctx.getService("metadata");
|
|
992
|
+
if (typeof metadata?.registerInMemory === "function") {
|
|
993
|
+
const securityBundle = this.bundle.manifest ? { ...this.bundle.manifest, ...this.bundle } : this.bundle;
|
|
994
|
+
const SECURITY_FIELDS = [
|
|
995
|
+
["roles", "role"],
|
|
996
|
+
["permissions", "permission"],
|
|
997
|
+
["sharingRules", "sharing_rule"],
|
|
998
|
+
["policies", "policy"]
|
|
999
|
+
];
|
|
1000
|
+
let count = 0;
|
|
1001
|
+
for (const [field, type] of SECURITY_FIELDS) {
|
|
1002
|
+
const arr = securityBundle?.[field];
|
|
1003
|
+
if (!Array.isArray(arr)) continue;
|
|
1004
|
+
for (const item of arr) {
|
|
1005
|
+
if (!item?.name) continue;
|
|
1006
|
+
metadata.registerInMemory(type, item.name, item);
|
|
1007
|
+
count += 1;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
if (count > 0) {
|
|
1011
|
+
ctx.logger.info("Registered stack-declared security metadata", { appId, count });
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
} catch (err) {
|
|
1015
|
+
ctx.logger.warn("[AppPlugin] failed to register security metadata", {
|
|
1016
|
+
error: err?.message ?? String(err)
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
990
1019
|
const stackBundle = this.bundle.default || this.bundle;
|
|
991
1020
|
const runtime = stackBundle && typeof stackBundle.onEnable === "function" ? stackBundle : this.bundle;
|
|
992
1021
|
if (runtime && typeof runtime.onEnable === "function") {
|
|
@@ -1606,6 +1635,8 @@ async function createStandaloneStack(config) {
|
|
|
1606
1635
|
const requires = Array.isArray(artifactBundle?.requires) ? artifactBundle.requires.filter((c) => typeof c === "string") : void 0;
|
|
1607
1636
|
const objects = Array.isArray(artifactBundle?.objects) ? artifactBundle.objects : void 0;
|
|
1608
1637
|
const manifest = artifactBundle?.manifest;
|
|
1638
|
+
const permissions = Array.isArray(artifactBundle?.permissions) ? artifactBundle.permissions : void 0;
|
|
1639
|
+
const roles = Array.isArray(artifactBundle?.roles) ? artifactBundle.roles : void 0;
|
|
1609
1640
|
return {
|
|
1610
1641
|
plugins,
|
|
1611
1642
|
api: {
|
|
@@ -1614,7 +1645,9 @@ async function createStandaloneStack(config) {
|
|
|
1614
1645
|
},
|
|
1615
1646
|
...requires ? { requires } : {},
|
|
1616
1647
|
...objects ? { objects } : {},
|
|
1617
|
-
...manifest ? { manifest } : {}
|
|
1648
|
+
...manifest ? { manifest } : {},
|
|
1649
|
+
...permissions ? { permissions } : {},
|
|
1650
|
+
...roles ? { roles } : {}
|
|
1618
1651
|
};
|
|
1619
1652
|
}
|
|
1620
1653
|
var import_node_path3, import_node_fs2, import_node_os, import_zod, import_types2, StandaloneStackConfigSchema;
|
|
@@ -2065,25 +2098,33 @@ function coerceLocale(value) {
|
|
|
2065
2098
|
const s = typeof value === "string" ? value.trim() : value != null ? String(value).trim() : "";
|
|
2066
2099
|
return s || void 0;
|
|
2067
2100
|
}
|
|
2101
|
+
function coerceCurrency(value) {
|
|
2102
|
+
const s = typeof value === "string" ? value.trim().toUpperCase() : "";
|
|
2103
|
+
return /^[A-Z]{3}$/.test(s) ? s : void 0;
|
|
2104
|
+
}
|
|
2068
2105
|
async function resolveLocalization(opts, ql, sctx) {
|
|
2069
2106
|
try {
|
|
2070
2107
|
const settings = await opts.getService("settings");
|
|
2071
2108
|
if (settings && typeof settings.get === "function") {
|
|
2072
|
-
const [tzRes, localeRes] = await Promise.all([
|
|
2109
|
+
const [tzRes, localeRes, currencyRes] = await Promise.all([
|
|
2073
2110
|
settings.get("localization", "timezone", sctx).catch(() => void 0),
|
|
2074
|
-
settings.get("localization", "locale", sctx).catch(() => void 0)
|
|
2111
|
+
settings.get("localization", "locale", sctx).catch(() => void 0),
|
|
2112
|
+
settings.get("localization", "currency", sctx).catch(() => void 0)
|
|
2075
2113
|
]);
|
|
2076
2114
|
const tz = coerceTimeZone(tzRes?.value);
|
|
2077
2115
|
const locale = coerceLocale(localeRes?.value);
|
|
2078
|
-
|
|
2116
|
+
const currency = coerceCurrency(currencyRes?.value);
|
|
2117
|
+
if (tz || locale || currency) return { timezone: tz ?? "UTC", locale: locale ?? "en-US", currency };
|
|
2079
2118
|
}
|
|
2080
2119
|
} catch {
|
|
2081
2120
|
}
|
|
2082
2121
|
const tzRows = await tryFind(ql, "sys_setting", { namespace: "localization", key: "timezone", scope: "tenant" }, 1);
|
|
2083
2122
|
const localeRows = await tryFind(ql, "sys_setting", { namespace: "localization", key: "locale", scope: "tenant" }, 1);
|
|
2123
|
+
const currencyRows = await tryFind(ql, "sys_setting", { namespace: "localization", key: "currency", scope: "tenant" }, 1);
|
|
2084
2124
|
return {
|
|
2085
2125
|
timezone: coerceTimeZone(tzRows[0]?.value) ?? "UTC",
|
|
2086
|
-
locale: coerceLocale(localeRows[0]?.value) ?? "en-US"
|
|
2126
|
+
locale: coerceLocale(localeRows[0]?.value) ?? "en-US",
|
|
2127
|
+
currency: coerceCurrency(currencyRows[0]?.value)
|
|
2087
2128
|
};
|
|
2088
2129
|
}
|
|
2089
2130
|
async function resolveExecutionContext(opts) {
|
|
@@ -2116,6 +2157,7 @@ async function resolveExecutionContext(opts) {
|
|
|
2116
2157
|
userId = sessionData?.user?.id ?? sessionData?.session?.userId;
|
|
2117
2158
|
tenantId = tenantId ?? sessionData?.session?.activeOrganizationId;
|
|
2118
2159
|
ctx.accessToken = sessionData?.session?.token ?? ctx.accessToken;
|
|
2160
|
+
if (sessionData?.user?.email) ctx.email = String(sessionData.user.email);
|
|
2119
2161
|
} catch {
|
|
2120
2162
|
}
|
|
2121
2163
|
}
|
|
@@ -2124,6 +2166,10 @@ async function resolveExecutionContext(opts) {
|
|
|
2124
2166
|
if (!userId) return ctx;
|
|
2125
2167
|
const ql = await opts.getQl();
|
|
2126
2168
|
if (!ql) return ctx;
|
|
2169
|
+
if (!ctx.email) {
|
|
2170
|
+
const userRows = await tryFind(ql, "sys_user", { id: userId }, 1);
|
|
2171
|
+
if (userRows[0]?.email) ctx.email = String(userRows[0].email);
|
|
2172
|
+
}
|
|
2127
2173
|
const memberWhere = tenantId ? { user_id: userId, organization_id: tenantId } : { user_id: userId };
|
|
2128
2174
|
const members = await tryFind(ql, "sys_member", memberWhere, 50);
|
|
2129
2175
|
for (const m of members) {
|
|
@@ -2133,6 +2179,13 @@ async function resolveExecutionContext(opts) {
|
|
|
2133
2179
|
}
|
|
2134
2180
|
}
|
|
2135
2181
|
}
|
|
2182
|
+
const userRoleRows = await tryFind(ql, "sys_user_role", { user_id: userId }, 200);
|
|
2183
|
+
for (const ur of userRoleRows) {
|
|
2184
|
+
const org = ur.organization_id ?? null;
|
|
2185
|
+
if (org && tenantId && org !== tenantId) continue;
|
|
2186
|
+
const r = ur.role;
|
|
2187
|
+
if (typeof r === "string" && r && !ctx.roles.includes(r)) ctx.roles.push(r);
|
|
2188
|
+
}
|
|
2136
2189
|
if (tenantId) {
|
|
2137
2190
|
const orgMembers = await tryFind(
|
|
2138
2191
|
ql,
|
|
@@ -2219,6 +2272,7 @@ async function resolveExecutionContext(opts) {
|
|
|
2219
2272
|
const localization = await resolveLocalization(opts, ql, { tenantId, userId });
|
|
2220
2273
|
ctx.timezone = localization.timezone;
|
|
2221
2274
|
ctx.locale = localization.locale;
|
|
2275
|
+
if (localization.currency) ctx.currency = localization.currency;
|
|
2222
2276
|
return ctx;
|
|
2223
2277
|
}
|
|
2224
2278
|
function isPermissionDeniedError(e) {
|