silosdk 0.0.0 → 0.0.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 (85) hide show
  1. package/README.md +3 -1
  2. package/dist/_virtual/rolldown_runtime.cjs +29 -0
  3. package/dist/cli/d1.cjs +93 -0
  4. package/dist/cli/d1.mjs +92 -0
  5. package/dist/cli/index.cjs +93 -0
  6. package/dist/cli/index.d.cts +1 -0
  7. package/dist/cli/index.d.mts +1 -0
  8. package/dist/cli/index.mjs +94 -0
  9. package/dist/cli/init.cjs +134 -0
  10. package/dist/cli/init.mjs +133 -0
  11. package/dist/cli/kv.cjs +63 -0
  12. package/dist/cli/kv.mjs +60 -0
  13. package/dist/cli/r2.cjs +83 -0
  14. package/dist/cli/r2.mjs +82 -0
  15. package/dist/cli/wrangler.cjs +93 -0
  16. package/dist/cli/wrangler.mjs +89 -0
  17. package/dist/local/adapters/cloudflare.cjs +200 -0
  18. package/dist/local/adapters/cloudflare.d.cts +50 -0
  19. package/dist/local/adapters/cloudflare.d.mts +50 -0
  20. package/dist/local/adapters/cloudflare.mjs +200 -0
  21. package/dist/local/auth-context.cjs +14 -0
  22. package/dist/local/auth-context.d.cts +7 -0
  23. package/dist/local/auth-context.d.mts +7 -0
  24. package/dist/local/auth-context.mjs +12 -0
  25. package/dist/local/auth.cjs +109 -0
  26. package/dist/local/auth.d.cts +26 -0
  27. package/dist/local/auth.d.mts +26 -0
  28. package/dist/local/auth.mjs +99 -0
  29. package/dist/local/commit.cjs +350 -0
  30. package/dist/local/commit.d.cts +59 -0
  31. package/dist/local/commit.d.mts +59 -0
  32. package/dist/local/commit.mjs +349 -0
  33. package/dist/local/config.cjs +17 -0
  34. package/dist/local/config.mjs +15 -0
  35. package/dist/local/index.cjs +16 -0
  36. package/dist/local/index.d.cts +10 -0
  37. package/dist/local/index.d.mts +10 -0
  38. package/dist/local/index.mjs +9 -0
  39. package/dist/local/provider.cjs +204 -0
  40. package/dist/local/provider.d.cts +25 -0
  41. package/dist/local/provider.d.mts +25 -0
  42. package/dist/local/provider.mjs +203 -0
  43. package/dist/local/query-store.cjs +276 -0
  44. package/dist/local/query-store.mjs +274 -0
  45. package/dist/local/storage.cjs +71 -0
  46. package/dist/local/storage.d.cts +7 -0
  47. package/dist/local/storage.d.mts +7 -0
  48. package/dist/local/storage.mjs +68 -0
  49. package/dist/local/sync.cjs +124 -0
  50. package/dist/local/sync.d.cts +36 -0
  51. package/dist/local/sync.d.mts +36 -0
  52. package/dist/local/sync.mjs +122 -0
  53. package/dist/local/view.cjs +257 -0
  54. package/dist/local/view.d.cts +24 -0
  55. package/dist/local/view.d.mts +24 -0
  56. package/dist/local/view.mjs +254 -0
  57. package/dist/package.cjs +11 -0
  58. package/dist/package.mjs +5 -0
  59. package/dist/schema/index.cjs +276 -0
  60. package/dist/schema/index.d.cts +207 -0
  61. package/dist/schema/index.d.mts +207 -0
  62. package/dist/schema/index.mjs +265 -0
  63. package/dist/server/auth.cjs +132 -0
  64. package/dist/server/auth.d.cts +49 -0
  65. package/dist/server/auth.d.mts +49 -0
  66. package/dist/server/auth.mjs +122 -0
  67. package/dist/server/d1.cjs +120 -0
  68. package/dist/server/d1.mjs +116 -0
  69. package/dist/server/do.cjs +132 -0
  70. package/dist/server/do.d.cts +21 -0
  71. package/dist/server/do.d.mts +21 -0
  72. package/dist/server/do.mjs +131 -0
  73. package/dist/server/index.cjs +355 -0
  74. package/dist/server/index.d.cts +65 -0
  75. package/dist/server/index.d.mts +65 -0
  76. package/dist/server/index.mjs +348 -0
  77. package/dist/server/protect.cjs +34 -0
  78. package/dist/server/protect.d.cts +32 -0
  79. package/dist/server/protect.d.mts +32 -0
  80. package/dist/server/protect.mjs +33 -0
  81. package/dist/server/r2.cjs +58 -0
  82. package/dist/server/r2.d.cts +4 -0
  83. package/dist/server/r2.d.mts +4 -0
  84. package/dist/server/r2.mjs +53 -0
  85. package/package.json +55 -2
package/README.md CHANGED
@@ -1 +1,3 @@
1
- # silosdk
1
+ # Silo
2
+
3
+ Type-safe reactive data for React Native and The Edge.
@@ -0,0 +1,29 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+
27
+ //#endregion
28
+
29
+ exports.__toESM = __toESM;
@@ -0,0 +1,93 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_wrangler = require('./wrangler.cjs');
3
+ let node_fs = require("node:fs");
4
+ let node_path = require("node:path");
5
+
6
+ //#region src/cli/d1.ts
7
+ /**
8
+ * Entry point for `silo d1 <subcommand> [args]`
9
+ * Currently handles: create
10
+ * Supports fallback: --id <uuid>
11
+ */
12
+ async function runD1(args) {
13
+ const idFlagIndex = args.indexOf("--id");
14
+ if (idFlagIndex !== -1) {
15
+ const uuid = args[idFlagIndex + 1];
16
+ if (!uuid) {
17
+ console.error("Error: --id requires a UUID argument");
18
+ process.exit(1);
19
+ }
20
+ await patchWranglerWithId(uuid);
21
+ return;
22
+ }
23
+ await d1Create();
24
+ }
25
+ async function d1Create() {
26
+ const wranglerPath = (0, node_path.resolve)(require_wrangler.siloDir(), "wrangler.jsonc");
27
+ let wranglerSource;
28
+ try {
29
+ wranglerSource = (0, node_fs.readFileSync)(wranglerPath, "utf8");
30
+ } catch {
31
+ console.error("Error: silo/wrangler.jsonc not found. Run `silo init` first.");
32
+ process.exit(1);
33
+ }
34
+ const dbName = extractDatabaseName(wranglerSource);
35
+ if (!dbName) {
36
+ console.error("Error: Could not find database_name in silo/wrangler.jsonc.");
37
+ process.exit(1);
38
+ }
39
+ console.log(`Creating D1 database: ${dbName} ...`);
40
+ const { stdout, code } = await require_wrangler.runWranglerCaptured([
41
+ "d1",
42
+ "create",
43
+ dbName
44
+ ]);
45
+ if (code !== 0) {
46
+ console.error("wrangler d1 create failed.");
47
+ process.exit(1);
48
+ }
49
+ const match = stdout.match(/database_id\s*=\s*"([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"/i);
50
+ if (!match) {
51
+ console.log("\nRaw wrangler output:\n");
52
+ console.log(stdout);
53
+ console.error("\nCould not parse database_id from wrangler output.");
54
+ console.error("To patch manually, run: silo d1 create --id <uuid>");
55
+ process.exit(1);
56
+ }
57
+ const uuid = match[1];
58
+ await patchWranglerWithId(uuid);
59
+ }
60
+ async function patchWranglerWithId(uuid) {
61
+ const wranglerPath = (0, node_path.resolve)(require_wrangler.siloDir(), "wrangler.jsonc");
62
+ let source;
63
+ try {
64
+ source = (0, node_fs.readFileSync)(wranglerPath, "utf8");
65
+ } catch {
66
+ console.error("Error: silo/wrangler.jsonc not found. Run `silo init` first.");
67
+ process.exit(1);
68
+ }
69
+ const placeholder = "TODO: run `silo d1 create` and paste the id here";
70
+ if (!source.includes(placeholder)) {
71
+ console.error(`Error: Could not find the placeholder "${placeholder}" in silo/wrangler.jsonc.`);
72
+ console.error("Has database_id already been set?");
73
+ process.exit(1);
74
+ }
75
+ (0, node_fs.writeFileSync)(wranglerPath, source.replace(placeholder, uuid), "utf8");
76
+ console.log(`Patched silo/wrangler.jsonc with database_id = "${uuid}"`);
77
+ }
78
+ /**
79
+ * Strips single-line // comments and extracts database_name from wrangler.jsonc.
80
+ * Uses a regex rather than a full JSONC parser to avoid a dependency.
81
+ */
82
+ function extractDatabaseName(source) {
83
+ const stripped = source.replace(/\/\/[^\n]*/g, "");
84
+ try {
85
+ const db = JSON.parse(stripped)?.d1_databases?.[0];
86
+ return typeof db?.database_name === "string" ? db.database_name : null;
87
+ } catch {
88
+ return source.match(/"database_name"\s*:\s*"([^"]+)"/)?.[1] ?? null;
89
+ }
90
+ }
91
+
92
+ //#endregion
93
+ exports.runD1 = runD1;
@@ -0,0 +1,92 @@
1
+ import { runWranglerCaptured, siloDir } from "./wrangler.mjs";
2
+ import { readFileSync, writeFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+
5
+ //#region src/cli/d1.ts
6
+ /**
7
+ * Entry point for `silo d1 <subcommand> [args]`
8
+ * Currently handles: create
9
+ * Supports fallback: --id <uuid>
10
+ */
11
+ async function runD1(args) {
12
+ const idFlagIndex = args.indexOf("--id");
13
+ if (idFlagIndex !== -1) {
14
+ const uuid = args[idFlagIndex + 1];
15
+ if (!uuid) {
16
+ console.error("Error: --id requires a UUID argument");
17
+ process.exit(1);
18
+ }
19
+ await patchWranglerWithId(uuid);
20
+ return;
21
+ }
22
+ await d1Create();
23
+ }
24
+ async function d1Create() {
25
+ const wranglerPath = resolve(siloDir(), "wrangler.jsonc");
26
+ let wranglerSource;
27
+ try {
28
+ wranglerSource = readFileSync(wranglerPath, "utf8");
29
+ } catch {
30
+ console.error("Error: silo/wrangler.jsonc not found. Run `silo init` first.");
31
+ process.exit(1);
32
+ }
33
+ const dbName = extractDatabaseName(wranglerSource);
34
+ if (!dbName) {
35
+ console.error("Error: Could not find database_name in silo/wrangler.jsonc.");
36
+ process.exit(1);
37
+ }
38
+ console.log(`Creating D1 database: ${dbName} ...`);
39
+ const { stdout, code } = await runWranglerCaptured([
40
+ "d1",
41
+ "create",
42
+ dbName
43
+ ]);
44
+ if (code !== 0) {
45
+ console.error("wrangler d1 create failed.");
46
+ process.exit(1);
47
+ }
48
+ const match = stdout.match(/database_id\s*=\s*"([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"/i);
49
+ if (!match) {
50
+ console.log("\nRaw wrangler output:\n");
51
+ console.log(stdout);
52
+ console.error("\nCould not parse database_id from wrangler output.");
53
+ console.error("To patch manually, run: silo d1 create --id <uuid>");
54
+ process.exit(1);
55
+ }
56
+ const uuid = match[1];
57
+ await patchWranglerWithId(uuid);
58
+ }
59
+ async function patchWranglerWithId(uuid) {
60
+ const wranglerPath = resolve(siloDir(), "wrangler.jsonc");
61
+ let source;
62
+ try {
63
+ source = readFileSync(wranglerPath, "utf8");
64
+ } catch {
65
+ console.error("Error: silo/wrangler.jsonc not found. Run `silo init` first.");
66
+ process.exit(1);
67
+ }
68
+ const placeholder = "TODO: run `silo d1 create` and paste the id here";
69
+ if (!source.includes(placeholder)) {
70
+ console.error(`Error: Could not find the placeholder "${placeholder}" in silo/wrangler.jsonc.`);
71
+ console.error("Has database_id already been set?");
72
+ process.exit(1);
73
+ }
74
+ writeFileSync(wranglerPath, source.replace(placeholder, uuid), "utf8");
75
+ console.log(`Patched silo/wrangler.jsonc with database_id = "${uuid}"`);
76
+ }
77
+ /**
78
+ * Strips single-line // comments and extracts database_name from wrangler.jsonc.
79
+ * Uses a regex rather than a full JSONC parser to avoid a dependency.
80
+ */
81
+ function extractDatabaseName(source) {
82
+ const stripped = source.replace(/\/\/[^\n]*/g, "");
83
+ try {
84
+ const db = JSON.parse(stripped)?.d1_databases?.[0];
85
+ return typeof db?.database_name === "string" ? db.database_name : null;
86
+ } catch {
87
+ return source.match(/"database_name"\s*:\s*"([^"]+)"/)?.[1] ?? null;
88
+ }
89
+ }
90
+
91
+ //#endregion
92
+ export { runD1 };
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ const require_wrangler = require('./wrangler.cjs');
3
+ const require_init = require('./init.cjs');
4
+ const require_d1 = require('./d1.cjs');
5
+ const require_kv = require('./kv.cjs');
6
+ const require_r2 = require('./r2.cjs');
7
+
8
+ //#region src/cli/index.ts
9
+ const [, , command, ...args] = process.argv;
10
+ function usage() {
11
+ console.log(`Usage: silo <command>
12
+
13
+ Commands:
14
+ init Scaffold silo/ directory into the current project
15
+ dev Start Cloudflare Worker in dev mode (wrangler dev)
16
+ deploy Deploy Cloudflare Worker (wrangler deploy)
17
+ logs Tail live Worker logs (wrangler tail)
18
+ d1 create Create D1 database and patch wrangler.jsonc
19
+ kv create Create SILO_SESSIONS KV namespace and patch wrangler.jsonc
20
+ kv create --id Manually patch wrangler.jsonc with an existing KV namespace id
21
+ r2 create Create R2 bucket and patch wrangler.jsonc
22
+ r2 create --name Manually patch wrangler.jsonc with an existing bucket name
23
+ secret put <key> Set a wrangler secret (e.g. RESEND_API_KEY)
24
+ `);
25
+ }
26
+ async function main() {
27
+ switch (command) {
28
+ case "init":
29
+ await require_init.runInit();
30
+ break;
31
+ case "dev":
32
+ await require_wrangler.runWrangler(["dev", ...args]);
33
+ break;
34
+ case "deploy":
35
+ await require_wrangler.runWrangler(["deploy", ...args]);
36
+ break;
37
+ case "logs":
38
+ await require_wrangler.runWrangler(["tail", ...args]);
39
+ break;
40
+ case "d1": {
41
+ const subcommand = args[0];
42
+ if (subcommand === "create") await require_d1.runD1(args.slice(1));
43
+ else {
44
+ console.error(`Unknown d1 subcommand: ${subcommand ?? "(none)"}`);
45
+ console.error("Available: silo d1 create");
46
+ process.exit(1);
47
+ }
48
+ break;
49
+ }
50
+ case "kv": {
51
+ const subcommand = args[0];
52
+ if (subcommand === "create") {
53
+ const idFlag = args.indexOf("--id");
54
+ if (idFlag !== -1 && args[idFlag + 1]) require_kv.runKvPatch(args[idFlag + 1]);
55
+ else await require_kv.runKvCreate();
56
+ } else {
57
+ console.error(`Unknown kv subcommand: ${subcommand ?? "(none)"}`);
58
+ console.error("Available: silo kv create [--id <namespace-id>]");
59
+ process.exit(1);
60
+ }
61
+ break;
62
+ }
63
+ case "r2": {
64
+ const subcommand = args[0];
65
+ if (subcommand === "create") await require_r2.runR2(args.slice(1));
66
+ else {
67
+ console.error(`Unknown r2 subcommand: ${subcommand ?? "(none)"}`);
68
+ console.error("Available: silo r2 create [--name <bucket-name>]");
69
+ process.exit(1);
70
+ }
71
+ break;
72
+ }
73
+ case "secret":
74
+ if (args[0] === "put" && args[1]) await require_kv.runSecretPut(args[1]);
75
+ else {
76
+ console.error("Usage: silo secret put <KEY>");
77
+ process.exit(1);
78
+ }
79
+ break;
80
+ default:
81
+ usage();
82
+ if (command) {
83
+ console.error(`Unknown command: ${command}`);
84
+ process.exit(1);
85
+ }
86
+ }
87
+ }
88
+ main().catch((err) => {
89
+ console.error(err instanceof Error ? err.message : String(err));
90
+ process.exit(1);
91
+ });
92
+
93
+ //#endregion
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+ import { runWrangler } from "./wrangler.mjs";
3
+ import { runInit } from "./init.mjs";
4
+ import { runD1 } from "./d1.mjs";
5
+ import { runKvCreate, runKvPatch, runSecretPut } from "./kv.mjs";
6
+ import { runR2 } from "./r2.mjs";
7
+
8
+ //#region src/cli/index.ts
9
+ const [, , command, ...args] = process.argv;
10
+ function usage() {
11
+ console.log(`Usage: silo <command>
12
+
13
+ Commands:
14
+ init Scaffold silo/ directory into the current project
15
+ dev Start Cloudflare Worker in dev mode (wrangler dev)
16
+ deploy Deploy Cloudflare Worker (wrangler deploy)
17
+ logs Tail live Worker logs (wrangler tail)
18
+ d1 create Create D1 database and patch wrangler.jsonc
19
+ kv create Create SILO_SESSIONS KV namespace and patch wrangler.jsonc
20
+ kv create --id Manually patch wrangler.jsonc with an existing KV namespace id
21
+ r2 create Create R2 bucket and patch wrangler.jsonc
22
+ r2 create --name Manually patch wrangler.jsonc with an existing bucket name
23
+ secret put <key> Set a wrangler secret (e.g. RESEND_API_KEY)
24
+ `);
25
+ }
26
+ async function main() {
27
+ switch (command) {
28
+ case "init":
29
+ await runInit();
30
+ break;
31
+ case "dev":
32
+ await runWrangler(["dev", ...args]);
33
+ break;
34
+ case "deploy":
35
+ await runWrangler(["deploy", ...args]);
36
+ break;
37
+ case "logs":
38
+ await runWrangler(["tail", ...args]);
39
+ break;
40
+ case "d1": {
41
+ const subcommand = args[0];
42
+ if (subcommand === "create") await runD1(args.slice(1));
43
+ else {
44
+ console.error(`Unknown d1 subcommand: ${subcommand ?? "(none)"}`);
45
+ console.error("Available: silo d1 create");
46
+ process.exit(1);
47
+ }
48
+ break;
49
+ }
50
+ case "kv": {
51
+ const subcommand = args[0];
52
+ if (subcommand === "create") {
53
+ const idFlag = args.indexOf("--id");
54
+ if (idFlag !== -1 && args[idFlag + 1]) runKvPatch(args[idFlag + 1]);
55
+ else await runKvCreate();
56
+ } else {
57
+ console.error(`Unknown kv subcommand: ${subcommand ?? "(none)"}`);
58
+ console.error("Available: silo kv create [--id <namespace-id>]");
59
+ process.exit(1);
60
+ }
61
+ break;
62
+ }
63
+ case "r2": {
64
+ const subcommand = args[0];
65
+ if (subcommand === "create") await runR2(args.slice(1));
66
+ else {
67
+ console.error(`Unknown r2 subcommand: ${subcommand ?? "(none)"}`);
68
+ console.error("Available: silo r2 create [--name <bucket-name>]");
69
+ process.exit(1);
70
+ }
71
+ break;
72
+ }
73
+ case "secret":
74
+ if (args[0] === "put" && args[1]) await runSecretPut(args[1]);
75
+ else {
76
+ console.error("Usage: silo secret put <KEY>");
77
+ process.exit(1);
78
+ }
79
+ break;
80
+ default:
81
+ usage();
82
+ if (command) {
83
+ console.error(`Unknown command: ${command}`);
84
+ process.exit(1);
85
+ }
86
+ }
87
+ }
88
+ main().catch((err) => {
89
+ console.error(err instanceof Error ? err.message : String(err));
90
+ process.exit(1);
91
+ });
92
+
93
+ //#endregion
94
+ export { };
@@ -0,0 +1,134 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_wrangler = require('./wrangler.cjs');
3
+ let node_fs = require("node:fs");
4
+ let node_readline = require("node:readline");
5
+ let node_path = require("node:path");
6
+
7
+ //#region src/cli/init.ts
8
+ function indexTemplate() {
9
+ return `import { createServer, SyncObject } from 'silosdk/server'
10
+ // import { createAuth, otpProvider, customProvider } from 'silosdk/server'
11
+ // TODO: import your view definitions here
12
+ // import { Post, Message } from '../src/schema'
13
+
14
+ export { SyncObject }
15
+
16
+ // Option A — built-in OTP auth
17
+ // const auth = createAuth({
18
+ // providers: [
19
+ // otpProvider({
20
+ // sendOTP: async (to, code) => {
21
+ // // Send \`code\` to \`to\` via any transport (email, SMS, etc.)
22
+ // },
23
+ // }),
24
+ // ],
25
+ // })
26
+
27
+ // Option B — BYO auth (Clerk, Supabase, JWT, etc.)
28
+ // const auth = createAuth({
29
+ // providers: customProvider(async (token) => {
30
+ // // Validate token and return { id } or null
31
+ // return null // TODO: implement
32
+ // }),
33
+ // })
34
+
35
+ export default createServer({
36
+ views: [
37
+ // Post, Message, ...
38
+ ],
39
+ // auth,
40
+ })
41
+ `;
42
+ }
43
+ function wranglerTemplate(serverName, dbName) {
44
+ return `{
45
+ "name": "${serverName}",
46
+ "main": "index.ts",
47
+ "compatibility_date": "2025-01-01",
48
+ "durable_objects": {
49
+ "bindings": [
50
+ { "name": "SILO_SYNC", "class_name": "SyncObject" }
51
+ ]
52
+ },
53
+ "migrations": [
54
+ { "tag": "v1", "new_sqlite_classes": ["SyncObject"] }
55
+ ],
56
+ "d1_databases": [
57
+ {
58
+ "binding": "SILO_DB",
59
+ "database_name": "${dbName}",
60
+ "database_id": "TODO: run \`silo d1 create\` and paste the id here"
61
+ }
62
+ ],
63
+ "kv_namespaces": [
64
+ {
65
+ "binding": "SILO_SESSIONS",
66
+ "id": "TODO: run \`silo kv create\` and paste the id here"
67
+ }
68
+ ],
69
+ "r2_buckets": [
70
+ {
71
+ "binding": "SILO_STORAGE",
72
+ "bucket_name": "TODO: run \`silo r2 create\` and paste the name here"
73
+ }
74
+ ]
75
+ }
76
+ `;
77
+ }
78
+ function prompt(rl, question) {
79
+ return new Promise((resolve$1) => {
80
+ rl.question(question, (answer) => resolve$1(answer.trim()));
81
+ });
82
+ }
83
+ function readPackageName() {
84
+ try {
85
+ const raw = (0, node_fs.readFileSync)((0, node_path.resolve)(require_wrangler.projectRoot(), "package.json"), "utf8");
86
+ const pkg = JSON.parse(raw);
87
+ return typeof pkg.name === "string" && pkg.name ? pkg.name : null;
88
+ } catch {
89
+ return null;
90
+ }
91
+ }
92
+ async function runInit() {
93
+ const defaultServerName = readPackageName() ?? "my-app";
94
+ const rl = (0, node_readline.createInterface)({
95
+ input: process.stdin,
96
+ output: process.stdout
97
+ });
98
+ let serverName;
99
+ let dbName;
100
+ try {
101
+ serverName = await prompt(rl, `Server name [${defaultServerName}]: `) || defaultServerName;
102
+ const defaultDbName = `${serverName}-db`;
103
+ dbName = await prompt(rl, `D1 database name [${defaultDbName}]: `) || defaultDbName;
104
+ } finally {
105
+ rl.close();
106
+ }
107
+ const dir = require_wrangler.siloDir();
108
+ const indexPath = (0, node_path.resolve)(dir, "index.ts");
109
+ const wranglerPath = (0, node_path.resolve)(dir, "wrangler.jsonc");
110
+ if ((0, node_fs.existsSync)(indexPath) || (0, node_fs.existsSync)(wranglerPath)) {
111
+ console.error("Error: silo/ directory already contains files. Remove them first or edit them manually.");
112
+ process.exit(1);
113
+ }
114
+ if (!(0, node_fs.existsSync)(dir)) (0, node_fs.mkdirSync)(dir, { recursive: true });
115
+ (0, node_fs.writeFileSync)(indexPath, indexTemplate(), "utf8");
116
+ (0, node_fs.writeFileSync)(wranglerPath, wranglerTemplate(serverName, dbName), "utf8");
117
+ console.log(`
118
+ Scaffolded silo/:
119
+ silo/index.ts — server entry point
120
+ silo/wrangler.jsonc — Cloudflare config
121
+
122
+ Next steps:
123
+ 1. Import your views in silo/index.ts and configure auth
124
+ (built-in OTP via createAuth, or BYO via customProvider)
125
+ 2. Run \`silo d1 create\` to create the D1 database and patch wrangler.jsonc
126
+ 3. Run \`silo kv create\` to create the SILO_SESSIONS KV namespace
127
+ 4. Run \`silo r2 create\` to create the SILO_STORAGE R2 bucket
128
+ 5. Run \`silo dev\` to start the Worker locally
129
+ 6. Run \`silo deploy\` to deploy to Cloudflare
130
+ `);
131
+ }
132
+
133
+ //#endregion
134
+ exports.runInit = runInit;
@@ -0,0 +1,133 @@
1
+ import { projectRoot, siloDir } from "./wrangler.mjs";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { createInterface } from "node:readline";
4
+ import { resolve } from "node:path";
5
+
6
+ //#region src/cli/init.ts
7
+ function indexTemplate() {
8
+ return `import { createServer, SyncObject } from 'silosdk/server'
9
+ // import { createAuth, otpProvider, customProvider } from 'silosdk/server'
10
+ // TODO: import your view definitions here
11
+ // import { Post, Message } from '../src/schema'
12
+
13
+ export { SyncObject }
14
+
15
+ // Option A — built-in OTP auth
16
+ // const auth = createAuth({
17
+ // providers: [
18
+ // otpProvider({
19
+ // sendOTP: async (to, code) => {
20
+ // // Send \`code\` to \`to\` via any transport (email, SMS, etc.)
21
+ // },
22
+ // }),
23
+ // ],
24
+ // })
25
+
26
+ // Option B — BYO auth (Clerk, Supabase, JWT, etc.)
27
+ // const auth = createAuth({
28
+ // providers: customProvider(async (token) => {
29
+ // // Validate token and return { id } or null
30
+ // return null // TODO: implement
31
+ // }),
32
+ // })
33
+
34
+ export default createServer({
35
+ views: [
36
+ // Post, Message, ...
37
+ ],
38
+ // auth,
39
+ })
40
+ `;
41
+ }
42
+ function wranglerTemplate(serverName, dbName) {
43
+ return `{
44
+ "name": "${serverName}",
45
+ "main": "index.ts",
46
+ "compatibility_date": "2025-01-01",
47
+ "durable_objects": {
48
+ "bindings": [
49
+ { "name": "SILO_SYNC", "class_name": "SyncObject" }
50
+ ]
51
+ },
52
+ "migrations": [
53
+ { "tag": "v1", "new_sqlite_classes": ["SyncObject"] }
54
+ ],
55
+ "d1_databases": [
56
+ {
57
+ "binding": "SILO_DB",
58
+ "database_name": "${dbName}",
59
+ "database_id": "TODO: run \`silo d1 create\` and paste the id here"
60
+ }
61
+ ],
62
+ "kv_namespaces": [
63
+ {
64
+ "binding": "SILO_SESSIONS",
65
+ "id": "TODO: run \`silo kv create\` and paste the id here"
66
+ }
67
+ ],
68
+ "r2_buckets": [
69
+ {
70
+ "binding": "SILO_STORAGE",
71
+ "bucket_name": "TODO: run \`silo r2 create\` and paste the name here"
72
+ }
73
+ ]
74
+ }
75
+ `;
76
+ }
77
+ function prompt(rl, question) {
78
+ return new Promise((resolve$1) => {
79
+ rl.question(question, (answer) => resolve$1(answer.trim()));
80
+ });
81
+ }
82
+ function readPackageName() {
83
+ try {
84
+ const raw = readFileSync(resolve(projectRoot(), "package.json"), "utf8");
85
+ const pkg = JSON.parse(raw);
86
+ return typeof pkg.name === "string" && pkg.name ? pkg.name : null;
87
+ } catch {
88
+ return null;
89
+ }
90
+ }
91
+ async function runInit() {
92
+ const defaultServerName = readPackageName() ?? "my-app";
93
+ const rl = createInterface({
94
+ input: process.stdin,
95
+ output: process.stdout
96
+ });
97
+ let serverName;
98
+ let dbName;
99
+ try {
100
+ serverName = await prompt(rl, `Server name [${defaultServerName}]: `) || defaultServerName;
101
+ const defaultDbName = `${serverName}-db`;
102
+ dbName = await prompt(rl, `D1 database name [${defaultDbName}]: `) || defaultDbName;
103
+ } finally {
104
+ rl.close();
105
+ }
106
+ const dir = siloDir();
107
+ const indexPath = resolve(dir, "index.ts");
108
+ const wranglerPath = resolve(dir, "wrangler.jsonc");
109
+ if (existsSync(indexPath) || existsSync(wranglerPath)) {
110
+ console.error("Error: silo/ directory already contains files. Remove them first or edit them manually.");
111
+ process.exit(1);
112
+ }
113
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
114
+ writeFileSync(indexPath, indexTemplate(), "utf8");
115
+ writeFileSync(wranglerPath, wranglerTemplate(serverName, dbName), "utf8");
116
+ console.log(`
117
+ Scaffolded silo/:
118
+ silo/index.ts — server entry point
119
+ silo/wrangler.jsonc — Cloudflare config
120
+
121
+ Next steps:
122
+ 1. Import your views in silo/index.ts and configure auth
123
+ (built-in OTP via createAuth, or BYO via customProvider)
124
+ 2. Run \`silo d1 create\` to create the D1 database and patch wrangler.jsonc
125
+ 3. Run \`silo kv create\` to create the SILO_SESSIONS KV namespace
126
+ 4. Run \`silo r2 create\` to create the SILO_STORAGE R2 bucket
127
+ 5. Run \`silo dev\` to start the Worker locally
128
+ 6. Run \`silo deploy\` to deploy to Cloudflare
129
+ `);
130
+ }
131
+
132
+ //#endregion
133
+ export { runInit };