@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
package/README.md ADDED
@@ -0,0 +1,182 @@
1
+ <h1 align="center">@edge-base/cli</h1>
2
+
3
+ <p align="center">
4
+ <b>Command-line workflow for EdgeBase</b><br>
5
+ Scaffold projects, run local development, deploy to Cloudflare, and operate your EdgeBase stack from one CLI
6
+ </p>
7
+
8
+ <p align="center">
9
+ <a href="https://www.npmjs.com/package/@edge-base/cli"><img src="https://img.shields.io/npm/v/%40edge-base%2Fcli?color=brightgreen" alt="npm"></a>&nbsp;
10
+ <a href="https://edgebase.fun/docs/cli"><img src="https://img.shields.io/badge/docs-cli-blue" alt="Docs"></a>&nbsp;
11
+ <a href="https://github.com/edge-base/edgebase/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://edgebase.fun/docs/getting-started/quickstart"><b>Quickstart</b></a> ·
16
+ <a href="https://edgebase.fun/docs/cli"><b>CLI Overview</b></a> ·
17
+ <a href="https://edgebase.fun/docs/cli/workflows"><b>CLI Workflows</b></a> ·
18
+ <a href="https://edgebase.fun/docs/cli/reference"><b>CLI Reference</b></a>
19
+ </p>
20
+
21
+ ---
22
+
23
+ `@edge-base/cli` is the command surface for the full EdgeBase project lifecycle.
24
+
25
+ Use it to:
26
+
27
+ - bootstrap a new project
28
+ - run local development with hot reload
29
+ - deploy and destroy project-scoped Cloudflare resources
30
+ - generate types, migrations, backups, and exports
31
+ - manage secrets, keys, plugins, and admin operations
32
+
33
+ > Beta: the CLI is already usable, but some commands and flags may still evolve before general availability.
34
+
35
+ ## Documentation Map
36
+
37
+ - [Quickstart](https://edgebase.fun/docs/getting-started/quickstart)
38
+ Start a new EdgeBase project with `npm create edge-base@latest`
39
+ - [CLI Overview](https://edgebase.fun/docs/cli)
40
+ Understand what the CLI owns across local development, deploy, data workflows, and tooling
41
+ - [CLI Workflows](https://edgebase.fun/docs/cli/workflows)
42
+ Task-focused guides for common flows
43
+ - [CLI Reference](https://edgebase.fun/docs/cli/reference)
44
+ Full command inventory, aliases, and environment variables
45
+
46
+ ## For AI Coding Assistants
47
+
48
+ This package ships with an `llms.txt` file for AI-assisted CLI usage.
49
+
50
+ You can find it:
51
+
52
+ - after install: `node_modules/@edge-base/cli/llms.txt`
53
+ - in the repository: [llms.txt](https://github.com/edge-base/edgebase/blob/main/packages/cli/llms.txt)
54
+
55
+ Use it when you want an agent to:
56
+
57
+ - pick the right command for a workflow
58
+ - avoid guessing package-manager entrypoints
59
+ - prefer `--json --non-interactive` in automation
60
+ - stay inside the supported EdgeBase project structure
61
+
62
+ ## Installation
63
+
64
+ For new projects, the best starting point is:
65
+
66
+ ```bash
67
+ npm create edge-base@latest my-app
68
+ ```
69
+
70
+ That scaffold installs the local CLI into the generated project for you.
71
+
72
+ If you want the CLI globally:
73
+
74
+ ```bash
75
+ npm install -g @edge-base/cli
76
+ ```
77
+
78
+ After that, you can run:
79
+
80
+ ```bash
81
+ edgebase --help
82
+ ```
83
+
84
+ ## Quick Start
85
+
86
+ ### Start a new project
87
+
88
+ ```bash
89
+ npm create edge-base@latest my-app
90
+ cd my-app
91
+ npm run dev
92
+ ```
93
+
94
+ Inside an EdgeBase project, the local CLI is available through:
95
+
96
+ ```bash
97
+ npx edgebase dev
98
+ ```
99
+
100
+ ### Deploy to Cloudflare
101
+
102
+ ```bash
103
+ cp .env.release.example .env.release
104
+ npx edgebase deploy
105
+ ```
106
+
107
+ ### Generate types
108
+
109
+ ```bash
110
+ npx edgebase typegen
111
+ ```
112
+
113
+ ## What The CLI Covers
114
+
115
+ | Area | Commands | What it covers |
116
+ | --- | --- | --- |
117
+ | Project lifecycle | `init`, `dev`, `deploy`, `destroy`, `logs`, `upgrade` | Bootstrap, local runtime, deploy, cleanup, logging, and package upgrades |
118
+ | Data workflow | `migration`, `migrate`, `seed`, `backup`, `export`, `typegen`, `neon` | Schema changes, provider migrations, fixture data, backups, exports, generated types, Neon setup |
119
+ | Security and admin | `secret`, `keys`, `admin` | Secrets, Service Key/JWT rotation, and admin recovery flows |
120
+ | Plugins and tooling | `plugins`, `create-plugin`, `docker`, `webhook-test`, `completion`, `describe`, `telemetry`, `realtime` | Plugin scaffolding, plugin maintenance, Docker support, completions, machine-readable command descriptions, telemetry, and Cloudflare Realtime setup |
121
+
122
+ ## Recommended Usage Pattern
123
+
124
+ Most teams do **not** need a global install.
125
+
126
+ A good default flow is:
127
+
128
+ 1. scaffold with `npm create edge-base@latest`
129
+ 2. keep the CLI local to the generated project
130
+ 3. run commands with `npm run ...` or `npx edgebase ...`
131
+
132
+ If you are adding EdgeBase to an existing frontend repo, a clean default is to scaffold into a dedicated subdirectory:
133
+
134
+ ```bash
135
+ cd your-frontend-project
136
+ npm create edge-base@latest edgebase
137
+ ```
138
+
139
+ That keeps the frontend app and the EdgeBase project close together without mixing them into the same root by accident.
140
+
141
+ ## Automation And CI
142
+
143
+ When another tool, agent, or CI job is driving the CLI, prefer:
144
+
145
+ ```bash
146
+ edgebase --json --non-interactive <command>
147
+ ```
148
+
149
+ This makes the CLI return structured responses instead of hanging on prompts.
150
+
151
+ Useful companion commands:
152
+
153
+ ```bash
154
+ edgebase --json describe
155
+ edgebase --json describe --command "deploy"
156
+ edgebase --json describe --command "backup restore"
157
+ ```
158
+
159
+ Read more: [CLI Reference](https://edgebase.fun/docs/cli/reference)
160
+
161
+ ## Common Environment Variables
162
+
163
+ | Variable | Used by |
164
+ | --- | --- |
165
+ | `EDGEBASE_URL` | Remote commands such as `migrate`, `backup`, `export`, `admin`, `plugins cleanup`, and `destroy` |
166
+ | `EDGEBASE_SERVICE_KEY` | Remote admin commands and Service Key authenticated flows |
167
+ | `CLOUDFLARE_API_TOKEN` | Non-interactive deploy/destroy flows |
168
+ | `CLOUDFLARE_ACCOUNT_ID` | Account-scoped Cloudflare operations |
169
+ | `NEON_API_KEY` | `edgebase neon setup` in non-interactive environments |
170
+
171
+ ## Related Packages
172
+
173
+ - [`create-edge-base`](https://www.npmjs.com/package/create-edge-base)
174
+ First-run project bootstrap package
175
+ - [`@edge-base/web`](https://www.npmjs.com/package/@edge-base/web)
176
+ Browser SDK for app code
177
+ - [`@edge-base/admin`](https://www.npmjs.com/package/@edge-base/admin)
178
+ Trusted server-side SDK for admin tasks
179
+
180
+ ## License
181
+
182
+ MIT
@@ -0,0 +1,10 @@
1
+ /**
2
+ * CLI: `npx edgebase admin` — Admin management commands
3
+ *
4
+ * Subcommands:
5
+ * reset-password — Reset admin password via Service Key or Cloudflare D1 direct access
6
+ */
7
+ import { Command } from 'commander';
8
+ export declare function toSqliteStringLiteral(value: string): string;
9
+ export declare const adminCommand: Command;
10
+ //# sourceMappingURL=admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../src/commands/admin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsHpC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAuID,eAAO,MAAM,YAAY,SACkB,CAAC"}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * CLI: `npx edgebase admin` — Admin management commands
3
+ *
4
+ * Subcommands:
5
+ * reset-password — Reset admin password via Service Key or Cloudflare D1 direct access
6
+ */
7
+ import { Command } from 'commander';
8
+ import { execFileSync } from 'node:child_process';
9
+ import * as readline from 'node:readline';
10
+ import { webcrypto } from 'node:crypto';
11
+ import chalk from 'chalk';
12
+ import { fetchWithTimeout } from '../lib/fetch-with-timeout.js';
13
+ import { resolveOptionalServiceKey, resolveServerUrl } from '../lib/resolve-options.js';
14
+ import { isCliStructuredError, raiseCliError, raiseNeedsInput, } from '../lib/agent-contract.js';
15
+ import { ensureCloudflareAuth } from '../lib/cf-auth.js';
16
+ import { isJson, isNonInteractive, isQuiet } from '../lib/cli-context.js';
17
+ import { readProjectWranglerContext, resolveManagedD1DatabaseName, } from '../lib/project-runtime.js';
18
+ import { wranglerCommand, wranglerArgs } from '../lib/wrangler.js';
19
+ const HASH_ITERATIONS = 100_000;
20
+ const SALT_LENGTH = 16;
21
+ const KEY_LENGTH = 32;
22
+ function toBase64(buffer) {
23
+ return Buffer.from(buffer).toString('base64');
24
+ }
25
+ async function hashPassword(password) {
26
+ const salt = webcrypto.getRandomValues(new Uint8Array(SALT_LENGTH));
27
+ const keyMaterial = await webcrypto.subtle.importKey('raw', new TextEncoder().encode(password), 'PBKDF2', false, ['deriveBits']);
28
+ const hash = await webcrypto.subtle.deriveBits({
29
+ name: 'PBKDF2',
30
+ salt,
31
+ iterations: HASH_ITERATIONS,
32
+ hash: 'SHA-256',
33
+ }, keyMaterial, KEY_LENGTH * 8);
34
+ return `pbkdf2:sha256:${HASH_ITERATIONS}:${toBase64(salt.buffer)}:${toBase64(hash)}`;
35
+ }
36
+ function prompt(question, hidden = false, options) {
37
+ if (!process.stdin.isTTY || isNonInteractive()) {
38
+ raiseNeedsInput({
39
+ code: 'admin_input_required',
40
+ field: options?.field,
41
+ message: options?.message ?? `${question.replace(/:?\s*$/, '')} is required.`,
42
+ hint: options?.hint,
43
+ });
44
+ }
45
+ return new Promise((resolve) => {
46
+ const rl = readline.createInterface({
47
+ input: process.stdin,
48
+ output: process.stdout,
49
+ });
50
+ if (hidden && process.stdout.isTTY) {
51
+ process.stdout.write(question);
52
+ const stdin = process.stdin;
53
+ const oldRawMode = stdin.isRaw;
54
+ stdin.setRawMode(true);
55
+ let input = '';
56
+ stdin.resume();
57
+ stdin.on('data', function handler(ch) {
58
+ const c = ch.toString('utf8');
59
+ if (c === '\n' || c === '\r' || c === '\u0004') {
60
+ stdin.setRawMode(oldRawMode ?? false);
61
+ stdin.removeListener('data', handler);
62
+ stdin.pause();
63
+ rl.close();
64
+ process.stdout.write('\n');
65
+ resolve(input);
66
+ }
67
+ else if (c === '\u007F' || c === '\b') {
68
+ if (input.length > 0)
69
+ input = input.slice(0, -1);
70
+ }
71
+ else {
72
+ input += c;
73
+ }
74
+ });
75
+ }
76
+ else {
77
+ rl.question(question, (answer) => {
78
+ rl.close();
79
+ resolve(answer);
80
+ });
81
+ }
82
+ });
83
+ }
84
+ function extractCommandFailure(error) {
85
+ if (!(error instanceof Error))
86
+ return 'Command failed for an unknown reason.';
87
+ const execError = error;
88
+ if (typeof execError.stderr === 'string' && execError.stderr.trim())
89
+ return execError.stderr.trim();
90
+ if (Buffer.isBuffer(execError.stderr) && execError.stderr.length > 0) {
91
+ return execError.stderr.toString('utf-8').trim();
92
+ }
93
+ if (typeof execError.stdout === 'string' && execError.stdout.trim())
94
+ return execError.stdout.trim();
95
+ if (Buffer.isBuffer(execError.stdout) && execError.stdout.length > 0) {
96
+ return execError.stdout.toString('utf-8').trim();
97
+ }
98
+ return error.message;
99
+ }
100
+ export function toSqliteStringLiteral(value) {
101
+ return `'${value.replace(/'/g, "''")}'`;
102
+ }
103
+ async function resetViaD1Direct(projectDir, email, newPassword, local) {
104
+ if (!local) {
105
+ const isTTY = Boolean(process.stdout.isTTY);
106
+ await ensureCloudflareAuth(projectDir, isTTY);
107
+ }
108
+ const dbName = resolveManagedD1DatabaseName(projectDir, 'AUTH_DB');
109
+ if (!dbName) {
110
+ raiseCliError({
111
+ code: 'auth_db_not_found',
112
+ message: 'Could not resolve AUTH_DB for this EdgeBase project.',
113
+ hint: 'Check your edgebase.config.ts and wrangler.toml, then retry.',
114
+ });
115
+ }
116
+ const configDir = readProjectWranglerContext(projectDir).dir;
117
+ const localFlag = local ? ['--local'] : [];
118
+ if (!isQuiet()) {
119
+ console.log('🔄 Hashing password...');
120
+ }
121
+ const passwordHash = await hashPassword(newPassword);
122
+ const now = new Date().toISOString();
123
+ if (!isQuiet()) {
124
+ console.log('🔍 Checking admin account...');
125
+ }
126
+ const normalizedEmail = email.trim().toLowerCase();
127
+ try {
128
+ const checkOutput = execFileSync(wranglerCommand(), wranglerArgs([
129
+ 'wrangler', 'd1', 'execute', dbName,
130
+ ...localFlag,
131
+ '--command', `SELECT id, email FROM _admins WHERE LOWER(TRIM(email)) = ${toSqliteStringLiteral(normalizedEmail)}`,
132
+ '--json',
133
+ ]), {
134
+ cwd: configDir,
135
+ encoding: 'utf-8',
136
+ stdio: ['ignore', 'pipe', 'pipe'],
137
+ timeout: 30000,
138
+ });
139
+ const results = JSON.parse(checkOutput);
140
+ const rows = results?.[0]?.results ?? [];
141
+ if (rows.length === 0) {
142
+ raiseCliError({
143
+ code: 'admin_not_found',
144
+ message: `No admin found with email: ${email}`,
145
+ field: 'email',
146
+ hint: 'Check the admin email address and retry.',
147
+ });
148
+ }
149
+ const adminId = rows[0].id;
150
+ if (!isQuiet()) {
151
+ console.log('🔄 Resetting password...');
152
+ }
153
+ execFileSync(wranglerCommand(), wranglerArgs([
154
+ 'wrangler', 'd1', 'execute', dbName,
155
+ ...localFlag,
156
+ '--command', `UPDATE _admins SET passwordHash = ${toSqliteStringLiteral(passwordHash)}, updatedAt = ${toSqliteStringLiteral(now)} WHERE id = ${toSqliteStringLiteral(adminId)}`,
157
+ ]), {
158
+ cwd: configDir,
159
+ encoding: 'utf-8',
160
+ stdio: ['ignore', 'pipe', 'pipe'],
161
+ timeout: 30000,
162
+ });
163
+ execFileSync(wranglerCommand(), wranglerArgs([
164
+ 'wrangler', 'd1', 'execute', dbName,
165
+ ...localFlag,
166
+ '--command', `DELETE FROM _admin_sessions WHERE adminId = ${toSqliteStringLiteral(adminId)}`,
167
+ ]), {
168
+ cwd: configDir,
169
+ encoding: 'utf-8',
170
+ stdio: ['ignore', 'pipe', 'pipe'],
171
+ timeout: 30000,
172
+ });
173
+ return {
174
+ mode: 'd1_direct',
175
+ email,
176
+ local,
177
+ dbName,
178
+ sessionsRevoked: true,
179
+ };
180
+ }
181
+ catch (error) {
182
+ if (isCliStructuredError(error))
183
+ throw error;
184
+ const message = extractCommandFailure(error);
185
+ if (message.includes('no such table')) {
186
+ raiseCliError({
187
+ code: 'auth_db_not_initialized',
188
+ message: 'Auth database not initialized. Deploy your project first.',
189
+ });
190
+ }
191
+ raiseCliError({
192
+ code: 'admin_password_reset_failed',
193
+ message: `D1 operation failed: ${message}`,
194
+ hint: 'Check your Wrangler login, D1 permissions, and project configuration, then retry.',
195
+ });
196
+ }
197
+ }
198
+ export const adminCommand = new Command('admin')
199
+ .description('Admin management commands');
200
+ adminCommand
201
+ .command('reset-password')
202
+ .description('Reset admin password')
203
+ .option('--url <url>', 'Worker URL (default: EDGEBASE_URL or http://localhost:8787)')
204
+ .option('--service-key <key>', 'Service Key (or set EDGEBASE_SERVICE_KEY env)')
205
+ .option('--email <email>', 'Admin email (skip interactive prompt)')
206
+ .option('--password <password>', 'New password (skip interactive prompt)')
207
+ .option('--local', 'Use local D1 database (for local dev)')
208
+ .action(async (options) => {
209
+ const email = options.email ?? await prompt('Admin email: ', false, {
210
+ field: 'email',
211
+ hint: 'Rerun with --email <email>.',
212
+ message: 'An admin email is required before password reset can continue.',
213
+ });
214
+ const newPassword = options.password ?? await prompt('New password (min 8 chars): ', true, {
215
+ field: 'password',
216
+ hint: 'Rerun with --password <password>.',
217
+ message: 'A new password is required before password reset can continue.',
218
+ });
219
+ if (!email) {
220
+ raiseNeedsInput({
221
+ code: 'admin_email_required',
222
+ field: 'email',
223
+ message: 'An admin email is required before password reset can continue.',
224
+ hint: 'Rerun with --email <email>.',
225
+ });
226
+ }
227
+ if (!newPassword) {
228
+ raiseNeedsInput({
229
+ code: 'admin_password_required',
230
+ field: 'password',
231
+ message: 'A new password is required before password reset can continue.',
232
+ hint: 'Rerun with --password <password>.',
233
+ });
234
+ }
235
+ if (newPassword.length < 8) {
236
+ raiseCliError({
237
+ code: 'admin_password_too_short',
238
+ field: 'password',
239
+ message: 'Password must be at least 8 characters.',
240
+ hint: 'Choose a password with at least 8 characters and rerun the command.',
241
+ });
242
+ }
243
+ const serviceKey = resolveOptionalServiceKey(options);
244
+ if (serviceKey) {
245
+ const url = resolveServerUrl({ url: options.url }, false) || 'http://localhost:8787';
246
+ if (!isQuiet()) {
247
+ console.log('\n🔄 Resetting admin password...');
248
+ }
249
+ try {
250
+ const resp = await fetchWithTimeout(`${url}/admin/api/internal/reset-password`, {
251
+ method: 'POST',
252
+ headers: {
253
+ 'Content-Type': 'application/json',
254
+ 'X-EdgeBase-Service-Key': serviceKey,
255
+ },
256
+ body: JSON.stringify({ email, newPassword }),
257
+ });
258
+ const data = await resp.json();
259
+ if (!resp.ok || !data.ok) {
260
+ raiseCliError({
261
+ code: 'admin_password_reset_failed',
262
+ message: `Failed: ${data.message || 'Unknown error'} (${data.code || resp.status})`,
263
+ hint: 'Check that the Worker is reachable and the service key has admin privileges.',
264
+ });
265
+ }
266
+ const result = {
267
+ mode: 'service_key',
268
+ email,
269
+ url,
270
+ sessionsRevoked: true,
271
+ };
272
+ if (isJson()) {
273
+ console.log(JSON.stringify({
274
+ status: 'success',
275
+ ...result,
276
+ }));
277
+ return;
278
+ }
279
+ console.log(chalk.green('✅'), 'Password reset successfully. All admin sessions have been revoked.');
280
+ return;
281
+ }
282
+ catch (error) {
283
+ if (isCliStructuredError(error))
284
+ throw error;
285
+ raiseCliError({
286
+ code: 'admin_connection_failed',
287
+ message: `Connection failed: ${error.message}`,
288
+ hint: 'Make sure the Worker is running and the URL is correct.',
289
+ });
290
+ }
291
+ }
292
+ const local = Boolean(options.local);
293
+ if (!isQuiet()) {
294
+ console.log(chalk.dim(`\n No Service Key found. Using ${local ? 'local' : 'Cloudflare'} D1 direct access...\n`));
295
+ }
296
+ const projectDir = process.cwd();
297
+ const result = await resetViaD1Direct(projectDir, email, newPassword, local);
298
+ if (isJson()) {
299
+ console.log(JSON.stringify({
300
+ status: 'success',
301
+ ...result,
302
+ }));
303
+ return;
304
+ }
305
+ console.log(chalk.green('✅'), 'Password reset successfully. All admin sessions have been revoked.');
306
+ });
307
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/commands/admin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,148 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * `npx edgebase backup` — Portable backup & restore via Worker Admin API.
4
+ *
5
+ * - `backup create` — Download all DO + D1 + optional R2/secrets as JSON (or tar.gz)
6
+ * - `backup restore` — Restore from a backup file
7
+ *
8
+ * Backup JSON format v1.1:
9
+ * { version, timestamp, source, config?, secrets?, control, auth, databases, storage? }
10
+ *
11
+ * Authentication: Service Key via --service-key flag or EDGEBASE_SERVICE_KEY env var.
12
+ * Target: Worker URL via --url flag or EDGEBASE_URL env var.
13
+ */
14
+ interface BackupAPIOptions {
15
+ url: string;
16
+ serviceKey: string;
17
+ }
18
+ declare function apiCall<T>(opts: BackupAPIOptions, path: string, method?: 'GET' | 'POST', body?: unknown): Promise<T>;
19
+ declare function apiBinary(opts: BackupAPIOptions, path: string): Promise<{
20
+ buffer: ArrayBuffer;
21
+ contentType: string;
22
+ }>;
23
+ declare function apiUpload(opts: BackupAPIOptions, path: string, body: Buffer | Uint8Array, contentType: string): Promise<void>;
24
+ interface DODump {
25
+ doName: string;
26
+ doType: 'database' | 'auth';
27
+ schema?: Record<string, string>;
28
+ tables: Record<string, unknown[]>;
29
+ timestamp: string;
30
+ }
31
+ interface DataNamespaceDump {
32
+ type: 'data';
33
+ namespace: string;
34
+ tables: Record<string, unknown[]>;
35
+ tableOrder?: string[];
36
+ timestamp: string;
37
+ }
38
+ interface StorageObject {
39
+ key: string;
40
+ size: number;
41
+ etag: string;
42
+ contentType: string;
43
+ }
44
+ /** v1.1 backup format — */
45
+ interface BackupFileV1_1 {
46
+ version: '1.1';
47
+ timestamp: string;
48
+ source: string;
49
+ config?: Record<string, unknown>;
50
+ secrets?: Record<string, string>;
51
+ control: {
52
+ d1: Record<string, unknown[]>;
53
+ };
54
+ auth: {
55
+ d1: Record<string, unknown[]>;
56
+ shards: Record<string, DODump>;
57
+ };
58
+ databases: Record<string, DODump>;
59
+ dataNamespaces?: Record<string, DataNamespaceDump>;
60
+ storage?: {
61
+ objects: StorageObject[];
62
+ };
63
+ }
64
+ declare function resolveOptions(options: {
65
+ url?: string;
66
+ serviceKey?: string;
67
+ }): BackupAPIOptions;
68
+ /**
69
+ * Run async tasks with a concurrency limit.
70
+ * Returns results in the same order as the input tasks.
71
+ */
72
+ declare function throttle<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]>;
73
+ /**
74
+ * Run async tasks with a concurrency limit and collect both fulfilled/rejected results.
75
+ * Results stay aligned with the input task order.
76
+ */
77
+ declare function throttleSettled<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<Array<PromiseSettledResult<T>>>;
78
+ declare function errorMessage(err: unknown): string;
79
+ declare function outputJson(payload: Record<string, unknown>): void;
80
+ declare function logHuman(...args: unknown[]): void;
81
+ declare function logHumanError(...args: unknown[]): void;
82
+ declare function writeHuman(text: string): void;
83
+ declare function collectSettledFailures<T>(results: Array<PromiseSettledResult<T>>, labels: string[]): string[];
84
+ declare function summarizeFailures(stage: string, failures: string[], max?: number): string;
85
+ declare function parseBackupFile(raw: unknown): BackupFileV1_1;
86
+ interface DownloadSessionPaths {
87
+ sessionDir: string;
88
+ storageDir: string;
89
+ manifestPath: string;
90
+ }
91
+ declare function resolveDownloadSessionPaths(edgebaseTmpDir: string, timestamp: string, resumeStorageDir?: string | null): DownloadSessionPaths;
92
+ /** Parse .dev.vars file → key/value map */
93
+ declare function parseDevVars(filePath: string): Record<string, string>;
94
+ /** Read secrets from environment */
95
+ declare function readSecrets(projectDir: string): Record<string, string> | null;
96
+ /** Write secrets to environment */
97
+ declare function writeSecrets(projectDir: string, secrets: Record<string, string>): void;
98
+ /** Recursively collect all files in a directory */
99
+ declare function collectFiles(dir: string, base?: string): Array<{
100
+ path: string;
101
+ rel: string;
102
+ }>;
103
+ export interface CloudflareAPIOptions {
104
+ accountId: string;
105
+ apiToken: string;
106
+ }
107
+ /**
108
+ * Enumerate all DO instances via Cloudflare REST API.
109
+ * Returns hex IDs of DOs that have stored data.
110
+ * Uses cursor pagination for large namespaces.
111
+ */
112
+ export declare function enumerateDOsViaCFAPI(cf: CloudflareAPIOptions, namespaceId: string): Promise<string[]>;
113
+ /**
114
+ * Get all DO namespace IDs for this worker via Cloudflare REST API.
115
+ * Returns array of { id, name, class } for each namespace.
116
+ */
117
+ export declare function getCFNamespaces(cf: CloudflareAPIOptions): Promise<Array<{
118
+ id: string;
119
+ name: string;
120
+ class: string;
121
+ }>>;
122
+ export declare const backupCommand: Command;
123
+ /** Exported for testing */
124
+ export declare const _internals: {
125
+ apiCall: typeof apiCall;
126
+ apiBinary: typeof apiBinary;
127
+ apiUpload: typeof apiUpload;
128
+ parseDevVars: typeof parseDevVars;
129
+ readSecrets: typeof readSecrets;
130
+ writeSecrets: typeof writeSecrets;
131
+ collectFiles: typeof collectFiles;
132
+ resolveOptions: typeof resolveOptions;
133
+ throttle: typeof throttle;
134
+ throttleSettled: typeof throttleSettled;
135
+ errorMessage: typeof errorMessage;
136
+ outputJson: typeof outputJson;
137
+ logHuman: typeof logHuman;
138
+ logHumanError: typeof logHumanError;
139
+ writeHuman: typeof writeHuman;
140
+ collectSettledFailures: typeof collectSettledFailures;
141
+ summarizeFailures: typeof summarizeFailures;
142
+ parseBackupFile: typeof parseBackupFile;
143
+ resolveDownloadSessionPaths: typeof resolveDownloadSessionPaths;
144
+ enumerateDOsViaCFAPI: typeof enumerateDOsViaCFAPI;
145
+ getCFNamespaces: typeof getCFNamespaces;
146
+ };
147
+ export {};
148
+ //# sourceMappingURL=backup.d.ts.map