@objectstack/runtime 6.8.0 → 6.8.1

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 CHANGED
@@ -2213,7 +2213,19 @@ var StandaloneStackConfigSchema = import_zod.z.object({
2213
2213
  databaseAuthToken: import_zod.z.string().optional(),
2214
2214
  databaseDriver: import_zod.z.enum(["sqlite", "sqlite-wasm", "turso", "memory", "postgres", "mongodb"]).optional(),
2215
2215
  environmentId: import_zod.z.string().optional(),
2216
- artifactPath: import_zod.z.string().optional()
2216
+ artifactPath: import_zod.z.string().optional(),
2217
+ /**
2218
+ * Project root directory. When set (typically by the CLI after locating
2219
+ * `objectstack.config.ts`), the default sqlite database is placed under
2220
+ * `<projectRoot>/.objectstack/data/standalone.db` instead of the global
2221
+ * `~/.objectstack/data/standalone.db`. This keeps per-project data
2222
+ * scoped to the project folder so different examples / apps don't
2223
+ * share a single database by accident.
2224
+ *
2225
+ * Explicit `databaseUrl` / `OS_DATABASE_URL` / `OS_HOME` still take
2226
+ * precedence over this default.
2227
+ */
2228
+ projectRoot: import_zod.z.string().optional()
2217
2229
  });
2218
2230
  function detectDriverFromUrl(dbUrl) {
2219
2231
  if (/^memory:\/\//i.test(dbUrl)) return "memory";
@@ -2238,7 +2250,7 @@ async function createStandaloneStack(config) {
2238
2250
  const environmentId = cfg.environmentId ?? process.env.OS_ENVIRONMENT_ID ?? "proj_local";
2239
2251
  const artifactPathInput = cfg.artifactPath ?? process.env.OS_ARTIFACT_PATH ?? (0, import_node_path2.resolve)(cwd, "dist/objectstack.json");
2240
2252
  const artifactPath = isHttpUrl(artifactPathInput) ? artifactPathInput : artifactPathInput.startsWith("/") ? artifactPathInput : (0, import_node_path2.resolve)(cwd, artifactPathInput);
2241
- const dbUrl = cfg.databaseUrl ?? process.env.OS_DATABASE_URL?.trim() ?? process.env.TURSO_DATABASE_URL?.trim() ?? `file:${(0, import_node_path2.resolve)(resolveObjectStackHome(), "data/standalone.db")}`;
2253
+ const dbUrl = cfg.databaseUrl ?? process.env.OS_DATABASE_URL?.trim() ?? process.env.TURSO_DATABASE_URL?.trim() ?? (process.env.OS_HOME?.trim() ? `file:${(0, import_node_path2.resolve)(resolveObjectStackHome(), "data/standalone.db")}` : cfg.projectRoot ? `file:${(0, import_node_path2.resolve)(cfg.projectRoot, ".objectstack/data/standalone.db")}` : `file:${(0, import_node_path2.resolve)(resolveObjectStackHome(), "data/standalone.db")}`);
2242
2254
  const dbAuthToken = cfg.databaseAuthToken ?? process.env.OS_DATABASE_AUTH_TOKEN?.trim() ?? process.env.TURSO_AUTH_TOKEN?.trim();
2243
2255
  const explicitDriver = cfg.databaseDriver ?? process.env.OS_DATABASE_DRIVER?.trim();
2244
2256
  const dbDriver = explicitDriver ?? detectDriverFromUrl(dbUrl);
@@ -2456,6 +2468,13 @@ function toHeaders(input) {
2456
2468
  }
2457
2469
  return h;
2458
2470
  }
2471
+ function safeJsonParse2(s, fallback) {
2472
+ try {
2473
+ return JSON.parse(s);
2474
+ } catch {
2475
+ return fallback;
2476
+ }
2477
+ }
2459
2478
  async function tryFind(ql, object, where, limit = 100) {
2460
2479
  if (!ql || typeof ql.find !== "function") return [];
2461
2480
  try {
@@ -2471,6 +2490,7 @@ async function resolveExecutionContext(opts) {
2471
2490
  const ctx = {
2472
2491
  roles: [],
2473
2492
  permissions: [],
2493
+ systemPermissions: [],
2474
2494
  isSystem: false
2475
2495
  };
2476
2496
  let userId;
@@ -2579,10 +2599,38 @@ async function resolveExecutionContext(opts) {
2579
2599
  { id: { $in: Array.from(psIds) } },
2580
2600
  500
2581
2601
  );
2602
+ const tabRank = {
2603
+ hidden: 0,
2604
+ default_off: 1,
2605
+ default_on: 2,
2606
+ visible: 3
2607
+ };
2608
+ const mergedTabs = {};
2582
2609
  for (const ps of psRows) {
2583
2610
  if (ps.name && !ctx.permissions.includes(ps.name)) {
2584
2611
  ctx.permissions.push(ps.name);
2585
2612
  }
2613
+ const sysPerms = typeof ps.system_permissions === "string" ? safeJsonParse2(ps.system_permissions, []) : ps.system_permissions ?? ps.systemPermissions;
2614
+ if (Array.isArray(sysPerms)) {
2615
+ for (const p of sysPerms) {
2616
+ if (typeof p === "string" && !ctx.systemPermissions.includes(p)) {
2617
+ ctx.systemPermissions.push(p);
2618
+ }
2619
+ }
2620
+ }
2621
+ const tabs = typeof ps.tab_permissions === "string" ? safeJsonParse2(ps.tab_permissions, {}) : ps.tab_permissions ?? ps.tabPermissions;
2622
+ if (tabs && typeof tabs === "object") {
2623
+ for (const [app, val] of Object.entries(tabs)) {
2624
+ if (typeof val !== "string" || !(val in tabRank)) continue;
2625
+ const cur = mergedTabs[app];
2626
+ if (!cur || tabRank[val] > tabRank[cur]) {
2627
+ mergedTabs[app] = val;
2628
+ }
2629
+ }
2630
+ }
2631
+ }
2632
+ if (Object.keys(mergedTabs).length > 0) {
2633
+ ctx.tabPermissions = mergedTabs;
2586
2634
  }
2587
2635
  }
2588
2636
  return ctx;