@edge-base/cli 0.1.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 (234) hide show
  1. package/README.md +182 -0
  2. package/dist/commands/admin.d.ts +10 -0
  3. package/dist/commands/admin.d.ts.map +1 -0
  4. package/dist/commands/admin.js +307 -0
  5. package/dist/commands/admin.js.map +1 -0
  6. package/dist/commands/backup.d.ts +148 -0
  7. package/dist/commands/backup.d.ts.map +1 -0
  8. package/dist/commands/backup.js +1247 -0
  9. package/dist/commands/backup.js.map +1 -0
  10. package/dist/commands/completion.d.ts +3 -0
  11. package/dist/commands/completion.d.ts.map +1 -0
  12. package/dist/commands/completion.js +168 -0
  13. package/dist/commands/completion.js.map +1 -0
  14. package/dist/commands/create-plugin.d.ts +3 -0
  15. package/dist/commands/create-plugin.d.ts.map +1 -0
  16. package/dist/commands/create-plugin.js +208 -0
  17. package/dist/commands/create-plugin.js.map +1 -0
  18. package/dist/commands/deploy.d.ts +146 -0
  19. package/dist/commands/deploy.d.ts.map +1 -0
  20. package/dist/commands/deploy.js +1823 -0
  21. package/dist/commands/deploy.js.map +1 -0
  22. package/dist/commands/describe.d.ts +45 -0
  23. package/dist/commands/describe.d.ts.map +1 -0
  24. package/dist/commands/describe.js +114 -0
  25. package/dist/commands/describe.js.map +1 -0
  26. package/dist/commands/destroy.d.ts +13 -0
  27. package/dist/commands/destroy.d.ts.map +1 -0
  28. package/dist/commands/destroy.js +642 -0
  29. package/dist/commands/destroy.js.map +1 -0
  30. package/dist/commands/dev.d.ts +80 -0
  31. package/dist/commands/dev.d.ts.map +1 -0
  32. package/dist/commands/dev.js +1131 -0
  33. package/dist/commands/dev.js.map +1 -0
  34. package/dist/commands/docker.d.ts +22 -0
  35. package/dist/commands/docker.d.ts.map +1 -0
  36. package/dist/commands/docker.js +373 -0
  37. package/dist/commands/docker.js.map +1 -0
  38. package/dist/commands/export.d.ts +15 -0
  39. package/dist/commands/export.d.ts.map +1 -0
  40. package/dist/commands/export.js +142 -0
  41. package/dist/commands/export.js.map +1 -0
  42. package/dist/commands/init.d.ts +7 -0
  43. package/dist/commands/init.d.ts.map +1 -0
  44. package/dist/commands/init.js +506 -0
  45. package/dist/commands/init.js.map +1 -0
  46. package/dist/commands/keys.d.ts +23 -0
  47. package/dist/commands/keys.d.ts.map +1 -0
  48. package/dist/commands/keys.js +347 -0
  49. package/dist/commands/keys.js.map +1 -0
  50. package/dist/commands/logs.d.ts +17 -0
  51. package/dist/commands/logs.d.ts.map +1 -0
  52. package/dist/commands/logs.js +104 -0
  53. package/dist/commands/logs.js.map +1 -0
  54. package/dist/commands/migrate.d.ts +29 -0
  55. package/dist/commands/migrate.d.ts.map +1 -0
  56. package/dist/commands/migrate.js +302 -0
  57. package/dist/commands/migrate.js.map +1 -0
  58. package/dist/commands/migration.d.ts +18 -0
  59. package/dist/commands/migration.d.ts.map +1 -0
  60. package/dist/commands/migration.js +114 -0
  61. package/dist/commands/migration.js.map +1 -0
  62. package/dist/commands/neon.d.ts +66 -0
  63. package/dist/commands/neon.d.ts.map +1 -0
  64. package/dist/commands/neon.js +600 -0
  65. package/dist/commands/neon.js.map +1 -0
  66. package/dist/commands/plugins.d.ts +9 -0
  67. package/dist/commands/plugins.d.ts.map +1 -0
  68. package/dist/commands/plugins.js +295 -0
  69. package/dist/commands/plugins.js.map +1 -0
  70. package/dist/commands/realtime.d.ts +3 -0
  71. package/dist/commands/realtime.d.ts.map +1 -0
  72. package/dist/commands/realtime.js +71 -0
  73. package/dist/commands/realtime.js.map +1 -0
  74. package/dist/commands/secret.d.ts +7 -0
  75. package/dist/commands/secret.d.ts.map +1 -0
  76. package/dist/commands/secret.js +180 -0
  77. package/dist/commands/secret.js.map +1 -0
  78. package/dist/commands/seed.d.ts +21 -0
  79. package/dist/commands/seed.d.ts.map +1 -0
  80. package/dist/commands/seed.js +325 -0
  81. package/dist/commands/seed.js.map +1 -0
  82. package/dist/commands/telemetry.d.ts +12 -0
  83. package/dist/commands/telemetry.d.ts.map +1 -0
  84. package/dist/commands/telemetry.js +57 -0
  85. package/dist/commands/telemetry.js.map +1 -0
  86. package/dist/commands/typegen.d.ts +26 -0
  87. package/dist/commands/typegen.d.ts.map +1 -0
  88. package/dist/commands/typegen.js +212 -0
  89. package/dist/commands/typegen.js.map +1 -0
  90. package/dist/commands/upgrade.d.ts +29 -0
  91. package/dist/commands/upgrade.d.ts.map +1 -0
  92. package/dist/commands/upgrade.js +265 -0
  93. package/dist/commands/upgrade.js.map +1 -0
  94. package/dist/commands/webhook-test.d.ts +3 -0
  95. package/dist/commands/webhook-test.d.ts.map +1 -0
  96. package/dist/commands/webhook-test.js +133 -0
  97. package/dist/commands/webhook-test.js.map +1 -0
  98. package/dist/index.d.ts +3 -0
  99. package/dist/index.d.ts.map +1 -0
  100. package/dist/index.js +183 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/lib/agent-contract.d.ts +36 -0
  103. package/dist/lib/agent-contract.d.ts.map +1 -0
  104. package/dist/lib/agent-contract.js +78 -0
  105. package/dist/lib/agent-contract.js.map +1 -0
  106. package/dist/lib/cf-auth.d.ts +76 -0
  107. package/dist/lib/cf-auth.d.ts.map +1 -0
  108. package/dist/lib/cf-auth.js +321 -0
  109. package/dist/lib/cf-auth.js.map +1 -0
  110. package/dist/lib/cli-context.d.ts +23 -0
  111. package/dist/lib/cli-context.d.ts.map +1 -0
  112. package/dist/lib/cli-context.js +40 -0
  113. package/dist/lib/cli-context.js.map +1 -0
  114. package/dist/lib/cloudflare-deploy-manifest.d.ts +26 -0
  115. package/dist/lib/cloudflare-deploy-manifest.d.ts.map +1 -0
  116. package/dist/lib/cloudflare-deploy-manifest.js +107 -0
  117. package/dist/lib/cloudflare-deploy-manifest.js.map +1 -0
  118. package/dist/lib/cloudflare-wrangler-resources.d.ts +32 -0
  119. package/dist/lib/cloudflare-wrangler-resources.d.ts.map +1 -0
  120. package/dist/lib/cloudflare-wrangler-resources.js +59 -0
  121. package/dist/lib/cloudflare-wrangler-resources.js.map +1 -0
  122. package/dist/lib/config-editor.d.ts +139 -0
  123. package/dist/lib/config-editor.d.ts.map +1 -0
  124. package/dist/lib/config-editor.js +1188 -0
  125. package/dist/lib/config-editor.js.map +1 -0
  126. package/dist/lib/deploy-shared.d.ts +55 -0
  127. package/dist/lib/deploy-shared.d.ts.map +1 -0
  128. package/dist/lib/deploy-shared.js +183 -0
  129. package/dist/lib/deploy-shared.js.map +1 -0
  130. package/dist/lib/dev-sidecar.d.ts +31 -0
  131. package/dist/lib/dev-sidecar.d.ts.map +1 -0
  132. package/dist/lib/dev-sidecar.js +1058 -0
  133. package/dist/lib/dev-sidecar.js.map +1 -0
  134. package/dist/lib/fetch-with-timeout.d.ts +14 -0
  135. package/dist/lib/fetch-with-timeout.d.ts.map +1 -0
  136. package/dist/lib/fetch-with-timeout.js +29 -0
  137. package/dist/lib/fetch-with-timeout.js.map +1 -0
  138. package/dist/lib/function-registry.d.ts +56 -0
  139. package/dist/lib/function-registry.d.ts.map +1 -0
  140. package/dist/lib/function-registry.js +210 -0
  141. package/dist/lib/function-registry.js.map +1 -0
  142. package/dist/lib/load-config.d.ts +24 -0
  143. package/dist/lib/load-config.d.ts.map +1 -0
  144. package/dist/lib/load-config.js +263 -0
  145. package/dist/lib/load-config.js.map +1 -0
  146. package/dist/lib/local-secrets.d.ts +2 -0
  147. package/dist/lib/local-secrets.d.ts.map +1 -0
  148. package/dist/lib/local-secrets.js +60 -0
  149. package/dist/lib/local-secrets.js.map +1 -0
  150. package/dist/lib/managed-resource-names.d.ts +4 -0
  151. package/dist/lib/managed-resource-names.d.ts.map +1 -0
  152. package/dist/lib/managed-resource-names.js +19 -0
  153. package/dist/lib/managed-resource-names.js.map +1 -0
  154. package/dist/lib/migrator.d.ts +57 -0
  155. package/dist/lib/migrator.d.ts.map +1 -0
  156. package/dist/lib/migrator.js +321 -0
  157. package/dist/lib/migrator.js.map +1 -0
  158. package/dist/lib/neon.d.ts +41 -0
  159. package/dist/lib/neon.d.ts.map +1 -0
  160. package/dist/lib/neon.js +325 -0
  161. package/dist/lib/neon.js.map +1 -0
  162. package/dist/lib/node-tools.d.ts +10 -0
  163. package/dist/lib/node-tools.d.ts.map +1 -0
  164. package/dist/lib/node-tools.js +32 -0
  165. package/dist/lib/node-tools.js.map +1 -0
  166. package/dist/lib/npm.d.ts +8 -0
  167. package/dist/lib/npm.d.ts.map +1 -0
  168. package/dist/lib/npm.js +10 -0
  169. package/dist/lib/npm.js.map +1 -0
  170. package/dist/lib/npx.d.ts +9 -0
  171. package/dist/lib/npx.d.ts.map +1 -0
  172. package/dist/lib/npx.js +11 -0
  173. package/dist/lib/npx.js.map +1 -0
  174. package/dist/lib/project-runtime.d.ts +38 -0
  175. package/dist/lib/project-runtime.d.ts.map +1 -0
  176. package/dist/lib/project-runtime.js +122 -0
  177. package/dist/lib/project-runtime.js.map +1 -0
  178. package/dist/lib/prompts.d.ts +28 -0
  179. package/dist/lib/prompts.d.ts.map +1 -0
  180. package/dist/lib/prompts.js +85 -0
  181. package/dist/lib/prompts.js.map +1 -0
  182. package/dist/lib/rate-limit-bindings.d.ts +11 -0
  183. package/dist/lib/rate-limit-bindings.d.ts.map +1 -0
  184. package/dist/lib/rate-limit-bindings.js +52 -0
  185. package/dist/lib/rate-limit-bindings.js.map +1 -0
  186. package/dist/lib/realtime-provision.d.ts +22 -0
  187. package/dist/lib/realtime-provision.d.ts.map +1 -0
  188. package/dist/lib/realtime-provision.js +246 -0
  189. package/dist/lib/realtime-provision.js.map +1 -0
  190. package/dist/lib/resolve-options.d.ts +42 -0
  191. package/dist/lib/resolve-options.d.ts.map +1 -0
  192. package/dist/lib/resolve-options.js +98 -0
  193. package/dist/lib/resolve-options.js.map +1 -0
  194. package/dist/lib/runtime-scaffold.d.ts +17 -0
  195. package/dist/lib/runtime-scaffold.d.ts.map +1 -0
  196. package/dist/lib/runtime-scaffold.js +366 -0
  197. package/dist/lib/runtime-scaffold.js.map +1 -0
  198. package/dist/lib/schema-check.d.ts +79 -0
  199. package/dist/lib/schema-check.d.ts.map +1 -0
  200. package/dist/lib/schema-check.js +347 -0
  201. package/dist/lib/schema-check.js.map +1 -0
  202. package/dist/lib/spinner.d.ts +20 -0
  203. package/dist/lib/spinner.d.ts.map +1 -0
  204. package/dist/lib/spinner.js +42 -0
  205. package/dist/lib/spinner.js.map +1 -0
  206. package/dist/lib/telemetry.d.ts +37 -0
  207. package/dist/lib/telemetry.d.ts.map +1 -0
  208. package/dist/lib/telemetry.js +98 -0
  209. package/dist/lib/telemetry.js.map +1 -0
  210. package/dist/lib/turnstile-provision.d.ts +27 -0
  211. package/dist/lib/turnstile-provision.d.ts.map +1 -0
  212. package/dist/lib/turnstile-provision.js +144 -0
  213. package/dist/lib/turnstile-provision.js.map +1 -0
  214. package/dist/lib/update-check.d.ts +13 -0
  215. package/dist/lib/update-check.d.ts.map +1 -0
  216. package/dist/lib/update-check.js +110 -0
  217. package/dist/lib/update-check.js.map +1 -0
  218. package/dist/lib/wrangler-secrets.d.ts +3 -0
  219. package/dist/lib/wrangler-secrets.d.ts.map +1 -0
  220. package/dist/lib/wrangler-secrets.js +32 -0
  221. package/dist/lib/wrangler-secrets.js.map +1 -0
  222. package/dist/lib/wrangler.d.ts +9 -0
  223. package/dist/lib/wrangler.d.ts.map +1 -0
  224. package/dist/lib/wrangler.js +84 -0
  225. package/dist/lib/wrangler.js.map +1 -0
  226. package/dist/templates/plugin/README.md.tmpl +91 -0
  227. package/dist/templates/plugin/client/js/package.json.tmpl +23 -0
  228. package/dist/templates/plugin/client/js/src/index.ts.tmpl +68 -0
  229. package/dist/templates/plugin/client/js/tsconfig.json.tmpl +14 -0
  230. package/dist/templates/plugin/server/package.json.tmpl +19 -0
  231. package/dist/templates/plugin/server/src/index.ts.tmpl +59 -0
  232. package/dist/templates/plugin/server/tsconfig.json.tmpl +14 -0
  233. package/llms.txt +94 -0
  234. package/package.json +60 -0
@@ -0,0 +1,142 @@
1
+ import { Command } from 'commander';
2
+ import { writeFileSync, existsSync, mkdirSync } from 'node:fs';
3
+ import { resolve, dirname } from 'node:path';
4
+ import chalk from 'chalk';
5
+ import { isCliStructuredError, raiseCliError } from '../lib/agent-contract.js';
6
+ import { spin } from '../lib/spinner.js';
7
+ import { isJson, isQuiet } from '../lib/cli-context.js';
8
+ import { promptText } from '../lib/prompts.js';
9
+ import { fetchWithTimeout } from '../lib/fetch-with-timeout.js';
10
+ import { resolveServiceKey, resolveServerUrl } from '../lib/resolve-options.js';
11
+ /**
12
+ * `npx edgebase export` — Export table data as JSON.
13
+ *
14
+ * - `--format json` (only JSON supported)
15
+ * - `--table <name>` — Required: specific table to export
16
+ * - `--output <path>` — Output file path
17
+ * - `--url <url>` — Server URL (or EDGEBASE_URL env)
18
+ * - `--service-key <key>` — Service Key (or EDGEBASE_SERVICE_KEY env, or .edgebase/secrets.json)
19
+ *
20
+ * Uses Service Key authentication to call the backup export API endpoint.
21
+ * Authentication/URL resolution follows the same pattern as `backup` command.
22
+ */
23
+ export const exportCommand = new Command('export')
24
+ .description('Export table data as JSON')
25
+ .option('--format <type>', 'Export format (only "json" supported)', 'json')
26
+ .option('--table <name>', 'Table to export')
27
+ .option('--output <path>', 'Output file path')
28
+ .option('--url <url>', 'Server URL (or EDGEBASE_URL env)')
29
+ .option('--service-key <key>', 'Service Key (or EDGEBASE_SERVICE_KEY env)')
30
+ .action(async (options) => {
31
+ const format = options.format.toLowerCase();
32
+ if (format !== 'json') {
33
+ raiseCliError({
34
+ code: 'export_format_unsupported',
35
+ field: 'format',
36
+ message: `Unsupported format: "${format}". Only "json" is currently supported.`,
37
+ hint: 'Rerun with --format json.',
38
+ });
39
+ }
40
+ // Interactive prompt for --table if missing (TTY only)
41
+ if (!options.table) {
42
+ options.table = await promptText('Which table to export?', undefined, {
43
+ field: 'table',
44
+ hint: 'Rerun with --table <name>.',
45
+ message: 'A table name is required before export can continue.',
46
+ });
47
+ }
48
+ // Resolve Service Key and URL via shared utilities
49
+ const serviceKey = resolveServiceKey(options);
50
+ const serverUrl = resolveServerUrl(options);
51
+ const tableName = options.table;
52
+ const defaultName = `${tableName}-export.json`;
53
+ const outputPath = resolve(options.output || `./${defaultName}`);
54
+ // Ensure output directory exists
55
+ const outputDir = dirname(outputPath);
56
+ if (!existsSync(outputDir)) {
57
+ mkdirSync(outputDir, { recursive: true });
58
+ }
59
+ if (!isQuiet()) {
60
+ console.log(chalk.blue('📦 Exporting table data...'));
61
+ console.log(chalk.dim(` Table: ${tableName}`));
62
+ console.log(chalk.dim(` Format: ${format}`));
63
+ console.log(chalk.dim(` Output: ${outputPath}`));
64
+ console.log();
65
+ }
66
+ // Call Export API endpoint (Service Key path)
67
+ const exportUrl = `${serverUrl.replace(/\/$/, '')}/admin/api/backup/export/${encodeURIComponent(tableName)}?format=json`;
68
+ const s = spin('Fetching data from server...');
69
+ try {
70
+ const response = await fetchWithTimeout(exportUrl, {
71
+ headers: {
72
+ 'X-EdgeBase-Service-Key': serviceKey,
73
+ },
74
+ });
75
+ if (!response.ok) {
76
+ const error = await response.text();
77
+ let message;
78
+ try {
79
+ const parsed = JSON.parse(error);
80
+ message = parsed.message || error;
81
+ }
82
+ catch {
83
+ message = error;
84
+ }
85
+ s.fail(`Export failed (${response.status})`);
86
+ raiseCliError({
87
+ code: response.status === 404 ? 'export_table_not_found' : 'export_failed',
88
+ message,
89
+ hint: response.status === 401
90
+ ? 'Check your Service Key. It may have been rotated.'
91
+ : response.status === 404
92
+ ? `Table "${tableName}" not found. Check the table name and retry.`
93
+ : 'Check the server URL and ensure the server is running.',
94
+ details: {
95
+ table: tableName,
96
+ status: response.status,
97
+ },
98
+ });
99
+ }
100
+ const data = await response.text();
101
+ writeFileSync(outputPath, data, 'utf-8');
102
+ // Count records
103
+ let recordCount = 0;
104
+ try {
105
+ const parsed = JSON.parse(data);
106
+ recordCount = Array.isArray(parsed) ? parsed.length : 0;
107
+ }
108
+ catch { /* ignore */ }
109
+ s.succeed(`Exported ${recordCount} record(s) from "${tableName}"`);
110
+ // Show server notice if present (e.g., View table warning)
111
+ const notice = response.headers.get('x-edgebase-notice');
112
+ if (notice) {
113
+ console.log(chalk.yellow('⚠'), chalk.yellow(notice));
114
+ }
115
+ if (isJson()) {
116
+ console.log(JSON.stringify({
117
+ status: 'success',
118
+ table: tableName,
119
+ records: recordCount,
120
+ output: outputPath,
121
+ }));
122
+ }
123
+ else if (!isQuiet()) {
124
+ console.log(chalk.dim(` → ${outputPath}`));
125
+ }
126
+ }
127
+ catch (err) {
128
+ if (isCliStructuredError(err))
129
+ throw err;
130
+ s.fail('Export failed');
131
+ raiseCliError({
132
+ code: 'export_failed',
133
+ message: err.message,
134
+ hint: 'Check the server URL and ensure the server is running.',
135
+ details: {
136
+ table: tableName,
137
+ output: outputPath,
138
+ },
139
+ });
140
+ }
141
+ });
142
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * `edgebase init [dir]` — Project scaffolding.
4
+ * Creates edgebase.config.ts, functions/ directory, env files, and .gitignore.
5
+ */
6
+ export declare const initCommand: Command;
7
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC;;;GAGG;AACH,eAAO,MAAM,WAAW,SAqLpB,CAAC"}
@@ -0,0 +1,506 @@
1
+ import { Command } from 'commander';
2
+ import { randomBytes } from 'node:crypto';
3
+ import { writeFileSync, mkdirSync, existsSync, chmodSync, readFileSync } from 'node:fs';
4
+ import { dirname, join, relative, resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import chalk from 'chalk';
7
+ import { deriveProjectSlug, ensureLocalWranglerToml, ensureRuntimeScaffold } from '../lib/runtime-scaffold.js';
8
+ /**
9
+ * `edgebase init [dir]` — Project scaffolding.
10
+ * Creates edgebase.config.ts, functions/ directory, env files, and .gitignore.
11
+ */
12
+ export const initCommand = new Command('init')
13
+ .description('Initialize a new EdgeBase project')
14
+ .argument('[dir]', 'Project directory', '.')
15
+ .option('--no-dev', 'Skip automatically starting the dev server after scaffolding')
16
+ .option('--no-open', 'Do not open the Admin Dashboard when auto-starting the dev server')
17
+ .action(async (dir, options) => {
18
+ const projectDir = resolve(dir);
19
+ const localCliEntry = resolveLocalCliEntry(projectDir);
20
+ const edgebaseBin = localCliEntry ? `node ${localCliEntry}` : 'npx edgebase';
21
+ const needsPublishedPackages = localCliEntry === null;
22
+ console.log(chalk.blue('⚡ Initializing EdgeBase project...'));
23
+ console.log();
24
+ // Create project directory if needed
25
+ if (!existsSync(projectDir)) {
26
+ mkdirSync(projectDir, { recursive: true });
27
+ }
28
+ const configPath = join(projectDir, 'edgebase.config.ts');
29
+ // Create edgebase.config.ts template
30
+ if (!existsSync(configPath)) {
31
+ writeFileSync(configPath, CONFIG_TEMPLATE);
32
+ console.log(chalk.green(' ✓'), 'edgebase.config.ts');
33
+ }
34
+ else {
35
+ console.log(chalk.yellow(' ⏭'), 'edgebase.config.ts (already exists)');
36
+ }
37
+ const configDir = join(projectDir, 'config');
38
+ const rateLimitsPath = join(configDir, 'rate-limits.ts');
39
+ if (!existsSync(rateLimitsPath)) {
40
+ mkdirSync(configDir, { recursive: true });
41
+ writeFileSync(rateLimitsPath, RATE_LIMITS_TEMPLATE);
42
+ console.log(chalk.green(' ✓'), 'config/rate-limits.ts');
43
+ }
44
+ else {
45
+ console.log(chalk.yellow(' ⏭'), 'config/rate-limits.ts (already exists)');
46
+ }
47
+ // Create functions/ directory
48
+ const functionsDir = join(projectDir, 'functions');
49
+ if (!existsSync(functionsDir)) {
50
+ mkdirSync(functionsDir, { recursive: true });
51
+ // Create example function
52
+ writeFileSync(join(functionsDir, 'health.ts'), EXAMPLE_FUNCTION_TEMPLATE);
53
+ console.log(chalk.green(' ✓'), 'functions/health.ts');
54
+ }
55
+ else {
56
+ console.log(chalk.yellow(' ⏭'), 'functions/ (already exists)');
57
+ }
58
+ // Create .env.development for local development secrets
59
+ const envDevPath = join(projectDir, '.env.development');
60
+ if (!existsSync(envDevPath)) {
61
+ const devUserSecret = generateDevSecret();
62
+ const devAdminSecret = generateDevSecret();
63
+ writeFileSync(envDevPath, ENV_DEVELOPMENT_TEMPLATE
64
+ .replace('JWT_USER_SECRET=', `JWT_USER_SECRET=${devUserSecret}`)
65
+ .replace('JWT_ADMIN_SECRET=', `JWT_ADMIN_SECRET=${devAdminSecret}`));
66
+ console.log(chalk.green(' ✓'), '.env.development (JWT secrets auto-generated)');
67
+ // Also save to .edgebase/secrets.json for local key management
68
+ const edgebaseDir = join(projectDir, '.edgebase');
69
+ const secretsJsonPath = join(edgebaseDir, 'secrets.json');
70
+ if (!existsSync(edgebaseDir))
71
+ mkdirSync(edgebaseDir, { recursive: true });
72
+ writeFileSync(secretsJsonPath, JSON.stringify({ JWT_USER_SECRET: devUserSecret, JWT_ADMIN_SECRET: devAdminSecret }, null, 2), 'utf-8');
73
+ chmodSync(secretsJsonPath, 0o600);
74
+ }
75
+ // Create example env files (committed to repo for onboarding)
76
+ const envDevExamplePath = join(projectDir, '.env.development.example');
77
+ if (!existsSync(envDevExamplePath)) {
78
+ writeFileSync(envDevExamplePath, ENV_DEVELOPMENT_TEMPLATE);
79
+ console.log(chalk.green(' ✓'), '.env.development.example');
80
+ }
81
+ const envReleaseExamplePath = join(projectDir, '.env.release.example');
82
+ if (!existsSync(envReleaseExamplePath)) {
83
+ writeFileSync(envReleaseExamplePath, ENV_RELEASE_TEMPLATE);
84
+ console.log(chalk.green(' ✓'), '.env.release.example');
85
+ }
86
+ const packageJsonPath = join(projectDir, 'package.json');
87
+ if (!existsSync(packageJsonPath)) {
88
+ writeFileSync(packageJsonPath, PACKAGE_JSON_TEMPLATE(deriveProjectSlug(projectDir), localCliEntry, needsPublishedPackages));
89
+ console.log(chalk.green(' ✓'), 'package.json');
90
+ }
91
+ else {
92
+ const packageJsonChanged = ensureScaffoldPackageJson(packageJsonPath, deriveProjectSlug(projectDir), localCliEntry, needsPublishedPackages);
93
+ console.log(packageJsonChanged ? chalk.green(' ✓') : chalk.yellow(' ⏭'), packageJsonChanged ? 'package.json (updated)' : 'package.json (already exists)');
94
+ }
95
+ const wranglerPath = join(projectDir, 'wrangler.toml');
96
+ if (!existsSync(wranglerPath)) {
97
+ ensureLocalWranglerToml(projectDir);
98
+ console.log(chalk.green(' ✓'), 'wrangler.toml');
99
+ }
100
+ else {
101
+ console.log(chalk.yellow(' ⏭'), 'wrangler.toml (already exists)');
102
+ }
103
+ const gitignorePath = join(projectDir, '.gitignore');
104
+ const hadGitignore = existsSync(gitignorePath);
105
+ const gitignoreChanged = ensureScaffoldGitignore(gitignorePath);
106
+ console.log(gitignoreChanged ? chalk.green(' ✓') : chalk.yellow(' ⏭'), !hadGitignore
107
+ ? '.gitignore'
108
+ : gitignoreChanged
109
+ ? '.gitignore (updated)'
110
+ : '.gitignore (already exists)');
111
+ ensureRuntimeScaffold(projectDir);
112
+ console.log(chalk.green(' ✓'), '.edgebase/runtime scaffold');
113
+ console.log();
114
+ console.log(chalk.green('✨'), 'Project initialized!');
115
+ console.log();
116
+ // Auto-start dev server with admin dashboard
117
+ if (!options.dev) {
118
+ console.log(chalk.bold('Next steps:'));
119
+ console.log(` 1. Edit ${chalk.cyan('edgebase.config.ts')} to define your schema and auth settings`);
120
+ if (needsPublishedPackages && shouldShowInstallStep()) {
121
+ console.log(` 2. Run ${chalk.cyan(`'npm install'`)} to install the local EdgeBase CLI`);
122
+ console.log(` 3. Run ${chalk.cyan(`'${edgebaseBin} dev'`)} to start the local development server`);
123
+ console.log(` 4. Open the Admin Dashboard to explore your API`);
124
+ console.log(` 5. Read the docs: ${chalk.cyan('https://edgebase.fun/docs/getting-started/quickstart')}`);
125
+ }
126
+ else if (needsPublishedPackages) {
127
+ console.log(` 2. Run ${chalk.cyan(`'${edgebaseBin} dev'`)} to start the local development server`);
128
+ console.log(` 3. Open the Admin Dashboard to explore your API`);
129
+ console.log(` 4. Read the docs: ${chalk.cyan('https://edgebase.fun/docs/getting-started/quickstart')}`);
130
+ }
131
+ else {
132
+ console.log(` 2. Run ${chalk.cyan(`'${edgebaseBin} dev'`)} to start the local development server`);
133
+ console.log(` 3. Open the Admin Dashboard to explore your API`);
134
+ console.log(` 4. Read the docs: ${chalk.cyan('https://edgebase.fun/docs/getting-started/quickstart')}`);
135
+ }
136
+ console.log();
137
+ console.log(chalk.dim('When you\'re ready for production:'));
138
+ const publishedInstallStep = needsPublishedPackages && shouldShowInstallStep();
139
+ console.log(` ${publishedInstallStep ? '6' : '5'}. Set ${chalk.cyan('release: true')} in edgebase.config.ts`);
140
+ console.log(` ${publishedInstallStep ? '7' : '6'}. Run ${chalk.cyan(`'${edgebaseBin} deploy'`)} to deploy to Cloudflare`);
141
+ return;
142
+ }
143
+ console.log(chalk.bold('Next steps:'));
144
+ console.log(` 1. Edit ${chalk.cyan('edgebase.config.ts')} to define your schema and auth settings`);
145
+ console.log(` 2. Open the Admin Dashboard to explore your API`);
146
+ console.log(` 3. Read the docs: ${chalk.cyan('https://edgebase.fun/docs/getting-started/quickstart')}`);
147
+ console.log();
148
+ console.log(chalk.dim('When you\'re ready for production:'));
149
+ console.log(` 4. Set ${chalk.cyan('release: true')} in edgebase.config.ts`);
150
+ console.log(` 5. Run ${chalk.cyan(`'${edgebaseBin} deploy'`)} to deploy to Cloudflare`);
151
+ console.log();
152
+ console.log(chalk.blue('⚡'), 'Starting dev server...');
153
+ console.log();
154
+ // Run dev in the project directory (same process, no redundant npx spawn)
155
+ process.chdir(projectDir);
156
+ const { devCommand } = await import('./dev.js');
157
+ const devArgs = options.open ? [] : ['--no-open'];
158
+ await devCommand.parseAsync(devArgs, { from: 'user' });
159
+ });
160
+ function generateDevSecret() {
161
+ return randomBytes(32).toString('hex');
162
+ }
163
+ // ─── Templates ───
164
+ const CONFIG_TEMPLATE = `import { defineConfig } from '@edge-base/shared';
165
+ import { rateLimiting } from './config/rate-limits';
166
+
167
+ export default defineConfig({
168
+ // release: false (default) — access policies are bypassed during development.
169
+ // Set release: true before production deployment to enable deny-by-default access.
170
+
171
+ databases: {
172
+ // Add your first DB block here, for example:
173
+ // app: {
174
+ // tables: {
175
+ // posts: {
176
+ // schema: {
177
+ // title: { type: 'string', required: true },
178
+ // content: { type: 'text' },
179
+ // },
180
+ // },
181
+ // },
182
+ // },
183
+ },
184
+
185
+ // Optional rooms use handlers.lifecycle / handlers.actions / handlers.timers:
186
+ // rooms: {
187
+ // game: {
188
+ // maxPlayers: 8,
189
+ // handlers: {
190
+ // lifecycle: {
191
+ // onCreate(room) {
192
+ // room.setSharedState(() => ({ status: 'waiting' }));
193
+ // },
194
+ // },
195
+ // actions: {
196
+ // PING: (_payload, room) => {
197
+ // room.broadcast('PONG', { at: Date.now() });
198
+ // },
199
+ // },
200
+ // },
201
+ // },
202
+ // },
203
+
204
+ auth: {
205
+ emailAuth: true,
206
+ },
207
+
208
+ storage: {
209
+ buckets: {
210
+ uploads: {
211
+ // Uses the generated STORAGE R2 binding by default.
212
+ // Add access policies here when ready for production:
213
+ // access: {
214
+ // read: () => true,
215
+ // write: (auth) => auth !== null,
216
+ // delete: (auth) => auth !== null,
217
+ // },
218
+ },
219
+ },
220
+ },
221
+
222
+ serviceKeys: {
223
+ keys: [
224
+ {
225
+ kid: 'root',
226
+ tier: 'root',
227
+ scopes: ['*'],
228
+ secretSource: 'dashboard',
229
+ secretRef: 'SERVICE_KEY',
230
+ },
231
+ ],
232
+ },
233
+
234
+ rateLimiting,
235
+
236
+ cors: {
237
+ origin: '*',
238
+ },
239
+ });
240
+ `;
241
+ const RATE_LIMITS_TEMPLATE = `export const rateLimiting = {
242
+ global: {
243
+ requests: 10_000_000,
244
+ window: '60s',
245
+ binding: { limit: 10_000_000, period: 60, namespaceId: '1001' },
246
+ },
247
+ db: {
248
+ requests: 100,
249
+ window: '60s',
250
+ binding: { limit: 10_000_000, period: 60, namespaceId: '1002' },
251
+ },
252
+ storage: {
253
+ requests: 50,
254
+ window: '60s',
255
+ binding: { limit: 10_000_000, period: 60, namespaceId: '1003' },
256
+ },
257
+ functions: {
258
+ requests: 50,
259
+ window: '60s',
260
+ binding: { limit: 10_000_000, period: 60, namespaceId: '1004' },
261
+ },
262
+ auth: {
263
+ requests: 30,
264
+ window: '60s',
265
+ binding: { limit: 10_000_000, period: 60, namespaceId: '1005' },
266
+ },
267
+ authSignin: {
268
+ requests: 10,
269
+ window: '60s',
270
+ binding: { limit: 10_000_000, period: 60, namespaceId: '1006' },
271
+ },
272
+ authSignup: {
273
+ requests: 10,
274
+ window: '60s',
275
+ binding: { limit: 10_000_000, period: 60, namespaceId: '1007' },
276
+ },
277
+ events: {
278
+ requests: 100,
279
+ window: '60s',
280
+ binding: { limit: 10_000_000, period: 60, namespaceId: '1008' },
281
+ },
282
+ } as const;
283
+ `;
284
+ const EXAMPLE_FUNCTION_TEMPLATE = `import { defineFunction } from '@edge-base/shared';
285
+
286
+ export const GET = defineFunction(async () => {
287
+ return Response.json({ ok: true });
288
+ });
289
+ `;
290
+ const GITIGNORE_RULES = [
291
+ 'node_modules/',
292
+ 'dist/',
293
+ '.wrangler/',
294
+ '.wrangler.generated.*',
295
+ '.dev.vars',
296
+ '.env.development',
297
+ '.env.release',
298
+ '.edgebase/',
299
+ 'edgebase.d.ts',
300
+ '*.local',
301
+ ];
302
+ const GITIGNORE_TEMPLATE = `${GITIGNORE_RULES.join('\n')}\n`;
303
+ function resolveLocalCliEntry(projectDir) {
304
+ let currentDir = resolve(projectDir);
305
+ while (true) {
306
+ const repoPackageJsonPath = join(currentDir, 'package.json');
307
+ const workspacePath = join(currentDir, 'pnpm-workspace.yaml');
308
+ const cliEntryPath = join(currentDir, 'packages', 'cli', 'dist', 'index.js');
309
+ if (existsSync(repoPackageJsonPath) && existsSync(workspacePath) && existsSync(cliEntryPath)) {
310
+ try {
311
+ const repoPackageJson = JSON.parse(readFileSync(repoPackageJsonPath, 'utf-8'));
312
+ if (repoPackageJson.name === 'edgebase') {
313
+ return toPosixPath(relative(projectDir, cliEntryPath));
314
+ }
315
+ }
316
+ catch {
317
+ // Ignore malformed repo metadata and keep walking upward.
318
+ }
319
+ }
320
+ const parentDir = dirname(currentDir);
321
+ if (parentDir === currentDir) {
322
+ return null;
323
+ }
324
+ currentDir = parentDir;
325
+ }
326
+ }
327
+ function toPosixPath(path) {
328
+ return path.replace(/\\/g, '/');
329
+ }
330
+ function readPackageJsonFromUrl(relativePath) {
331
+ try {
332
+ const packageJsonPath = fileURLToPath(new URL(relativePath, import.meta.url));
333
+ return JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
334
+ }
335
+ catch {
336
+ return null;
337
+ }
338
+ }
339
+ function resolveScaffoldDependencyVersion(packageName) {
340
+ const cliPackageJson = readPackageJsonFromUrl('../../package.json');
341
+ const cliVersion = typeof cliPackageJson?.version === 'string' ? cliPackageJson.version : '0.1.0';
342
+ const cliDependencies = typeof cliPackageJson?.dependencies === 'object' && cliPackageJson.dependencies !== null
343
+ ? cliPackageJson.dependencies
344
+ : {};
345
+ const declaredVersion = cliDependencies[packageName];
346
+ if (typeof declaredVersion === 'string' && !declaredVersion.startsWith('workspace:')) {
347
+ return /^\d+\.\d+\.\d+(?:[-+].+)?$/.test(declaredVersion)
348
+ ? `^${declaredVersion}`
349
+ : declaredVersion;
350
+ }
351
+ if (packageName === '@edge-base/shared') {
352
+ const sharedPackageJson = readPackageJsonFromUrl('../../../shared/package.json');
353
+ if (typeof sharedPackageJson?.version === 'string') {
354
+ return `^${sharedPackageJson.version}`;
355
+ }
356
+ }
357
+ return `^${cliVersion}`;
358
+ }
359
+ const PACKAGE_JSON_TEMPLATE = (name, localCliEntry, needsPublishedPackages) => {
360
+ return `${JSON.stringify(buildPackageJsonObject(name, localCliEntry, needsPublishedPackages), null, 2)}\n`;
361
+ };
362
+ function buildPackageJsonObject(name, localCliEntry, needsPublishedPackages) {
363
+ const scriptPrefix = localCliEntry ? `node ${localCliEntry}` : 'edgebase';
364
+ const packageJson = {
365
+ name,
366
+ private: true,
367
+ type: 'module',
368
+ scripts: {
369
+ dev: `${scriptPrefix} dev`,
370
+ deploy: `${scriptPrefix} deploy`,
371
+ typegen: `${scriptPrefix} typegen`,
372
+ },
373
+ engines: {
374
+ node: '^22.0.0 || ^24.0.0',
375
+ },
376
+ };
377
+ if (needsPublishedPackages) {
378
+ packageJson.devDependencies = {
379
+ '@edge-base/cli': resolveScaffoldDependencyVersion('@edge-base/cli'),
380
+ '@edge-base/shared': resolveScaffoldDependencyVersion('@edge-base/shared'),
381
+ };
382
+ }
383
+ return packageJson;
384
+ }
385
+ // ─── Env File Templates ───
386
+ function shouldShowInstallStep() {
387
+ return process.env.EDGEBASE_BOOTSTRAP_WRAPPER !== '1';
388
+ }
389
+ function ensureScaffoldPackageJson(packageJsonPath, name, localCliEntry, needsPublishedPackages) {
390
+ let existing;
391
+ try {
392
+ existing = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
393
+ }
394
+ catch {
395
+ return false;
396
+ }
397
+ const generated = buildPackageJsonObject(name, localCliEntry, needsPublishedPackages);
398
+ let changed = false;
399
+ if (existing.name === undefined) {
400
+ existing.name = generated.name;
401
+ changed = true;
402
+ }
403
+ if (existing.private === undefined) {
404
+ existing.private = generated.private;
405
+ changed = true;
406
+ }
407
+ if (existing.type === undefined) {
408
+ existing.type = generated.type;
409
+ changed = true;
410
+ }
411
+ const existingScripts = ensureStringMap(existing, 'scripts');
412
+ for (const [key, value] of Object.entries(generated.scripts ?? {})) {
413
+ if (existingScripts[key] === undefined) {
414
+ existingScripts[key] = value;
415
+ changed = true;
416
+ }
417
+ }
418
+ const existingEngines = ensureStringMap(existing, 'engines');
419
+ if (generated.engines?.node && existingEngines.node === undefined) {
420
+ existingEngines.node = generated.engines.node;
421
+ changed = true;
422
+ }
423
+ if (needsPublishedPackages) {
424
+ const existingDependencies = ensureStringMap(existing, 'dependencies');
425
+ const existingDevDependencies = ensureStringMap(existing, 'devDependencies');
426
+ const existingPeerDependencies = ensureStringMap(existing, 'peerDependencies');
427
+ const existingOptionalDependencies = ensureStringMap(existing, 'optionalDependencies');
428
+ for (const [key, value] of Object.entries(generated.devDependencies ?? {})) {
429
+ if (existingDependencies[key] === undefined
430
+ && existingDevDependencies[key] === undefined
431
+ && existingPeerDependencies[key] === undefined
432
+ && existingOptionalDependencies[key] === undefined) {
433
+ existingDevDependencies[key] = value;
434
+ changed = true;
435
+ }
436
+ }
437
+ }
438
+ if (!changed) {
439
+ return false;
440
+ }
441
+ writeFileSync(packageJsonPath, `${JSON.stringify(existing, null, 2)}\n`, 'utf-8');
442
+ return true;
443
+ }
444
+ function ensureScaffoldGitignore(gitignorePath) {
445
+ if (!existsSync(gitignorePath)) {
446
+ writeFileSync(gitignorePath, GITIGNORE_TEMPLATE, 'utf-8');
447
+ return true;
448
+ }
449
+ const existing = readFileSync(gitignorePath, 'utf-8');
450
+ const existingRules = new Set(existing
451
+ .split(/\r?\n/)
452
+ .map((line) => line.trim())
453
+ .filter((line) => line.length > 0));
454
+ const missingRules = GITIGNORE_RULES.filter((rule) => !existingRules.has(rule));
455
+ if (missingRules.length === 0) {
456
+ return false;
457
+ }
458
+ const prefix = existing.length === 0 || existing.endsWith('\n') ? '' : '\n';
459
+ writeFileSync(gitignorePath, `${existing}${prefix}${missingRules.join('\n')}\n`, 'utf-8');
460
+ return true;
461
+ }
462
+ function ensureStringMap(target, key) {
463
+ const current = target[key];
464
+ if (current && typeof current === 'object' && !Array.isArray(current)) {
465
+ return current;
466
+ }
467
+ const next = {};
468
+ target[key] = next;
469
+ return next;
470
+ }
471
+ const ENV_DEVELOPMENT_TEMPLATE = `# EdgeBase Development Environment Variables
472
+ # This file is git-ignored. Copy from .env.development.example to get started.
473
+ #
474
+ # JWT secrets below are auto-generated by EdgeBase project scaffolding.
475
+ # Add any development/test API keys below.
476
+
477
+ JWT_USER_SECRET=
478
+ JWT_ADMIN_SECRET=
479
+
480
+ # Example: Stripe test keys
481
+ # STRIPE_SECRET_KEY=sk_test_...
482
+ # STRIPE_WEBHOOK_SECRET=whsec_...
483
+
484
+ # Example: Email provider (Resend, etc.)
485
+ # EMAIL_API_KEY=re_test_...
486
+ `;
487
+ const ENV_RELEASE_TEMPLATE = `# EdgeBase Production Environment Variables
488
+ # This file is git-ignored. Copy from .env.release.example to get started.
489
+ #
490
+ # On \`edgebase deploy\`, these are auto-synced to Cloudflare Secrets.
491
+ # SERVICE_KEY is auto-managed by the deploy pipeline — do not include it here.
492
+
493
+ JWT_USER_SECRET=
494
+ JWT_ADMIN_SECRET=
495
+
496
+ # Database provider connection strings (only if using provider: 'neon' or 'postgres')
497
+ # DB_POSTGRES_SHARED_URL=postgres://user:pass@host/db?sslmode=require
498
+
499
+ # Example: Stripe live keys
500
+ # STRIPE_SECRET_KEY=sk_live_...
501
+ # STRIPE_WEBHOOK_SECRET=whsec_...
502
+
503
+ # Example: Email provider (Resend, etc.)
504
+ # EMAIL_API_KEY=re_...
505
+ `;
506
+ //# sourceMappingURL=init.js.map