business-stack 0.1.1 → 0.1.5

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/README.md CHANGED
@@ -8,8 +8,9 @@ Install these on your machine and ensure they are on your `PATH`:
8
8
 
9
9
  | Tool | Purpose |
10
10
  |------|---------|
11
- | [Node.js](https://nodejs.org/) 20+ | Runs the `business-stack` CLI (`setup`, `start`, `doctor`) |
12
- | [Bun](https://bun.sh) | Installs JS workspaces and runs the gateway |
11
+ | [Node.js](https://nodejs.org/) 20+ | Runs the `business-stack` CLI |
12
+ | **npm** (comes with Node) | `business-stack start` / `dev` use **`npm install`** and **`npm run`** for workspaces and Turborepo |
13
+ | *(optional)* [Bun](https://bun.sh) | Only if you develop the **full monorepo** from git (`bun run dev` at repo root); **not** required for the published `business-stack` package |
13
14
  | [uv](https://docs.astral.sh/uv/) | Installs and runs the Python backend |
14
15
  | Python **3.12** | Required by the backend (managed via `uv`) |
15
16
 
@@ -19,6 +20,18 @@ Check your environment:
19
20
  npx business-stack doctor
20
21
  ```
21
22
 
23
+ ### Using `npx` (no install, or one-off runs)
24
+
25
+ `npx` runs the same `business-stack` binary as a global or local install. Use a version tag so npm does not cache an old release:
26
+
27
+ ```bash
28
+ npx --yes business-stack@latest doctor
29
+ npx --yes business-stack@latest setup --yes
30
+ npx --yes business-stack@latest start
31
+ ```
32
+
33
+ On **Windows Command Prompt**, use the same commands; if `npx` is slow the first time, it is downloading the package.
34
+
22
35
  ## Installation (recommended: project-level)
23
36
 
24
37
  **Prefer a local (project) install** so the stack, generated `.env` files, and SQLite database live under your project’s `node_modules/business-stack/`, match npm’s default `npm i business-stack`, and avoid permission or PATH issues from global installs.
@@ -49,7 +62,7 @@ npx business-stack start
49
62
  ```
50
63
 
51
64
  - **`setup`** generates secrets, stores them in SQLite (`node_modules/business-stack/gateway/auth.sqlite`, table `stack_secrets`), and writes `gateway/.env`, `frontend/web/.env.local`, and `backend/.env` under that package path. You do not need to create `.env` files by hand.
52
- - **`start`** runs `bun install`, `uv sync`, production build, Alembic migrations, then starts Next (`next start`), the gateway, and uvicorn. First run can take several minutes.
65
+ - **`start`** runs **`npm install`** (workspaces), **`uv sync`**, **`npm run build`**, Alembic migrations, then **`npm run start`** (Turborepo: Next, gateway, backend). First run can take several minutes.
53
66
 
54
67
  Optional flags for `start`: `--skip-install`, `--skip-build`, `--skip-migrate`.
55
68
 
@@ -111,18 +111,108 @@ function writeEnvFile(filePath, content) {
111
111
  fs.writeFileSync(filePath, `${content.trim()}\n`, "utf8");
112
112
  }
113
113
 
114
+ function getCliPackageVersion() {
115
+ try {
116
+ const p = path.join(__dirname, "..", "package.json");
117
+ return JSON.parse(fs.readFileSync(p, "utf8")).version;
118
+ } catch {
119
+ return "?";
120
+ }
121
+ }
122
+
123
+ function logPhase(msg) {
124
+ const line = `business-stack: ${msg}`;
125
+ console.log(line);
126
+ console.error(line);
127
+ }
128
+
129
+ /** Microsoft Store / WindowsApps shims often exit 0 immediately with no real Bun — skip them. */
130
+ function isWindowsAppsStub(exePath) {
131
+ const n = exePath.toLowerCase().replace(/\//g, "\\");
132
+ return (
133
+ n.includes("\\windowsapps\\") ||
134
+ n.includes("microsoft\\windowsapps") ||
135
+ n.endsWith("appinstaller.exe")
136
+ );
137
+ }
138
+
139
+ function whereAll(cmd) {
140
+ const r = spawnSync("where.exe", [cmd], {
141
+ encoding: "utf8",
142
+ windowsHide: true,
143
+ });
144
+ if (r.status !== 0 || !r.stdout) {
145
+ return [];
146
+ }
147
+ return r.stdout
148
+ .split(/\r?\n/)
149
+ .map((s) => s.trim())
150
+ .filter(Boolean);
151
+ }
152
+
153
+ function executableResponds(exe, args) {
154
+ const r = spawnSync(exe, args, {
155
+ encoding: "utf8",
156
+ windowsHide: true,
157
+ stdio: ["ignore", "pipe", "pipe"],
158
+ timeout: 20_000,
159
+ });
160
+ if (r.error) {
161
+ return false;
162
+ }
163
+ if (r.status !== 0) {
164
+ return false;
165
+ }
166
+ const out = `${String(r.stdout || "")}${String(r.stderr || "")}`.trim();
167
+ return out.length >= 2;
168
+ }
169
+
170
+ /**
171
+ * Resolve `npm` / `bun` / `uv` on Windows: `where` can list a useless WindowsApps stub first.
172
+ * Pick a path that successfully runs `--version`.
173
+ */
174
+ function resolveExecutable(cmd) {
175
+ if (process.platform !== "win32") {
176
+ return cmd;
177
+ }
178
+ const all = whereAll(cmd);
179
+ if (all.length === 0) {
180
+ return cmd;
181
+ }
182
+ const preferred = all.filter((p) => !isWindowsAppsStub(p));
183
+ const order = preferred.length > 0 ? preferred : all;
184
+ for (let i = order.length - 1; i >= 0; i--) {
185
+ const exe = order[i];
186
+ if (isWindowsAppsStub(exe)) {
187
+ continue;
188
+ }
189
+ if (executableResponds(exe, ["--version"])) {
190
+ return exe;
191
+ }
192
+ }
193
+ for (let i = order.length - 1; i >= 0; i--) {
194
+ const exe = order[i];
195
+ if (executableResponds(exe, ["--version"])) {
196
+ return exe;
197
+ }
198
+ }
199
+ return order[order.length - 1] || cmd;
200
+ }
201
+
114
202
  function cmdExists(cmd) {
115
203
  const isWin = process.platform === "win32";
116
204
  const which = isWin ? "where" : "which";
117
- const r = spawnSync(which, [cmd], { encoding: "utf8" });
205
+ const r = spawnSync(which, [cmd], { encoding: "utf8", windowsHide: isWin });
118
206
  return r.status === 0;
119
207
  }
120
208
 
121
209
  function runDoctor() {
122
210
  const ok = [];
123
211
  const bad = [];
124
- if (cmdExists("bun")) ok.push("bun");
125
- else bad.push("bun (https://bun.sh)");
212
+ if (cmdExists("node")) ok.push("node");
213
+ else bad.push("node (https://nodejs.org/)");
214
+ if (cmdExists("npm")) ok.push("npm");
215
+ else bad.push("npm (ships with Node.js)");
126
216
  if (cmdExists("uv")) ok.push("uv");
127
217
  else bad.push("uv (https://docs.astral.sh/uv/)");
128
218
  if (cmdExists("python") || cmdExists("python3")) ok.push("python");
@@ -136,6 +226,9 @@ function runDoctor() {
136
226
  return;
137
227
  }
138
228
  console.log("\nAll common toolchain binaries are on PATH.");
229
+ console.log(
230
+ "\nThe gateway runs on **Node** (tsx + better-sqlite3). Bun is optional for monorepo contributors only.",
231
+ );
139
232
  }
140
233
 
141
234
  async function promptDefaults(rl, defaults) {
@@ -264,29 +357,86 @@ BACKEND_GATEWAY_SECRET=${backendGatewaySecret}
264
357
  }
265
358
 
266
359
  function envFileLooksConfigured(stackRoot) {
267
- const g = path.join(stackRoot, "gateway", ".env");
268
- if (fs.existsSync(g)) {
269
- const t = fs.readFileSync(g, "utf8");
270
- if (/BETTER_AUTH_SECRET=\S+/.test(t) || /INTEGRATIONS_ENCRYPTION_KEY=\S+/.test(t)) {
271
- return true;
360
+ try {
361
+ const g = path.join(stackRoot, "gateway", ".env");
362
+ if (fs.existsSync(g)) {
363
+ const t = fs.readFileSync(g, "utf8");
364
+ if (
365
+ /^BETTER_AUTH_SECRET=./m.test(t) ||
366
+ /^INTEGRATIONS_ENCRYPTION_KEY=./m.test(t)
367
+ ) {
368
+ return true;
369
+ }
272
370
  }
371
+ return hasExistingSecrets(stackRoot);
372
+ } catch (e) {
373
+ console.error(
374
+ "business-stack: could not read setup state:",
375
+ e instanceof Error ? e.message : e,
376
+ );
377
+ return false;
273
378
  }
274
- return hasExistingSecrets(stackRoot);
275
379
  }
276
380
 
277
- function runCmd(cmd, args, cwd, extraEnv) {
278
- const r = spawnSync(cmd, args, {
381
+ function runCmd(label, cmd, args, cwd, extraEnv) {
382
+ logPhase(`${label}…`);
383
+ const exe = resolveExecutable(cmd);
384
+ if (process.platform === "win32") {
385
+ logPhase(`using ${cmd} → ${exe}`);
386
+ }
387
+ const r = spawnSync(exe, args, {
279
388
  cwd,
280
389
  stdio: "inherit",
281
390
  env: { ...process.env, ...extraEnv },
282
391
  shell: false,
392
+ windowsHide: process.platform === "win32",
283
393
  });
394
+ if (r.error) {
395
+ console.error(`business-stack: ${label} failed:`, r.error.message);
396
+ console.error(` Command: ${exe} ${args.join(" ")}`);
397
+ console.error(` cwd: ${cwd}`);
398
+ process.exit(1);
399
+ }
400
+ if (r.signal) {
401
+ console.error(`business-stack: ${label} killed (${r.signal})`);
402
+ process.exit(1);
403
+ }
284
404
  if (r.status !== 0) {
285
405
  process.exit(r.status ?? 1);
286
406
  }
287
407
  }
288
408
 
289
- function runStart(opts) {
409
+ /**
410
+ * Wait for turbo + servers. Async so Commander keeps the Node event loop alive on Windows
411
+ * until the child exits (avoids exiting immediately with no output).
412
+ */
413
+ function waitForChild(child, label) {
414
+ return new Promise((resolve) => {
415
+ let settled = false;
416
+ const finish = (code) => {
417
+ if (settled) return;
418
+ settled = true;
419
+ resolve(code ?? 0);
420
+ };
421
+
422
+ child.on("error", (err) => {
423
+ console.error(`business-stack: ${label} — failed to spawn process:`, err.message);
424
+ console.error(" Run: business-stack doctor");
425
+ finish(1);
426
+ });
427
+
428
+ child.on("exit", (code, sig) => {
429
+ if (sig) {
430
+ console.error(`business-stack: ${label} — child exited with signal ${sig}`);
431
+ finish(1);
432
+ return;
433
+ }
434
+ finish(code ?? 0);
435
+ });
436
+ });
437
+ }
438
+
439
+ async function runStart(opts) {
290
440
  const stackRoot = getStackRoot();
291
441
  if (!envFileLooksConfigured(stackRoot)) {
292
442
  console.error(
@@ -295,6 +445,10 @@ function runStart(opts) {
295
445
  process.exit(1);
296
446
  }
297
447
 
448
+ logPhase("starting (install → sync → build → migrate → servers)");
449
+ logPhase(`stack root ${stackRoot}`);
450
+ logPhase(`CLI package v${getCliPackageVersion()} — if there is no output below, run: npm i -g business-stack@latest`);
451
+
298
452
  const fromDb = readStackSecretsEnv(stackRoot);
299
453
  const childEnv = { ...process.env };
300
454
  for (const [k, v] of Object.entries(fromDb)) {
@@ -304,43 +458,61 @@ function runStart(opts) {
304
458
  }
305
459
 
306
460
  if (!opts.skipInstall) {
307
- runCmd("bun", ["install"], stackRoot, childEnv);
461
+ runCmd(
462
+ "npm install (workspaces)",
463
+ "npm",
464
+ ["install", "--no-fund", "--no-audit"],
465
+ stackRoot,
466
+ childEnv,
467
+ );
308
468
  }
309
- runCmd("uv", ["sync"], path.join(stackRoot, "backend"), childEnv);
469
+ runCmd("uv sync (backend)", "uv", ["sync"], path.join(stackRoot, "backend"), childEnv);
310
470
  if (!opts.skipBuild) {
311
- runCmd("bun", ["run", "build"], stackRoot, childEnv);
471
+ runCmd("npm run build", "npm", ["run", "build"], stackRoot, childEnv);
312
472
  }
313
473
  if (!opts.skipMigrate) {
314
- runCmd("uv", ["run", "alembic", "upgrade", "head"], path.join(stackRoot, "backend"), childEnv);
474
+ runCmd(
475
+ "alembic upgrade head",
476
+ "uv",
477
+ ["run", "alembic", "upgrade", "head"],
478
+ path.join(stackRoot, "backend"),
479
+ childEnv,
480
+ );
315
481
  }
316
482
 
317
- const child = spawn("bun", ["run", "start"], {
483
+ logPhase("launching production servers (turbo start via npm)");
484
+ const npmExe = resolveExecutable("npm");
485
+ if (process.platform === "win32") {
486
+ logPhase(`using npm → ${npmExe}`);
487
+ }
488
+ const child = spawn(npmExe, ["run", "start"], {
318
489
  cwd: stackRoot,
319
490
  stdio: "inherit",
320
491
  env: childEnv,
321
492
  shell: false,
493
+ windowsHide: process.platform === "win32",
322
494
  });
323
495
 
324
- function shutdown(signal) {
496
+ const shutdown = () => {
325
497
  try {
326
- if (process.platform === "win32") {
498
+ if (process.platform === "win32" && child.pid) {
327
499
  spawnSync("taskkill", ["/PID", String(child.pid), "/T", "/F"], {
328
500
  stdio: "ignore",
501
+ windowsHide: true,
329
502
  });
330
- } else {
331
- child.kill(signal);
503
+ } else if (child.pid) {
504
+ child.kill("SIGINT");
332
505
  }
333
506
  } catch {
334
507
  /* ignore */
335
508
  }
336
- }
509
+ };
337
510
 
338
- process.on("SIGINT", () => shutdown("SIGINT"));
339
- process.on("SIGTERM", () => shutdown("SIGTERM"));
340
- child.on("exit", (code, sig) => {
341
- if (sig) process.exit(1);
342
- process.exit(code ?? 0);
343
- });
511
+ process.once("SIGINT", shutdown);
512
+ process.once("SIGTERM", shutdown);
513
+
514
+ const code = await waitForChild(child, "turbo start");
515
+ process.exit(code);
344
516
  }
345
517
 
346
518
  function runDev() {
@@ -352,17 +524,17 @@ function runDev() {
352
524
  childEnv[k] = String(v);
353
525
  }
354
526
  }
355
- runCmd("bun", ["run", "dev"], stackRoot, childEnv);
527
+ runCmd("npm run dev", "npm", ["run", "dev"], stackRoot, childEnv);
356
528
  }
357
529
 
358
530
  program
359
531
  .name("business-stack")
360
532
  .description("Run the business-stack monorepo (Next + Hono gateway + FastAPI)")
361
- .version("0.1.1");
533
+ .version("0.1.5");
362
534
 
363
535
  program
364
536
  .command("doctor")
365
- .description("Check for bun, uv, and python on PATH")
537
+ .description("Check for node, npm, uv, and python on PATH")
366
538
  .action(runDoctor);
367
539
 
368
540
  program
@@ -382,12 +554,12 @@ program
382
554
  program
383
555
  .command("start")
384
556
  .description("Install deps, build, migrate, run production stack (turbo start)")
385
- .option("--skip-install", "Skip bun install")
557
+ .option("--skip-install", "Skip npm install")
386
558
  .option("--skip-build", "Skip turbo build")
387
559
  .option("--skip-migrate", "Skip alembic upgrade")
388
- .action((o) => {
560
+ .action(async (o) => {
389
561
  try {
390
- runStart(o);
562
+ await runStart(o);
391
563
  } catch (e) {
392
564
  console.error(e instanceof Error ? e.message : e);
393
565
  process.exit(1);
package/gateway/README.md CHANGED
@@ -1,13 +1,23 @@
1
- To install dependencies:
1
+ Install dependencies from the **repo root** (workspaces) or in this folder:
2
+
2
3
  ```sh
3
- bun install
4
+ npm install
4
5
  ```
5
6
 
6
- To run:
7
+ Run (development with reload):
8
+
7
9
  ```sh
8
- bun run dev
10
+ npm run dev
11
+ ```
12
+
13
+ Production-style (no watch):
14
+
15
+ ```sh
16
+ npm run start
9
17
  ```
10
18
 
11
19
  The gateway listens on **port 3001** by default (`PORT`). Open `http://127.0.0.1:3001` (or set `PORT`).
12
20
 
21
+ Stack: **Hono**, **Node** via **tsx**, **better-sqlite3** for auth + integration settings, **Better Auth**.
22
+
13
23
  Better Auth needs a public **base URL** (where `/api/auth` is reached in the browser). With the Next.js app proxying auth, set `BETTER_AUTH_URL` to that origin (e.g. `http://localhost:3000`). See `.env.example`. If unset, the gateway defaults to `http://localhost:3000`.
@@ -1,24 +1,27 @@
1
1
  {
2
2
  "name": "@business-stack/gateway",
3
3
  "private": true,
4
- "packageManager": "bun@1.3.1",
5
4
  "scripts": {
6
- "dev": "bun run --hot src/index.ts",
7
- "start": "bun run src/index.ts",
8
- "migrate": "bun x @better-auth/cli@latest migrate --yes",
9
- "build": "bun -e \"require('fs').mkdirSync('dist',{recursive:true}); require('fs').writeFileSync('dist/.buildstamp','')\"",
5
+ "dev": "tsx watch src/index.ts",
6
+ "start": "tsx src/index.ts",
7
+ "migrate": "npx @better-auth/cli@latest migrate --yes",
8
+ "build": "node -e \"require('fs').mkdirSync('dist',{recursive:true}); require('fs').writeFileSync('dist/.buildstamp','')\"",
10
9
  "lint": "biome check .",
11
10
  "lint:fix": "biome check --write .",
12
11
  "typecheck": "tsc --noEmit",
13
- "test": "bun -e \"process.exit(0)\"",
14
- "clean": "bun x rimraf@6 dist"
12
+ "test": "node -e \"process.exit(0)\"",
13
+ "clean": "npx rimraf@6 dist"
15
14
  },
16
15
  "dependencies": {
16
+ "@hono/node-server": "^1.19.9",
17
17
  "better-auth": "1.5.6",
18
- "hono": "^4.12.10"
18
+ "better-sqlite3": "^11.7.0",
19
+ "hono": "^4.12.10",
20
+ "tsx": "^4.19.3"
19
21
  },
20
22
  "devDependencies": {
21
- "@types/bun": "latest",
23
+ "@types/better-sqlite3": "^7.6.12",
24
+ "@types/node": "^20",
22
25
  "typescript": "^5.8.3"
23
26
  }
24
27
  }
@@ -1,11 +1,11 @@
1
- import { Database } from "bun:sqlite";
2
1
  import { betterAuth } from "better-auth";
2
+ import Database from "better-sqlite3";
3
3
  import { loadStackSecretsIntoEnv } from "./stack-secrets";
4
4
 
5
5
  loadStackSecretsIntoEnv();
6
6
 
7
7
  const dbPath = process.env.BETTER_AUTH_DATABASE_PATH ?? "auth.sqlite";
8
- const sqlite = new Database(dbPath, { create: true });
8
+ const sqlite = new Database(dbPath);
9
9
 
10
10
  function parseTrustedOrigins(): string[] {
11
11
  const raw = process.env.BETTER_AUTH_TRUSTED_ORIGINS;
@@ -1,3 +1,4 @@
1
+ import { serve } from "@hono/node-server";
1
2
  import { Hono } from "hono";
2
3
  import { cors } from "hono/cors";
3
4
  import { proxy } from "hono/proxy";
@@ -130,12 +131,14 @@ app.get("/session", (c) => {
130
131
  });
131
132
 
132
133
  const port = Number(process.env.PORT ?? 3001);
134
+ const hostname = process.env.HOST?.trim() || "127.0.0.1";
133
135
 
134
- export default {
135
- port,
136
+ serve({
136
137
  fetch: app.fetch,
137
- };
138
+ port,
139
+ hostname,
140
+ });
138
141
 
139
142
  console.log(
140
- `Gateway listening on http://localhost:${port} (backend ${backendOrigin}, prefix ${apiGatewayPrefix})`,
143
+ `Gateway listening on http://${hostname}:${port} (backend ${backendOrigin}, prefix ${apiGatewayPrefix})`,
141
144
  );
@@ -1,15 +1,15 @@
1
- import { Database } from "bun:sqlite";
1
+ import Database from "better-sqlite3";
2
2
  import { decryptIntegrationValue, encryptIntegrationValue } from "./crypto";
3
3
  import { INTEGRATION_DB_KEYS, type IntegrationDbKey } from "./keys";
4
4
 
5
5
  const dbPath = process.env.BETTER_AUTH_DATABASE_PATH ?? "auth.sqlite";
6
6
 
7
- let _db: Database | null = null;
7
+ let _db: Database.Database | null = null;
8
8
 
9
- function getDb(): Database {
9
+ function getDb(): Database.Database {
10
10
  if (!_db) {
11
- _db = new Database(dbPath, { create: true });
12
- _db.run(`
11
+ _db = new Database(dbPath);
12
+ _db.exec(`
13
13
  CREATE TABLE IF NOT EXISTS integration_settings (
14
14
  key TEXT PRIMARY KEY NOT NULL,
15
15
  ciphertext TEXT NOT NULL,
@@ -22,8 +22,8 @@ function getDb(): Database {
22
22
 
23
23
  export function getEncryptedRow(key: IntegrationDbKey): string | null {
24
24
  const row = getDb()
25
- .query("SELECT ciphertext FROM integration_settings WHERE key = ?")
26
- .get(key) as { ciphertext: string } | null;
25
+ .prepare("SELECT ciphertext FROM integration_settings WHERE key = ?")
26
+ .get(key) as { ciphertext: string } | undefined;
27
27
  return row?.ciphertext ?? null;
28
28
  }
29
29
 
@@ -33,16 +33,17 @@ export function setEncryptedRow(
33
33
  ): void {
34
34
  const ciphertext = encryptIntegrationValue(plaintext);
35
35
  const updatedAt = new Date().toISOString();
36
- getDb().run(
37
- `INSERT INTO integration_settings (key, ciphertext, updated_at)
38
- VALUES (?, ?, ?)
39
- ON CONFLICT(key) DO UPDATE SET ciphertext = excluded.ciphertext, updated_at = excluded.updated_at`,
40
- [key, ciphertext, updatedAt],
41
- );
36
+ getDb()
37
+ .prepare(
38
+ `INSERT INTO integration_settings (key, ciphertext, updated_at)
39
+ VALUES (?, ?, ?)
40
+ ON CONFLICT(key) DO UPDATE SET ciphertext = excluded.ciphertext, updated_at = excluded.updated_at`,
41
+ )
42
+ .run(key, ciphertext, updatedAt);
42
43
  }
43
44
 
44
45
  export function deleteRow(key: IntegrationDbKey): void {
45
- getDb().run("DELETE FROM integration_settings WHERE key = ?", [key]);
46
+ getDb().prepare("DELETE FROM integration_settings WHERE key = ?").run(key);
46
47
  }
47
48
 
48
49
  export function getPlaintext(key: IntegrationDbKey): string | null {
@@ -1,4 +1,4 @@
1
- import { Database } from "bun:sqlite";
1
+ import Database from "better-sqlite3";
2
2
 
3
3
  /**
4
4
  * If an env var is unset or whitespace-only, fill it from `stack_secrets` in the auth DB.
@@ -6,20 +6,20 @@ import { Database } from "bun:sqlite";
6
6
  */
7
7
  export function loadStackSecretsIntoEnv(): void {
8
8
  const dbPath = process.env.BETTER_AUTH_DATABASE_PATH ?? "auth.sqlite";
9
- let db: Database;
9
+ let db: Database.Database;
10
10
  try {
11
- db = new Database(dbPath, { create: true });
11
+ db = new Database(dbPath);
12
12
  } catch {
13
13
  return;
14
14
  }
15
15
  try {
16
- db.run(`
16
+ db.exec(`
17
17
  CREATE TABLE IF NOT EXISTS stack_secrets (
18
18
  key TEXT PRIMARY KEY NOT NULL,
19
19
  value TEXT NOT NULL
20
20
  )
21
21
  `);
22
- const rows = db.query("SELECT key, value FROM stack_secrets").all() as {
22
+ const rows = db.prepare("SELECT key, value FROM stack_secrets").all() as {
23
23
  key: string;
24
24
  value: string;
25
25
  }[];
@@ -5,7 +5,7 @@
5
5
  "moduleResolution": "bundler",
6
6
  "target": "ES2022",
7
7
  "lib": ["ES2022"],
8
- "types": ["bun-types"],
8
+ "types": ["node"],
9
9
  "skipLibCheck": true,
10
10
  "noEmit": true
11
11
  },
package/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "business-stack",
3
- "version": "0.1.1",
3
+ "version": "0.1.5",
4
4
  "description": "Next.js + Hono gateway + FastAPI monorepo",
5
5
  "license": "UNLICENSED",
6
- "packageManager": "bun@1.3.1",
7
6
  "workspaces": ["frontend/web", "gateway", "backend"],
8
7
  "scripts": {
9
8
  "prepublishOnly": "node ../scripts/sync-npm-package.cjs",