@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.d.cts CHANGED
@@ -98,6 +98,7 @@ declare const StandaloneStackConfigSchema: z.ZodObject<{
98
98
  }>>;
99
99
  environmentId: z.ZodOptional<z.ZodString>;
100
100
  artifactPath: z.ZodOptional<z.ZodString>;
101
+ projectRoot: z.ZodOptional<z.ZodString>;
101
102
  }, z.core.$strip>;
102
103
  type StandaloneStackConfig = z.input<typeof StandaloneStackConfigSchema>;
103
104
  interface StandaloneStackResult {
package/dist/index.d.ts CHANGED
@@ -98,6 +98,7 @@ declare const StandaloneStackConfigSchema: z.ZodObject<{
98
98
  }>>;
99
99
  environmentId: z.ZodOptional<z.ZodString>;
100
100
  artifactPath: z.ZodOptional<z.ZodString>;
101
+ projectRoot: z.ZodOptional<z.ZodString>;
101
102
  }, z.core.$strip>;
102
103
  type StandaloneStackConfig = z.input<typeof StandaloneStackConfigSchema>;
103
104
  interface StandaloneStackResult {
package/dist/index.js CHANGED
@@ -2122,7 +2122,19 @@ var StandaloneStackConfigSchema = z.object({
2122
2122
  databaseAuthToken: z.string().optional(),
2123
2123
  databaseDriver: z.enum(["sqlite", "sqlite-wasm", "turso", "memory", "postgres", "mongodb"]).optional(),
2124
2124
  environmentId: z.string().optional(),
2125
- artifactPath: z.string().optional()
2125
+ artifactPath: z.string().optional(),
2126
+ /**
2127
+ * Project root directory. When set (typically by the CLI after locating
2128
+ * `objectstack.config.ts`), the default sqlite database is placed under
2129
+ * `<projectRoot>/.objectstack/data/standalone.db` instead of the global
2130
+ * `~/.objectstack/data/standalone.db`. This keeps per-project data
2131
+ * scoped to the project folder so different examples / apps don't
2132
+ * share a single database by accident.
2133
+ *
2134
+ * Explicit `databaseUrl` / `OS_DATABASE_URL` / `OS_HOME` still take
2135
+ * precedence over this default.
2136
+ */
2137
+ projectRoot: z.string().optional()
2126
2138
  });
2127
2139
  function detectDriverFromUrl(dbUrl) {
2128
2140
  if (/^memory:\/\//i.test(dbUrl)) return "memory";
@@ -2147,7 +2159,7 @@ async function createStandaloneStack(config) {
2147
2159
  const environmentId = cfg.environmentId ?? process.env.OS_ENVIRONMENT_ID ?? "proj_local";
2148
2160
  const artifactPathInput = cfg.artifactPath ?? process.env.OS_ARTIFACT_PATH ?? resolvePath2(cwd, "dist/objectstack.json");
2149
2161
  const artifactPath = isHttpUrl(artifactPathInput) ? artifactPathInput : artifactPathInput.startsWith("/") ? artifactPathInput : resolvePath2(cwd, artifactPathInput);
2150
- const dbUrl = cfg.databaseUrl ?? process.env.OS_DATABASE_URL?.trim() ?? process.env.TURSO_DATABASE_URL?.trim() ?? `file:${resolvePath2(resolveObjectStackHome(), "data/standalone.db")}`;
2162
+ const dbUrl = cfg.databaseUrl ?? process.env.OS_DATABASE_URL?.trim() ?? process.env.TURSO_DATABASE_URL?.trim() ?? (process.env.OS_HOME?.trim() ? `file:${resolvePath2(resolveObjectStackHome(), "data/standalone.db")}` : cfg.projectRoot ? `file:${resolvePath2(cfg.projectRoot, ".objectstack/data/standalone.db")}` : `file:${resolvePath2(resolveObjectStackHome(), "data/standalone.db")}`);
2151
2163
  const dbAuthToken = cfg.databaseAuthToken ?? process.env.OS_DATABASE_AUTH_TOKEN?.trim() ?? process.env.TURSO_AUTH_TOKEN?.trim();
2152
2164
  const explicitDriver = cfg.databaseDriver ?? process.env.OS_DATABASE_DRIVER?.trim();
2153
2165
  const dbDriver = explicitDriver ?? detectDriverFromUrl(dbUrl);
@@ -2365,6 +2377,13 @@ function toHeaders(input) {
2365
2377
  }
2366
2378
  return h;
2367
2379
  }
2380
+ function safeJsonParse2(s, fallback) {
2381
+ try {
2382
+ return JSON.parse(s);
2383
+ } catch {
2384
+ return fallback;
2385
+ }
2386
+ }
2368
2387
  async function tryFind(ql, object, where, limit = 100) {
2369
2388
  if (!ql || typeof ql.find !== "function") return [];
2370
2389
  try {
@@ -2380,6 +2399,7 @@ async function resolveExecutionContext(opts) {
2380
2399
  const ctx = {
2381
2400
  roles: [],
2382
2401
  permissions: [],
2402
+ systemPermissions: [],
2383
2403
  isSystem: false
2384
2404
  };
2385
2405
  let userId;
@@ -2488,10 +2508,38 @@ async function resolveExecutionContext(opts) {
2488
2508
  { id: { $in: Array.from(psIds) } },
2489
2509
  500
2490
2510
  );
2511
+ const tabRank = {
2512
+ hidden: 0,
2513
+ default_off: 1,
2514
+ default_on: 2,
2515
+ visible: 3
2516
+ };
2517
+ const mergedTabs = {};
2491
2518
  for (const ps of psRows) {
2492
2519
  if (ps.name && !ctx.permissions.includes(ps.name)) {
2493
2520
  ctx.permissions.push(ps.name);
2494
2521
  }
2522
+ const sysPerms = typeof ps.system_permissions === "string" ? safeJsonParse2(ps.system_permissions, []) : ps.system_permissions ?? ps.systemPermissions;
2523
+ if (Array.isArray(sysPerms)) {
2524
+ for (const p of sysPerms) {
2525
+ if (typeof p === "string" && !ctx.systemPermissions.includes(p)) {
2526
+ ctx.systemPermissions.push(p);
2527
+ }
2528
+ }
2529
+ }
2530
+ const tabs = typeof ps.tab_permissions === "string" ? safeJsonParse2(ps.tab_permissions, {}) : ps.tab_permissions ?? ps.tabPermissions;
2531
+ if (tabs && typeof tabs === "object") {
2532
+ for (const [app, val] of Object.entries(tabs)) {
2533
+ if (typeof val !== "string" || !(val in tabRank)) continue;
2534
+ const cur = mergedTabs[app];
2535
+ if (!cur || tabRank[val] > tabRank[cur]) {
2536
+ mergedTabs[app] = val;
2537
+ }
2538
+ }
2539
+ }
2540
+ }
2541
+ if (Object.keys(mergedTabs).length > 0) {
2542
+ ctx.tabPermissions = mergedTabs;
2495
2543
  }
2496
2544
  }
2497
2545
  return ctx;