@suluk/platform 0.5.0 → 0.5.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/plan.ts +18 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suluk/platform",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "The platform generator (C051): write one `definePlatform` manifest → it plans the shadcn-registry adds, generates the wired Hono entry, and merges each module's provision fragment into a single provision.config. The manifest compiles to a shadcn-add list + a C047 provision.config; the generator runs the adds + `@suluk/provision`. Turns the Suluk backend registry into a one-command platform. CANDIDATE tooling.",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/src/plan.ts CHANGED
@@ -694,24 +694,35 @@ function buildEntry(services: string[], opts?: Record<string, Record<string, unk
694
694
  */
695
695
  function buildDevEntry(services: string[]): string {
696
696
  const usesKv = services.includes("rate-credit");
697
- const kvImport = usesKv ? "jsonFileKvStore, " : "";
697
+ const usesEmail = services.includes("email");
698
+ const usesBilling = services.includes("billing");
699
+ const localImports = ["d1FromSqlite", ...(usesKv ? ["jsonFileKvStore"] : []), ...(usesEmail ? ["jsonFileMailbox"] : []), "applyLocalSchema"];
700
+ const billingImport = usesBilling ? '\nimport { mockStripeFetch } from "@suluk/billing";' : "";
698
701
  const kvBind = usesKv ? "\n RATE_CREDIT_KV: jsonFileKvStore(KV_PATH)," : "";
702
+ const mailboxBind = usesEmail ? "\n SULUK_MAILBOX_SINK: mailbox," : "";
703
+ // mock-until-keyed: only inject the Stripe fake when there is no real key (a provisioned app hits real Stripe).
704
+ const stripeInject = usesBilling
705
+ ? '\nif (!env.STRIPE_SECRET_KEY) { env.STRIPE_SECRET_KEY = "sk_mock_local"; env.STRIPE_FETCH = mockStripeFetch(); }'
706
+ : "";
707
+ const mailboxRoute = usesEmail
708
+ ? '\n// a dev-only inbox view of the emails the mock provider captured (never mounted on the deployed Worker).\napp.get("/api/email/dev/mailbox", async (c) => c.json(await mailbox.list()));\n'
709
+ : "";
699
710
  return `// AUTO-GENERATED by @suluk/platform — the bun MOCK-PROVIDER dev server. Runs the wired app under bun with a
700
711
  // bun:sqlite DB + JSON-file KV, so \`bun run dev\` works with ZERO Cloudflare account and no wrangler. A provider goes REAL
701
712
  // the moment its key is present (mock-until-keyed): add real keys to .env.temp + \`bun run provision\` and this file uses
702
713
  // them. NOTE: src/index.ts (the deployed Worker) imports NONE of these mocks — bun:sqlite never enters the Worker bundle.
703
714
  import { app } from "./index";
704
715
  import { Database } from "bun:sqlite";
705
- import { d1FromSqlite, ${kvImport}applyLocalSchema } from "@suluk/cloudflare/local";
716
+ import { ${localImports.join(", ")} } from "@suluk/cloudflare/local";${billingImport}
706
717
  import { loadEnvFile } from "@suluk/env/node";
707
718
 
708
- const DB_PATH = process.env.SULUK_DB_PATH ?? ".suluk/dev.sqlite";${usesKv ? '\nconst KV_PATH = process.env.SULUK_KV_PATH ?? ".suluk/dev-kv.json";' : ""}
719
+ const DB_PATH = process.env.SULUK_DB_PATH ?? ".suluk/dev.sqlite";${usesKv ? '\nconst KV_PATH = process.env.SULUK_KV_PATH ?? ".suluk/dev-kv.json";' : ""}${usesEmail ? '\nconst MAILBOX_PATH = process.env.SULUK_MAILBOX_PATH ?? ".suluk/dev-mailbox.json";' : ""}
709
720
  const PORT = Number(process.env.PORT ?? 8787);
710
721
 
711
722
  const sqlite = new Database(DB_PATH, { create: true });
712
723
  const tables = await applyLocalSchema(sqlite); // discover src/db/*.ts + create the tables from the drizzle schema
713
724
  console.log(\`[suluk dev] sqlite \${DB_PATH} — \${tables.length} tables\`);
714
-
725
+ ${usesEmail ? "const mailbox = jsonFileMailbox(MAILBOX_PATH); // a local inbox the mock email provider saves to\n" : ""}
715
726
  // Real secrets (if this app has been provisioned): decrypt the committed .env with the local private key. Fresh app / no
716
727
  // key → {} → every provider mocks. Best-effort: a decryption failure never blocks the mock path.
717
728
  let secrets: Record<string, string> = {};
@@ -722,12 +733,12 @@ try { secrets = await loadEnvFile(); } catch {}
722
733
  const env: Record<string, unknown> = {
723
734
  ...process.env,
724
735
  ...secrets,
725
- DB: d1FromSqlite(sqlite),${kvBind}
736
+ DB: d1FromSqlite(sqlite),${kvBind}${mailboxBind}
726
737
  };
727
738
 
728
739
  const mocked = ["GOOGLE_CLIENT_ID", "STRIPE_SECRET_KEY", "RESEND_API_KEY"].filter((k) => !env[k]);
729
- if (mocked.length) console.log(\`[suluk dev] mocked (no key): \${mocked.join(", ")}\`);
730
-
740
+ if (mocked.length) console.log(\`[suluk dev] mocked (no key): \${mocked.join(", ")}\`);${stripeInject}
741
+ ${mailboxRoute}
731
742
  const ctx = { waitUntil() {}, passThroughOnException() {} } as unknown as ExecutionContext;
732
743
  Bun.serve({ port: PORT, idleTimeout: 120, fetch: (req) => app.fetch(req, env as Parameters<typeof app.fetch>[1], ctx) });
733
744
  console.log(\`[suluk dev] → http://localhost:\${PORT} (mock-until-keyed; provision to go live)\`);