@rebasepro/cli 0.23.0 → 0.24.1-canary.g19596ef
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -3
- package/bin/rebase.js +4 -1
- package/dist/agent-setup-B31F00DC.js +324 -0
- package/dist/agent-setup-B31F00DC.js.map +1 -0
- package/dist/api-keys-Bl1I9q7M.js +525 -0
- package/dist/api-keys-Bl1I9q7M.js.map +1 -0
- package/dist/apps-CNgQJjg5.js +340 -0
- package/dist/apps-CNgQJjg5.js.map +1 -0
- package/dist/args-BnmsEXvu.js +109 -0
- package/dist/args-BnmsEXvu.js.map +1 -0
- package/dist/atlas-dev-database-D_LP_Woq.js +62 -0
- package/dist/atlas-dev-database-D_LP_Woq.js.map +1 -0
- package/dist/auth-aySHEF45.js +414 -0
- package/dist/auth-aySHEF45.js.map +1 -0
- package/dist/branch-pointer-DvSHBjjz.js +2 -0
- package/dist/build-DIHWIqO4.js +336 -0
- package/dist/build-DIHWIqO4.js.map +1 -0
- package/dist/bundle-CqURVN-K.js +1621 -0
- package/dist/bundle-CqURVN-K.js.map +1 -0
- package/dist/bundle.d.ts +12 -3
- package/dist/cli.d.ts +23 -2
- package/dist/cloud-DjByQlkW.js +9667 -0
- package/dist/cloud-DjByQlkW.js.map +1 -0
- package/dist/collection-drift-BKj_BoMq.js +106 -0
- package/dist/collection-drift-BKj_BoMq.js.map +1 -0
- package/dist/commands/__test_support__/parser-specs.d.ts +13 -0
- package/dist/commands/agent-setup.d.ts +116 -0
- package/dist/commands/api-keys.d.ts +86 -23
- package/dist/commands/apps.d.ts +17 -0
- package/dist/commands/auth.d.ts +7 -0
- package/dist/commands/build.d.ts +5 -1
- package/dist/commands/cloud/auth.d.ts +4 -3
- package/dist/commands/cloud/bundle-deploy.d.ts +45 -0
- package/dist/commands/cloud/context.d.ts +44 -5
- package/dist/commands/cloud/cron.d.ts +53 -0
- package/dist/commands/cloud/debug.d.ts +134 -0
- package/dist/commands/cloud/index.d.ts +89 -12
- package/dist/commands/cloud/token-capabilities.d.ts +76 -0
- package/dist/commands/cloud/tokens.d.ts +23 -0
- package/dist/commands/console.d.ts +12 -0
- package/dist/commands/db.d.ts +79 -25
- package/dist/commands/dev.d.ts +181 -13
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/generate_sdk.d.ts +29 -2
- package/dist/commands/init.d.ts +115 -14
- package/dist/commands/schema.d.ts +6 -0
- package/dist/commands/skills.d.ts +126 -7
- package/dist/commands/start.d.ts +44 -0
- package/dist/commands/storage.d.ts +46 -0
- package/dist/commands/upgrade.d.ts +1 -0
- package/dist/consent-ClRHmcxf.js +76 -0
- package/dist/consent-ClRHmcxf.js.map +1 -0
- package/dist/console-D6SJf8k_.js +102 -0
- package/dist/console-D6SJf8k_.js.map +1 -0
- package/dist/context-BqhRydBg.js +1234 -0
- package/dist/context-BqhRydBg.js.map +1 -0
- package/dist/{daemon-entry-LTFKtpHy.js → daemon-entry-Da-D3rmH.js} +3 -4
- package/dist/daemon-entry-Da-D3rmH.js.map +1 -0
- package/dist/daemon-pzsQwDHa.js +2 -0
- package/dist/db-B7RuNuaQ.js +1312 -0
- package/dist/db-B7RuNuaQ.js.map +1 -0
- package/dist/derive-Dl0z2OWi.js +484 -0
- package/dist/derive-Dl0z2OWi.js.map +1 -0
- package/dist/dev-CYr_WXan.js +1599 -0
- package/dist/dev-CYr_WXan.js.map +1 -0
- package/dist/dev-db/atlas-dev-database.d.ts +32 -0
- package/dist/dev-db/daemon-entry.d.ts +13 -0
- package/dist/dev-db/daemon.d.ts +10 -0
- package/dist/dev-db/last-dev-database.d.ts +41 -0
- package/dist/dev-db/prepare.d.ts +29 -3
- package/dist/dev-db/pull.d.ts +90 -5
- package/dist/dev-db/resolve.d.ts +26 -2
- package/dist/dev-preflight-B-LYyBf1.js +2 -0
- package/dist/dev-server-DG8Tt-uf.js +96 -0
- package/dist/dev-server-DG8Tt-uf.js.map +1 -0
- package/dist/doctor-BP8cZ-7F.js +771 -0
- package/dist/doctor-BP8cZ-7F.js.map +1 -0
- package/dist/eject-DizdoecV.js +335 -0
- package/dist/eject-DizdoecV.js.map +1 -0
- package/dist/fold-static-BC9CYicw.js +201 -0
- package/dist/fold-static-BC9CYicw.js.map +1 -0
- package/dist/fold-static.d.ts +26 -3
- package/dist/function-portability-BIvlvR9q.js +265 -0
- package/dist/function-portability-BIvlvR9q.js.map +1 -0
- package/dist/generate_sdk-BPqdJc3Q.js +489 -0
- package/dist/generate_sdk-BPqdJc3Q.js.map +1 -0
- package/dist/index.es.js +199 -22095
- package/dist/index.es.js.map +1 -1
- package/dist/init-Utstvh2Q.js +1149 -0
- package/dist/init-Utstvh2Q.js.map +1 -0
- package/dist/last-dev-database-B58g89uA.js +2 -0
- package/dist/manifest-DRp0UVTj.js +880 -0
- package/dist/manifest-DRp0UVTj.js.map +1 -0
- package/dist/manifest.d.ts +56 -4
- package/dist/normalize-imports-X0Tgze9y.js +107 -0
- package/dist/normalize-imports-X0Tgze9y.js.map +1 -0
- package/dist/package-manager-DSEOwTqM.js +193 -0
- package/dist/package-manager-DSEOwTqM.js.map +1 -0
- package/dist/path-flags-BFgG9V6y.js +91 -0
- package/dist/path-flags-BFgG9V6y.js.map +1 -0
- package/dist/precompress.d.ts +17 -0
- package/dist/prepare-CDN6lSpz.js +1236 -0
- package/dist/prepare-CDN6lSpz.js.map +1 -0
- package/dist/{project-3WCbrrfW.js → project-Wp2zoyeN.js} +34 -184
- package/dist/project-Wp2zoyeN.js.map +1 -0
- package/dist/pull-CrGYMEsy.js +458 -0
- package/dist/pull-CrGYMEsy.js.map +1 -0
- package/dist/resolve-B2O-wKKk.js +2 -0
- package/dist/resources-FD7AfZx8.js +183 -0
- package/dist/resources-FD7AfZx8.js.map +1 -0
- package/dist/schema-DMdr431S.js +125 -0
- package/dist/schema-DMdr431S.js.map +1 -0
- package/dist/skills-DTFibT1m.js +642 -0
- package/dist/skills-DTFibT1m.js.map +1 -0
- package/dist/start-DEa-hOBh.js +267 -0
- package/dist/start-DEa-hOBh.js.map +1 -0
- package/dist/{state-C59Elrnt.js → state-Do7ZJYkF.js} +49 -4
- package/dist/state-Do7ZJYkF.js.map +1 -0
- package/dist/status-DxnJTekv.js +352 -0
- package/dist/status-DxnJTekv.js.map +1 -0
- package/dist/storage-DyVq-f_F.js +303 -0
- package/dist/storage-DyVq-f_F.js.map +1 -0
- package/dist/telemetry/identity.d.ts +10 -1
- package/dist/telemetry-C8Uq8phb.js +129 -0
- package/dist/telemetry-C8Uq8phb.js.map +1 -0
- package/dist/telemetry-EMFRVRQi.js +351 -0
- package/dist/telemetry-EMFRVRQi.js.map +1 -0
- package/dist/unknown-command-DNwDcX3w.js +98 -0
- package/dist/unknown-command-DNwDcX3w.js.map +1 -0
- package/dist/upgrade-CtZtRkTE.js +1332 -0
- package/dist/upgrade-CtZtRkTE.js.map +1 -0
- package/dist/upgrade.d.ts +38 -5
- package/dist/utils/dev-preflight.d.ts +47 -5
- package/dist/utils/dev-server.d.ts +30 -0
- package/dist/utils/path-flags.d.ts +31 -0
- package/dist/utils/project.d.ts +16 -0
- package/dist/utils/temp-archive.d.ts +9 -0
- package/dist/version-Buyyo1ut.js +58 -0
- package/dist/version-Buyyo1ut.js.map +1 -0
- package/package.json +7 -7
- package/templates/eject/Dockerfile +4 -2
- package/templates/eject/backend/src/env.ts +1 -1
- package/templates/eject/backend/src/index.ts +42 -4
- package/templates/eject/docker-compose.custom.yml +8 -4
- package/templates/generated-schemas/blank.ts +40 -0
- package/templates/generated-schemas/blog.ts +127 -0
- package/templates/generated-schemas/ecommerce.ts +93 -0
- package/templates/overlays/baas/ai-instructions.md +1 -1
- package/templates/overlays/baas/config/package.json +1 -0
- package/templates/overlays/baas/config/storage.ts +5 -3
- package/templates/overlays/baas/package.json +1 -0
- package/templates/template/.cursorrules +1 -1
- package/templates/template/.env.example +20 -10
- package/templates/template/.github/copilot-instructions.md +1 -1
- package/templates/template/.mcp.json +2 -2
- package/templates/template/.windsurfrules +1 -1
- package/templates/template/AGENTS.md +1 -1
- package/templates/template/CLAUDE.md +1 -1
- package/templates/template/README.md +21 -15
- package/templates/template/ai-instructions.md +5 -4
- package/templates/template/backend/functions/hello.ts +8 -0
- package/templates/template/backend/package.json +1 -1
- package/templates/template/config/resources.ts +7 -6
- package/templates/template/config/storage.ts +5 -3
- package/templates/template/docker-compose.yml +15 -9
- package/templates/template/frontend/vite.config.ts +13 -3
- package/templates/template/gitignore +6 -1
- package/templates/template/package.json +5 -3
- package/templates/template/scripts/example.ts +6 -4
- package/templates/template/tsconfig.json +25 -0
- package/dist/branch-pointer-dBiClJ0p.js +0 -111
- package/dist/branch-pointer-dBiClJ0p.js.map +0 -1
- package/dist/constraints-DKGbNfUW.js +0 -48
- package/dist/constraints-DKGbNfUW.js.map +0 -1
- package/dist/daemon-DR9Tk0La.js +0 -355
- package/dist/daemon-DR9Tk0La.js.map +0 -1
- package/dist/daemon-entry-LTFKtpHy.js.map +0 -1
- package/dist/dev-preflight-CNLl4rdo.js +0 -367
- package/dist/dev-preflight-CNLl4rdo.js.map +0 -1
- package/dist/project-3WCbrrfW.js.map +0 -1
- package/dist/pull-Dywm5FWP.js +0 -232
- package/dist/pull-Dywm5FWP.js.map +0 -1
- package/dist/resolve-BAeRUBhg.js +0 -74
- package/dist/resolve-BAeRUBhg.js.map +0 -1
- package/dist/state-C59Elrnt.js.map +0 -1
- package/templates/template/backend/src/schema.generated.ts +0 -13
|
@@ -18,14 +18,32 @@
|
|
|
18
18
|
* A subdirectory layout has no such problem: the rule file already sits beside
|
|
19
19
|
* its own assets, so `references/x.md` resolves as written and nothing is
|
|
20
20
|
* loaded until it is opened.
|
|
21
|
+
*
|
|
22
|
+
* `homeMarkers` are the directories under `~` that say the assistant is
|
|
23
|
+
* installed on this machine. They answer a different question from
|
|
24
|
+
* `detectDir`: a fresh scaffold has no `.claude/` of its own, so `rebase init`
|
|
25
|
+
* asks the machine which assistants the developer has and pre-selects those.
|
|
26
|
+
*
|
|
27
|
+
* `mcp` is where the assistant reads a *project-level* MCP server list, and in
|
|
28
|
+
* which shape — see `agent-setup.ts`. `projectDir` is what `REBASE_PROJECT_DIR`
|
|
29
|
+
* is set to: `"."` where the server is spawned in the project, the editor's own
|
|
30
|
+
* workspace variable where it may not be. `null` means there is no project
|
|
31
|
+
* file to write: Windsurf reads only a user-level config, and one entry there
|
|
32
|
+
* cannot name every project on the machine.
|
|
21
33
|
*/
|
|
22
|
-
declare const AGENTS: {
|
|
34
|
+
export declare const AGENTS: {
|
|
23
35
|
readonly cursor: {
|
|
24
36
|
readonly label: "Cursor";
|
|
25
37
|
readonly detectDir: ".cursor";
|
|
38
|
+
readonly homeMarkers: readonly [".cursor"];
|
|
26
39
|
readonly targetDir: ".cursor/rules";
|
|
27
40
|
readonly flatLayout: true;
|
|
28
41
|
readonly indexFile: "rebase.mdc";
|
|
42
|
+
readonly mcp: {
|
|
43
|
+
readonly file: ".cursor/mcp.json";
|
|
44
|
+
readonly format: "mcpServers";
|
|
45
|
+
readonly projectDir: "${workspaceFolder}";
|
|
46
|
+
};
|
|
29
47
|
/** The body is not a rule file here — `indexFile` is. */
|
|
30
48
|
readonly transformFile: (skillName: string, content: string) => {
|
|
31
49
|
fileName: string;
|
|
@@ -35,8 +53,14 @@ declare const AGENTS: {
|
|
|
35
53
|
readonly claude: {
|
|
36
54
|
readonly label: "Claude Code";
|
|
37
55
|
readonly detectDir: ".claude";
|
|
56
|
+
readonly homeMarkers: readonly [".claude"];
|
|
38
57
|
readonly targetDir: ".claude/skills";
|
|
39
58
|
readonly flatLayout: false;
|
|
59
|
+
readonly mcp: {
|
|
60
|
+
readonly file: ".mcp.json";
|
|
61
|
+
readonly format: "mcpServers";
|
|
62
|
+
readonly projectDir: ".";
|
|
63
|
+
};
|
|
40
64
|
/** Claude Code uses the standard SKILL.md format in subdirectories. */
|
|
41
65
|
readonly transformFile: (skillName: string, content: string) => {
|
|
42
66
|
fileName: string;
|
|
@@ -46,9 +70,11 @@ declare const AGENTS: {
|
|
|
46
70
|
readonly windsurf: {
|
|
47
71
|
readonly label: "Windsurf";
|
|
48
72
|
readonly detectDir: ".windsurf";
|
|
73
|
+
readonly homeMarkers: readonly [".codeium/windsurf", ".windsurf"];
|
|
49
74
|
readonly targetDir: ".windsurf/rules";
|
|
50
75
|
readonly flatLayout: true;
|
|
51
76
|
readonly indexFile: "rebase.md";
|
|
77
|
+
readonly mcp: null;
|
|
52
78
|
/** The body is not a rule file here — `indexFile` is. */
|
|
53
79
|
readonly transformFile: (skillName: string, content: string) => {
|
|
54
80
|
fileName: string;
|
|
@@ -58,8 +84,14 @@ declare const AGENTS: {
|
|
|
58
84
|
readonly gemini: {
|
|
59
85
|
readonly label: "Gemini CLI / Antigravity";
|
|
60
86
|
readonly detectDir: ".agents";
|
|
87
|
+
readonly homeMarkers: readonly [".gemini"];
|
|
61
88
|
readonly targetDir: ".agents/skills";
|
|
62
89
|
readonly flatLayout: false;
|
|
90
|
+
readonly mcp: {
|
|
91
|
+
readonly file: ".gemini/settings.json";
|
|
92
|
+
readonly format: "mcpServers";
|
|
93
|
+
readonly projectDir: ".";
|
|
94
|
+
};
|
|
63
95
|
/** Gemini uses the standard SKILL.md format in subdirectories. */
|
|
64
96
|
readonly transformFile: (skillName: string, content: string) => {
|
|
65
97
|
fileName: string;
|
|
@@ -69,9 +101,15 @@ declare const AGENTS: {
|
|
|
69
101
|
readonly codex: {
|
|
70
102
|
readonly label: "Codex CLI";
|
|
71
103
|
readonly detectDir: ".codex";
|
|
72
|
-
readonly
|
|
104
|
+
readonly homeMarkers: readonly [".codex"];
|
|
105
|
+
readonly targetDir: ".agents/skills";
|
|
73
106
|
readonly flatLayout: false;
|
|
74
|
-
|
|
107
|
+
readonly mcp: {
|
|
108
|
+
readonly file: ".codex/config.toml";
|
|
109
|
+
readonly format: "codexToml";
|
|
110
|
+
readonly projectDir: ".";
|
|
111
|
+
};
|
|
112
|
+
/** Codex uses the standard SKILL.md format in subdirectories. */
|
|
75
113
|
readonly transformFile: (skillName: string, content: string) => {
|
|
76
114
|
fileName: string;
|
|
77
115
|
content: string;
|
|
@@ -80,9 +118,15 @@ declare const AGENTS: {
|
|
|
80
118
|
readonly kiro: {
|
|
81
119
|
readonly label: "Kiro";
|
|
82
120
|
readonly detectDir: ".kiro";
|
|
121
|
+
readonly homeMarkers: readonly [".kiro"];
|
|
83
122
|
readonly targetDir: ".kiro/steering";
|
|
84
123
|
readonly flatLayout: true;
|
|
85
124
|
readonly indexFile: "rebase.md";
|
|
125
|
+
readonly mcp: {
|
|
126
|
+
readonly file: ".kiro/settings/mcp.json";
|
|
127
|
+
readonly format: "mcpServers";
|
|
128
|
+
readonly projectDir: ".";
|
|
129
|
+
};
|
|
86
130
|
/** The body is not a rule file here — `indexFile` is. */
|
|
87
131
|
readonly transformFile: (skillName: string, content: string) => {
|
|
88
132
|
fileName: string;
|
|
@@ -92,9 +136,15 @@ declare const AGENTS: {
|
|
|
92
136
|
readonly copilot: {
|
|
93
137
|
readonly label: "GitHub Copilot";
|
|
94
138
|
readonly detectDir: null;
|
|
139
|
+
readonly homeMarkers: readonly [];
|
|
95
140
|
readonly targetDir: ".github/instructions";
|
|
96
141
|
readonly flatLayout: true;
|
|
97
142
|
readonly indexFile: "rebase.instructions.md";
|
|
143
|
+
readonly mcp: {
|
|
144
|
+
readonly file: ".vscode/mcp.json";
|
|
145
|
+
readonly format: "vscode";
|
|
146
|
+
readonly projectDir: "${workspaceFolder}";
|
|
147
|
+
};
|
|
98
148
|
/** The body is not a rule file here — `indexFile` is. */
|
|
99
149
|
readonly transformFile: (skillName: string, content: string) => {
|
|
100
150
|
fileName: string;
|
|
@@ -102,7 +152,11 @@ declare const AGENTS: {
|
|
|
102
152
|
};
|
|
103
153
|
};
|
|
104
154
|
};
|
|
105
|
-
type AgentKey = keyof typeof AGENTS;
|
|
155
|
+
export type AgentKey = keyof typeof AGENTS;
|
|
156
|
+
/** Narrows a string to an agent name, by the table's own keys. */
|
|
157
|
+
export declare function isAgentKey(value: string): value is AgentKey;
|
|
158
|
+
/** Every agent, in table order. */
|
|
159
|
+
export declare const AGENT_KEYS: AgentKey[];
|
|
106
160
|
export interface LoadedSkill {
|
|
107
161
|
name: string;
|
|
108
162
|
/** Absolute path of the skill's source directory. */
|
|
@@ -113,6 +167,13 @@ export interface LoadedSkill {
|
|
|
113
167
|
}
|
|
114
168
|
/** Read all skill directories and return their names, content and assets. */
|
|
115
169
|
export declare function loadSkills(skillsDir: string): LoadedSkill[];
|
|
170
|
+
/**
|
|
171
|
+
* The skills this CLI ships, from its own `@rebasepro/agent-skills`.
|
|
172
|
+
*
|
|
173
|
+
* Throws rather than exiting, so `rebase init` can report a missing bundle as a
|
|
174
|
+
* warning and still finish the scaffold.
|
|
175
|
+
*/
|
|
176
|
+
export declare function loadBundledSkills(): LoadedSkill[];
|
|
116
177
|
/**
|
|
117
178
|
* The one always-on rule a flat-layout agent gets, in place of every skill.
|
|
118
179
|
*
|
|
@@ -136,11 +197,57 @@ export declare function renderSkillIndex(skills: LoadedSkill[], agentKey: AgentK
|
|
|
136
197
|
* guessing, because the wrong guess installs 21 files and reports success.
|
|
137
198
|
*/
|
|
138
199
|
export declare function detectAgents(projectDir: string): AgentKey[];
|
|
200
|
+
/** What `detectInstalledAgents` found for one assistant. */
|
|
201
|
+
export interface InstalledAgent {
|
|
202
|
+
key: AgentKey;
|
|
203
|
+
label: string;
|
|
204
|
+
/** The home directory checked, as `~/…` — the one found, else the first. */
|
|
205
|
+
marker: string | null;
|
|
206
|
+
found: boolean;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Which assistants are installed on this machine, from their home directories.
|
|
210
|
+
*
|
|
211
|
+
* The question `rebase init` needs answered, and one `detectAgents` cannot: a
|
|
212
|
+
* project that does not exist yet has no `.claude/` in it. What the machine has
|
|
213
|
+
* is only a default — the developer confirms it — so a false positive costs an
|
|
214
|
+
* unticked box, not 21 files nobody asked for.
|
|
215
|
+
*/
|
|
216
|
+
export declare function detectInstalledAgents(home?: string): InstalledAgent[];
|
|
139
217
|
/** Install skills for a specific agent into the project directory. */
|
|
140
|
-
|
|
218
|
+
/**
|
|
219
|
+
* The file in each target directory that records what the installer wrote:
|
|
220
|
+
* relative path → sha256 of the bytes written. A dotfile, so no agent loads it
|
|
221
|
+
* as a rule.
|
|
222
|
+
*/
|
|
223
|
+
export declare const SKILLS_MANIFEST = ".rebase-skills.json";
|
|
224
|
+
/** What one agent's install did. */
|
|
225
|
+
export interface AgentInstallResult {
|
|
141
226
|
skills: number;
|
|
142
227
|
assets: number;
|
|
143
|
-
|
|
228
|
+
/** Files left as they are because they were edited since the last install (relative to the target dir). */
|
|
229
|
+
kept: string[];
|
|
230
|
+
/** Files of skills the bundle no longer ships, removed because nobody edited them. */
|
|
231
|
+
removed: string[];
|
|
232
|
+
}
|
|
233
|
+
export declare function installForAgent(agentKey: AgentKey, skills: LoadedSkill[], projectDir: string, options?: {
|
|
234
|
+
force?: boolean;
|
|
235
|
+
}): AgentInstallResult;
|
|
236
|
+
/** What `installSkills` did for one agent. */
|
|
237
|
+
export interface SkillsInstallResult extends AgentInstallResult {
|
|
238
|
+
agent: AgentKey;
|
|
239
|
+
/** An earlier agent in the same run that already wrote this directory. */
|
|
240
|
+
sharedWith?: AgentKey;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Install for several agents, writing each target directory once.
|
|
244
|
+
*
|
|
245
|
+
* Gemini and Codex both read `.agents/skills`; installing twice would write the
|
|
246
|
+
* same 21 files twice and report two installs of one directory.
|
|
247
|
+
*/
|
|
248
|
+
export declare function installSkills(agents: readonly AgentKey[], skills: LoadedSkill[], projectDir: string, options?: {
|
|
249
|
+
force?: boolean;
|
|
250
|
+
}): SkillsInstallResult[];
|
|
144
251
|
/** Everything the switch below dispatches, for the did-you-mean. */
|
|
145
252
|
export declare const SKILLS_SUBCOMMANDS: readonly ["install"];
|
|
146
253
|
export declare function skillsCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
|
|
@@ -150,4 +257,16 @@ export declare function skillsCommand(subcommand: string | undefined, rawArgs: s
|
|
|
150
257
|
* given.
|
|
151
258
|
*/
|
|
152
259
|
export declare function parseAgentFlags(rawArgs: string[]): AgentKey[] | null;
|
|
153
|
-
|
|
260
|
+
/** `rebase skills install`'s whole line: the agents it names, `--mcp` and `--force`. */
|
|
261
|
+
export declare function parseSkillsInstallLine(rawArgs: string[]): {
|
|
262
|
+
agents: AgentKey[] | null;
|
|
263
|
+
mcp: boolean;
|
|
264
|
+
force: boolean;
|
|
265
|
+
};
|
|
266
|
+
/**
|
|
267
|
+
* The agents a list of `--agent` values names, or null when it names none.
|
|
268
|
+
*
|
|
269
|
+
* Shared by `rebase skills install` and `rebase init`, so both accept the same
|
|
270
|
+
* spellings. Throws a UsageError on a name that is not an agent.
|
|
271
|
+
*/
|
|
272
|
+
export declare function resolveAgentNames(values: readonly string[]): AgentKey[] | null;
|
package/dist/commands/start.d.ts
CHANGED
|
@@ -1 +1,45 @@
|
|
|
1
|
+
import type { RebaseBundleStatic } from "@rebasepro/types";
|
|
2
|
+
import type { DevDatabase } from "../dev-db/resolve.js";
|
|
3
|
+
/** The NODE_ENV the runtime will see, and where it comes from. */
|
|
4
|
+
export interface StartNodeEnv {
|
|
5
|
+
value: string | undefined;
|
|
6
|
+
source: "shell" | ".env" | "unset";
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* What NODE_ENV the server will boot in. The shell wins — dotenv never
|
|
10
|
+
* overrides a variable that is already set — then `.env`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function startNodeEnv(projectRoot: string): StartNodeEnv;
|
|
13
|
+
/**
|
|
14
|
+
* The banner for a `rebase start` that is not a production server, or `null`.
|
|
15
|
+
*
|
|
16
|
+
* Not forced to production: the scaffold's `.env` points at a loopback
|
|
17
|
+
* database, which a production boot refuses, so forcing it would break the
|
|
18
|
+
* documented local run. What must not happen is the silence — a command the
|
|
19
|
+
* help called "(production)" booting with the first-registration window open.
|
|
20
|
+
*/
|
|
21
|
+
export declare function nonProductionWarning(nodeEnv: StartNodeEnv): string[] | null;
|
|
22
|
+
/**
|
|
23
|
+
* What to say about the apps a bundle serves only on their own hostname.
|
|
24
|
+
*
|
|
25
|
+
* The runtime prints "Server running at http://localhost:<port>", and an app
|
|
26
|
+
* whose `path` names a hostname answers only requests carrying that `Host` —
|
|
27
|
+
* so opening the printed URL showed a 404 for an app that was running fine,
|
|
28
|
+
* and nothing said why. One line per such app, with a command that reaches it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function hostRoutedNotice(staticApps: readonly RebaseBundleStatic[], port: string | undefined): string[];
|
|
31
|
+
/**
|
|
32
|
+
* What to say when there is no DATABASE_URL for the runtime, or `null`.
|
|
33
|
+
*
|
|
34
|
+
* The runtime requires one, and its refusal — `DATABASE_URL: is required`, and
|
|
35
|
+
* a link to the self-hosting docs — is right for a deployment and says nothing
|
|
36
|
+
* to the reader most likely to see it: someone running the scaffold's own
|
|
37
|
+
* `.env`, which leaves DATABASE_URL commented out because `rebase dev` brings a
|
|
38
|
+
* database of its own. That database is one command away, so this names it.
|
|
39
|
+
*
|
|
40
|
+
* `kind` is what `rebase dev` runs this project on, so the line can say which
|
|
41
|
+
* database `rebase db url` will print. A blank value is unset, as the runtime
|
|
42
|
+
* reads it.
|
|
43
|
+
*/
|
|
44
|
+
export declare function missingDatabaseUrl(env: Record<string, string | undefined>, kind: DevDatabase["kind"] | null): string[] | null;
|
|
1
45
|
export declare function startCommand(rawArgs?: string[]): Promise<void>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Everything the switch below dispatches, for the did-you-mean. */
|
|
2
|
+
export declare const STORAGE_SUBCOMMANDS: readonly ["orphans", "move"];
|
|
3
|
+
/** The flags `rebase storage orphans` takes. */
|
|
4
|
+
export declare const ORPHANS_FLAGS: {
|
|
5
|
+
readonly "--source": StringConstructor;
|
|
6
|
+
readonly "--older-than": NumberConstructor;
|
|
7
|
+
readonly "--delete": BooleanConstructor;
|
|
8
|
+
readonly "--yes": BooleanConstructor;
|
|
9
|
+
readonly "-y": "--yes";
|
|
10
|
+
readonly "--json": BooleanConstructor;
|
|
11
|
+
};
|
|
12
|
+
/** The flags `rebase storage move` takes. */
|
|
13
|
+
export declare const MOVE_FLAGS: {
|
|
14
|
+
readonly "--from": StringConstructor;
|
|
15
|
+
readonly "--to": StringConstructor;
|
|
16
|
+
readonly "--prefix": StringConstructor;
|
|
17
|
+
readonly "--delete-source": BooleanConstructor;
|
|
18
|
+
readonly "--json": BooleanConstructor;
|
|
19
|
+
};
|
|
20
|
+
/** One stored object, as the backend lists it. */
|
|
21
|
+
interface StoredObjectEntry {
|
|
22
|
+
key: string;
|
|
23
|
+
size?: number;
|
|
24
|
+
updated?: string;
|
|
25
|
+
}
|
|
26
|
+
/** What `GET /admin/storage/orphans` answers. */
|
|
27
|
+
export interface OrphanReport {
|
|
28
|
+
storageId: string;
|
|
29
|
+
objects: number;
|
|
30
|
+
orphans: StoredObjectEntry[];
|
|
31
|
+
recent: number;
|
|
32
|
+
scanned: string[];
|
|
33
|
+
unscanned: {
|
|
34
|
+
collection: string;
|
|
35
|
+
reason: string;
|
|
36
|
+
}[];
|
|
37
|
+
}
|
|
38
|
+
/** Bytes, as a person reads them. */
|
|
39
|
+
export declare function formatBytes(bytes: number): string;
|
|
40
|
+
/**
|
|
41
|
+
* The lines that describe an orphan scan. Exported so its tests can read them
|
|
42
|
+
* without a server.
|
|
43
|
+
*/
|
|
44
|
+
export declare function describeOrphanReport(report: OrphanReport, olderThanHours: number): string[];
|
|
45
|
+
export declare function storageCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
|
|
46
|
+
export {};
|
|
@@ -2,6 +2,7 @@ import { type ChangedPin, type OverrideFinding, type SkippedSpec, type Unreadabl
|
|
|
2
2
|
/** Every flag `rebase upgrade` accepts. Its help page and the docs verifier read this. */
|
|
3
3
|
export declare const UPGRADE_FLAGS: {
|
|
4
4
|
readonly "--to": StringConstructor;
|
|
5
|
+
readonly "--allow-downgrade": BooleanConstructor;
|
|
5
6
|
readonly "--drop-local-overrides": BooleanConstructor;
|
|
6
7
|
readonly "--no-install": BooleanConstructor;
|
|
7
8
|
readonly "--dry-run": BooleanConstructor;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { a as setConsent, c as buildEvent, f as readConfig, o as suppressionReason } from "./telemetry-EMFRVRQi.js";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import inquirer from "inquirer";
|
|
4
|
+
//#region src/telemetry/consent.ts
|
|
5
|
+
/** True when we may ask: nothing forbids it, and there is a question to ask. */
|
|
6
|
+
function shouldPrompt(env = process.env, { reAskDeclined = false } = {}) {
|
|
7
|
+
if (!process.stdin.isTTY) return false;
|
|
8
|
+
const reason = suppressionReason(env);
|
|
9
|
+
if (reason === "not_asked") return true;
|
|
10
|
+
return reAskDeclined && reason === "declined";
|
|
11
|
+
}
|
|
12
|
+
function renderPreview(event, properties) {
|
|
13
|
+
const preview = buildEvent(event, properties, {
|
|
14
|
+
machineId: "<random uuid, generated only if you say yes>",
|
|
15
|
+
projectId: "<random uuid, per checkout>"
|
|
16
|
+
});
|
|
17
|
+
return JSON.stringify(preview, null, 2);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Ask, record the answer, and report it.
|
|
21
|
+
*
|
|
22
|
+
* Never throws and never blocks a non-interactive run: `rebase init --yes` in
|
|
23
|
+
* CI must behave exactly as it does today, which means not asking and not
|
|
24
|
+
* sending.
|
|
25
|
+
*/
|
|
26
|
+
async function promptForConsent(options = {}) {
|
|
27
|
+
if (!shouldPrompt(process.env, options)) return false;
|
|
28
|
+
const askedBefore = suppressionReason(process.env) === "declined";
|
|
29
|
+
try {
|
|
30
|
+
console.log("");
|
|
31
|
+
console.log(chalk.bold("Help improve Rebase?"));
|
|
32
|
+
console.log("");
|
|
33
|
+
console.log(chalk.gray(" Rebase is self-hosted, so we only learn what works if you tell us."));
|
|
34
|
+
console.log(chalk.gray(" Anonymous: random ids, the CLI version, your OS, and which template and"));
|
|
35
|
+
console.log(chalk.gray(" package manager you used. Never project names, paths, schemas, URLs or"));
|
|
36
|
+
console.log(chalk.gray(" error messages."));
|
|
37
|
+
console.log("");
|
|
38
|
+
console.log(chalk.gray(` Print the exact payload with ${chalk.cyan("rebase telemetry show")}; change your mind`));
|
|
39
|
+
console.log(chalk.gray(` any time with ${chalk.cyan("rebase telemetry disable")}.`));
|
|
40
|
+
if (askedBefore) {
|
|
41
|
+
console.log("");
|
|
42
|
+
console.log(chalk.gray(" You declined before; that stands unless you change it here."));
|
|
43
|
+
}
|
|
44
|
+
console.log("");
|
|
45
|
+
const { accepted } = await inquirer.prompt([{
|
|
46
|
+
type: "confirm",
|
|
47
|
+
name: "accepted",
|
|
48
|
+
message: "Share anonymous usage data?",
|
|
49
|
+
default: false
|
|
50
|
+
}]);
|
|
51
|
+
setConsent(Boolean(accepted));
|
|
52
|
+
console.log(accepted ? chalk.green(" Thank you — sharing enabled.") : chalk.gray(" Nothing will be sent." + (options.reAskDeclined ? " You will be asked again the next time you scaffold a project." : " You will not be asked again.")));
|
|
53
|
+
console.log("");
|
|
54
|
+
return Boolean(accepted);
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Human-readable current state, for `rebase telemetry status`. */
|
|
60
|
+
function describeState(env = process.env) {
|
|
61
|
+
const reason = suppressionReason(env);
|
|
62
|
+
const config = readConfig();
|
|
63
|
+
switch (reason) {
|
|
64
|
+
case null: return `${chalk.green("enabled")} — schema v1, machine id ${chalk.gray(config.machineId ?? "unset")}`;
|
|
65
|
+
case "not_asked": return `${chalk.yellow("not configured")} — nothing has been sent, and you have not been asked yet`;
|
|
66
|
+
case "declined": return `${chalk.gray("disabled")} — you declined${config.decidedAt ? ` on ${config.decidedAt.slice(0, 10)}` : ""}`;
|
|
67
|
+
case "do_not_track": return `${chalk.gray("disabled")} — the ${chalk.cyan("DO_NOT_TRACK")} environment variable is set`;
|
|
68
|
+
case "rebase_telemetry_disabled": return `${chalk.gray("disabled")} — the ${chalk.cyan("REBASE_TELEMETRY_DISABLED")} environment variable is set`;
|
|
69
|
+
case "ci": return `${chalk.gray("disabled")} — this looks like CI (${chalk.cyan("CI")} is set), which is never counted`;
|
|
70
|
+
case "project_opt_out": return `${chalk.gray("disabled")} — this project's ${chalk.cyan("rebase.json")} sets ${chalk.cyan("\"telemetry\": false")}`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { promptForConsent as n, renderPreview as r, describeState as t };
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=consent-ClRHmcxf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent-ClRHmcxf.js","names":[],"sources":["../src/telemetry/consent.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport inquirer from \"inquirer\";\n\nimport { buildEvent, TELEMETRY_SCHEMA_VERSION, TelemetryEventName } from \"./payload\";\nimport { readConfig } from \"./identity\";\nimport { setConsent, suppressionReason } from \"./index\";\n\n/**\n * Asking, and what the question looks like.\n *\n * ## Why the prompt comes *after* the work\n *\n * The first `rebase init` on a machine is the event most worth having, and it\n * is the one where no consent exists yet. Asking before scaffolding puts a\n * privacy negotiation in front of someone who has not yet seen the tool do\n * anything — the worst possible moment, and a reliable way to get a reflexive\n * no.\n *\n * So the question is asked once the project exists and the user has seen it\n * work. The event's data is still in memory at that point, so nothing is lost\n * by waiting, and — this is the part that matters — **nothing has been\n * transmitted or written**. Declining leaves no id, no file, no record.\n *\n * ## Why the payload is shown rather than described\n *\n * \"Anonymous usage data\" is a phrase that has been used to mean almost\n * anything. Printing the exact JSON costs four lines of output and replaces a\n * claim the user has to take on faith with something they can read. It is also\n * the same builder the sender uses, so it cannot drift into a comfortable\n * fiction.\n */\n\n/** Where the question is being asked from, which decides how often it may be. */\nexport interface PromptOptions {\n /**\n * Ask again even though this machine already declined.\n *\n * Set by `rebase init`, and only there. Scaffolding a project is a\n * deliberate, occasional act with a natural pause in it — not something\n * anyone does in a loop — so asking each time is an offer rather than\n * nagging, and it reaches the person whose first answer was a reflex before\n * they had seen the tool do anything.\n *\n * It does **not** re-ask someone who accepted: they are already sharing, so\n * the only thing another prompt could do is talk them out of it.\n *\n * Nothing else changes. `DO_NOT_TRACK`, `REBASE_TELEMETRY_DISABLED`, `CI`\n * and a project's `\"telemetry\": false` are answers, not questions, and they\n * still suppress the prompt entirely — a re-ask that could override a\n * committed repository policy would be exactly the consent-by-proxy the\n * policy exists to prevent.\n */\n reAskDeclined?: boolean;\n}\n\n/** True when we may ask: nothing forbids it, and there is a question to ask. */\nexport function shouldPrompt(\n env: NodeJS.ProcessEnv = process.env,\n { reAskDeclined = false }: PromptOptions = {}\n): boolean {\n if (!process.stdin.isTTY) return false;\n\n const reason = suppressionReason(env);\n // `not_asked` is the only reason that is a question rather than an answer.\n // A user who set DO_NOT_TRACK, or is on CI, has already told us — and so\n // has one who is already sharing (`null`), whom we never re-ask.\n if (reason === \"not_asked\") return true;\n return reAskDeclined && reason === \"declined\";\n}\n\nexport function renderPreview(event: TelemetryEventName, properties: Record<string, unknown>): string {\n const preview = buildEvent(event, properties, {\n machineId: \"<random uuid, generated only if you say yes>\",\n projectId: \"<random uuid, per checkout>\"\n });\n return JSON.stringify(preview, null, 2);\n}\n\n/**\n * Ask, record the answer, and report it.\n *\n * Never throws and never blocks a non-interactive run: `rebase init --yes` in\n * CI must behave exactly as it does today, which means not asking and not\n * sending.\n */\nexport async function promptForConsent(options: PromptOptions = {}): Promise<boolean> {\n if (!shouldPrompt(process.env, options)) return false;\n\n // Only true when this is a second (or later) asking, which the closing line\n // needs to know: \"you will not be asked again\" is false at `init`.\n const askedBefore = suppressionReason(process.env) === \"declined\";\n\n try {\n console.log(\"\");\n console.log(chalk.bold(\"Help improve Rebase?\"));\n console.log(\"\");\n console.log(chalk.gray(\" Rebase is self-hosted, so we only learn what works if you tell us.\"));\n console.log(chalk.gray(\" Anonymous: random ids, the CLI version, your OS, and which template and\"));\n console.log(chalk.gray(\" package manager you used. Never project names, paths, schemas, URLs or\"));\n console.log(chalk.gray(\" error messages.\"));\n console.log(\"\");\n console.log(chalk.gray(` Print the exact payload with ${chalk.cyan(\"rebase telemetry show\")}; change your mind`));\n console.log(chalk.gray(` any time with ${chalk.cyan(\"rebase telemetry disable\")}.`));\n if (askedBefore) {\n console.log(\"\");\n console.log(chalk.gray(\" You declined before; that stands unless you change it here.\"));\n }\n console.log(\"\");\n\n const { accepted } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"accepted\",\n message: \"Share anonymous usage data?\",\n // Defaults to no. Telemetry is off until somebody says yes, and\n // a bare Enter is the commonest answer to any prompt — so a\n // pre-selected yes would make pressing through `init` the\n // consent. `y` is one keystroke, and `rebase telemetry enable`\n // is the same answer later.\n default: false\n }\n ] as Parameters<typeof inquirer.prompt>[0]) as { accepted: boolean };\n\n setConsent(Boolean(accepted));\n\n console.log(\n accepted\n ? chalk.green(\" Thank you — sharing enabled.\")\n : chalk.gray(\n \" Nothing will be sent.\"\n + (options.reAskDeclined\n ? \" You will be asked again the next time you scaffold a project.\"\n : \" You will not be asked again.\")\n )\n );\n console.log(\"\");\n return Boolean(accepted);\n } catch {\n // A prompt that fails (piped stdin, a terminal that went away) is a\n // decline, and specifically a decline we do not persist — the user\n // never actually saw the question, so they should still get to answer\n // it another day.\n return false;\n }\n}\n\n/** Human-readable current state, for `rebase telemetry status`. */\nexport function describeState(env: NodeJS.ProcessEnv = process.env): string {\n const reason = suppressionReason(env);\n const config = readConfig();\n switch (reason) {\n case null:\n return `${chalk.green(\"enabled\")} — schema v${TELEMETRY_SCHEMA_VERSION}, machine id ${chalk.gray(config.machineId ?? \"unset\")}`;\n case \"not_asked\":\n return `${chalk.yellow(\"not configured\")} — nothing has been sent, and you have not been asked yet`;\n case \"declined\":\n return `${chalk.gray(\"disabled\")} — you declined${config.decidedAt ? ` on ${config.decidedAt.slice(0, 10)}` : \"\"}`;\n case \"do_not_track\":\n return `${chalk.gray(\"disabled\")} — the ${chalk.cyan(\"DO_NOT_TRACK\")} environment variable is set`;\n case \"rebase_telemetry_disabled\":\n return `${chalk.gray(\"disabled\")} — the ${chalk.cyan(\"REBASE_TELEMETRY_DISABLED\")} environment variable is set`;\n case \"ci\":\n return `${chalk.gray(\"disabled\")} — this looks like CI (${chalk.cyan(\"CI\")} is set), which is never counted`;\n case \"project_opt_out\":\n return `${chalk.gray(\"disabled\")} — this project's ${chalk.cyan(\"rebase.json\")} sets ${chalk.cyan('\"telemetry\": false')}`;\n }\n}\n"],"mappings":";;;;;AAwDA,SAAgB,aACZ,MAAyB,QAAQ,KACjC,EAAE,gBAAgB,UAAyB,CAAC,GACrC;CACP,IAAI,CAAC,QAAQ,MAAM,OAAO,OAAO;CAEjC,MAAM,SAAS,kBAAkB,GAAG;CAIpC,IAAI,WAAW,aAAa,OAAO;CACnC,OAAO,iBAAiB,WAAW;AACvC;AAEA,SAAgB,cAAc,OAA2B,YAA6C;CAClG,MAAM,UAAU,WAAW,OAAO,YAAY;EAC1C,WAAW;EACX,WAAW;CACf,CAAC;CACD,OAAO,KAAK,UAAU,SAAS,MAAM,CAAC;AAC1C;;;;;;;;AASA,eAAsB,iBAAiB,UAAyB,CAAC,GAAqB;CAClF,IAAI,CAAC,aAAa,QAAQ,KAAK,OAAO,GAAG,OAAO;CAIhD,MAAM,cAAc,kBAAkB,QAAQ,GAAG,MAAM;CAEvD,IAAI;EACA,QAAQ,IAAI,EAAE;EACd,QAAQ,IAAI,MAAM,KAAK,sBAAsB,CAAC;EAC9C,QAAQ,IAAI,EAAE;EACd,QAAQ,IAAI,MAAM,KAAK,sEAAsE,CAAC;EAC9F,QAAQ,IAAI,MAAM,KAAK,2EAA2E,CAAC;EACnG,QAAQ,IAAI,MAAM,KAAK,0EAA0E,CAAC;EAClG,QAAQ,IAAI,MAAM,KAAK,mBAAmB,CAAC;EAC3C,QAAQ,IAAI,EAAE;EACd,QAAQ,IAAI,MAAM,KAAK,kCAAkC,MAAM,KAAK,uBAAuB,EAAE,mBAAmB,CAAC;EACjH,QAAQ,IAAI,MAAM,KAAK,mBAAmB,MAAM,KAAK,0BAA0B,EAAE,EAAE,CAAC;EACpF,IAAI,aAAa;GACb,QAAQ,IAAI,EAAE;GACd,QAAQ,IAAI,MAAM,KAAK,+DAA+D,CAAC;EAC3F;EACA,QAAQ,IAAI,EAAE;EAEd,MAAM,EAAE,aAAa,MAAM,SAAS,OAAO,CACvC;GACI,MAAM;GACN,MAAM;GACN,SAAS;GAMT,SAAS;EACb,CACJ,CAA0C;EAE1C,WAAW,QAAQ,QAAQ,CAAC;EAE5B,QAAQ,IACJ,WACM,MAAM,MAAM,gCAAgC,IAC5C,MAAM,KACJ,6BACG,QAAQ,gBACL,mEACA,gCACV,CACR;EACA,QAAQ,IAAI,EAAE;EACd,OAAO,QAAQ,QAAQ;CAC3B,QAAQ;EAKJ,OAAO;CACX;AACJ;;AAGA,SAAgB,cAAc,MAAyB,QAAQ,KAAa;CACxE,MAAM,SAAS,kBAAkB,GAAG;CACpC,MAAM,SAAS,WAAW;CAC1B,QAAQ,QAAR;EACI,KAAK,MACD,OAAO,GAAG,MAAM,MAAM,SAAS,EAAE,2BAAqD,MAAM,KAAK,OAAO,aAAa,OAAO;EAChI,KAAK,aACD,OAAO,GAAG,MAAM,OAAO,gBAAgB,EAAE;EAC7C,KAAK,YACD,OAAO,GAAG,MAAM,KAAK,UAAU,EAAE,iBAAiB,OAAO,YAAY,OAAO,OAAO,UAAU,MAAM,GAAG,EAAE,MAAM;EAClH,KAAK,gBACD,OAAO,GAAG,MAAM,KAAK,UAAU,EAAE,SAAS,MAAM,KAAK,cAAc,EAAE;EACzE,KAAK,6BACD,OAAO,GAAG,MAAM,KAAK,UAAU,EAAE,SAAS,MAAM,KAAK,2BAA2B,EAAE;EACtF,KAAK,MACD,OAAO,GAAG,MAAM,KAAK,UAAU,EAAE,yBAAyB,MAAM,KAAK,IAAI,EAAE;EAC/E,KAAK,mBACD,OAAO,GAAG,MAAM,KAAK,UAAU,EAAE,oBAAoB,MAAM,KAAK,aAAa,EAAE,QAAQ,MAAM,KAAK,sBAAoB;CAC9H;AACJ"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { n as parseCommandArgs, r as wantsHelp } from "./args-BnmsEXvu.js";
|
|
2
|
+
import { r as refuseMissingCollectionsPath, t as COLLECTIONS_FLAG_HELP } from "./path-flags-BFgG9V6y.js";
|
|
3
|
+
import { managedNotices, prepareDatabaseEnv } from "./prepare-CDN6lSpz.js";
|
|
4
|
+
import { absolutizeLocalPathArgs, ensureDockerDatabase, n as argsFromCommand, resolveDriverCli, spawnDriverCli, t as reportSpawnFailure } from "./db-B7RuNuaQ.js";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import path from "path";
|
|
7
|
+
//#region src/commands/console.ts
|
|
8
|
+
/**
|
|
9
|
+
* CLI command: rebase console
|
|
10
|
+
*
|
|
11
|
+
* A Node REPL with the project open — `rebase` (what `openRebase` from
|
|
12
|
+
* `@rebasepro/server-postgres` returns: `dataAsAdmin`, `sql`, `withAuth`) and
|
|
13
|
+
* `collections` in scope — or, with `--eval`, one piece of code run and its
|
|
14
|
+
* result printed as JSON.
|
|
15
|
+
*
|
|
16
|
+
* Resolved like `rebase db push`: the same project and `.env`, the same
|
|
17
|
+
* database (the managed one started if that is what the project uses), the
|
|
18
|
+
* same `--collections` loader — the driver's, spawned in `backend/`. Opening
|
|
19
|
+
* the database changes nothing in it.
|
|
20
|
+
*/
|
|
21
|
+
var CONSOLE_FLAGS = {
|
|
22
|
+
"--eval": String,
|
|
23
|
+
"-e": "--eval",
|
|
24
|
+
"--collections": String,
|
|
25
|
+
"-c": "--collections",
|
|
26
|
+
"--database-url": String,
|
|
27
|
+
"--docker": Boolean
|
|
28
|
+
};
|
|
29
|
+
/** What each long flag above does, for the Options block. */
|
|
30
|
+
var CONSOLE_FLAG_HELP = {
|
|
31
|
+
"--eval": "Run this code instead of the REPL, print its awaited result as JSON, and exit 1 if it throws",
|
|
32
|
+
"--collections": COLLECTIONS_FLAG_HELP,
|
|
33
|
+
"--database-url": "Open this database instead of the project's",
|
|
34
|
+
"--docker": "Use the database from docker compose, starting it if needed"
|
|
35
|
+
};
|
|
36
|
+
/** Where the REPL keeps its history: the project's own `.rebase/`, which the scaffold ignores. */
|
|
37
|
+
function consoleHistoryPath(projectRoot) {
|
|
38
|
+
return path.join(projectRoot, ".rebase", "console_history");
|
|
39
|
+
}
|
|
40
|
+
function flagLabel(flag) {
|
|
41
|
+
return [flag, ...Object.entries(CONSOLE_FLAGS).filter(([, target]) => target === flag).map(([alias]) => alias)].join(", ");
|
|
42
|
+
}
|
|
43
|
+
function printConsoleHelp() {
|
|
44
|
+
console.log(`
|
|
45
|
+
${chalk.bold("rebase console")} — Explore the project's data from a REPL
|
|
46
|
+
|
|
47
|
+
${chalk.green.bold("Usage")}
|
|
48
|
+
rebase console [options]
|
|
49
|
+
|
|
50
|
+
${chalk.green.bold("Options")}
|
|
51
|
+
${Object.keys(CONSOLE_FLAG_HELP).map((flag) => ` ${chalk.blue(flagLabel(flag).padEnd(22))} ${CONSOLE_FLAG_HELP[flag]}`).join("\n")}
|
|
52
|
+
|
|
53
|
+
In scope:
|
|
54
|
+
rebase dataAsAdmin, sql(query, { params }), withAuth(user) → { data }, close()
|
|
55
|
+
collections the project's collections
|
|
56
|
+
|
|
57
|
+
Top-level await works. Opening the database changes nothing in it: no table,
|
|
58
|
+
role or trigger is created. withAuth runs as the user under row-level security.
|
|
59
|
+
|
|
60
|
+
${chalk.green.bold("Examples")}
|
|
61
|
+
rebase console
|
|
62
|
+
rebase console -e "rebase.dataAsAdmin.posts.find({ limit: 5 })"
|
|
63
|
+
rebase console -e "(await rebase.withAuth({ uid: 'u1', roles: ['user'] })).data.posts.find()"
|
|
64
|
+
rebase console -e "rebase.sql('select count(*) from posts')"
|
|
65
|
+
`);
|
|
66
|
+
}
|
|
67
|
+
async function consoleCommand(rawArgs) {
|
|
68
|
+
if (wantsHelp(rawArgs)) {
|
|
69
|
+
printConsoleHelp();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const { flags } = parseCommandArgs({
|
|
73
|
+
spec: CONSOLE_FLAGS,
|
|
74
|
+
rawArgs,
|
|
75
|
+
commandWords: 1,
|
|
76
|
+
command: "console",
|
|
77
|
+
maxPositionals: 0
|
|
78
|
+
});
|
|
79
|
+
const resolved = await resolveDriverCli();
|
|
80
|
+
const { projectRoot, backendDir } = resolved;
|
|
81
|
+
refuseMissingCollectionsPath(rawArgs, process.cwd(), backendDir, "console");
|
|
82
|
+
await ensureDockerDatabase(projectRoot, rawArgs);
|
|
83
|
+
const say = flags["--eval"] === void 0 ? (line) => console.log(chalk.gray(` ${line}`)) : (line) => console.error(chalk.gray(` ${line}`));
|
|
84
|
+
const prepared = await prepareDatabaseEnv(projectRoot, {
|
|
85
|
+
flagUrl: flags["--database-url"] ?? null,
|
|
86
|
+
flagDocker: flags["--docker"] === true,
|
|
87
|
+
onProgress: say
|
|
88
|
+
});
|
|
89
|
+
Object.assign(resolved.env, prepared.env);
|
|
90
|
+
for (const line of managedNotices(prepared)) say(line);
|
|
91
|
+
const childArgs = [...absolutizeLocalPathArgs(argsFromCommand(rawArgs, "console"), process.cwd()), `--history=${consoleHistoryPath(projectRoot)}`];
|
|
92
|
+
try {
|
|
93
|
+
await spawnDriverCli(resolved, childArgs);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
reportSpawnFailure(error);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { consoleCommand };
|
|
101
|
+
|
|
102
|
+
//# sourceMappingURL=console-D6SJf8k_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-D6SJf8k_.js","names":[],"sources":["../src/commands/console.ts"],"sourcesContent":["/**\n * CLI command: rebase console\n *\n * A Node REPL with the project open — `rebase` (what `openRebase` from\n * `@rebasepro/server-postgres` returns: `dataAsAdmin`, `sql`, `withAuth`) and\n * `collections` in scope — or, with `--eval`, one piece of code run and its\n * result printed as JSON.\n *\n * Resolved like `rebase db push`: the same project and `.env`, the same\n * database (the managed one started if that is what the project uses), the\n * same `--collections` loader — the driver's, spawned in `backend/`. Opening\n * the database changes nothing in it.\n */\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\nimport { argsFromCommand } from \"../utils/command-words\";\nimport { COLLECTIONS_FLAG_HELP, refuseMissingCollectionsPath } from \"../utils/path-flags\";\nimport { reportSpawnFailure } from \"../utils/spawn-error\";\nimport { managedNotices, prepareDatabaseEnv } from \"../dev-db/prepare\";\nimport { absolutizeLocalPathArgs, ensureDockerDatabase, resolveDriverCli, spawnDriverCli } from \"./db\";\n\nexport const CONSOLE_FLAGS = {\n \"--eval\": String,\n \"-e\": \"--eval\",\n \"--collections\": String,\n \"-c\": \"--collections\",\n \"--database-url\": String,\n \"--docker\": Boolean\n} as const;\n\n/** What each long flag above does, for the Options block. */\nconst CONSOLE_FLAG_HELP: Record<string, string> = {\n \"--eval\": \"Run this code instead of the REPL, print its awaited result as JSON, and exit 1 if it throws\",\n \"--collections\": COLLECTIONS_FLAG_HELP,\n \"--database-url\": \"Open this database instead of the project's\",\n \"--docker\": \"Use the database from docker compose, starting it if needed\"\n};\n\n/** Where the REPL keeps its history: the project's own `.rebase/`, which the scaffold ignores. */\nexport function consoleHistoryPath(projectRoot: string): string {\n return path.join(projectRoot, \".rebase\", \"console_history\");\n}\n\nfunction flagLabel(flag: string): string {\n const aliases = Object.entries(CONSOLE_FLAGS)\n .filter(([, target]) => target === flag)\n .map(([alias]) => alias);\n return [flag, ...aliases].join(\", \");\n}\n\nexport function printConsoleHelp(): void {\n console.log(`\n${chalk.bold(\"rebase console\")} — Explore the project's data from a REPL\n\n${chalk.green.bold(\"Usage\")}\n rebase console [options]\n\n${chalk.green.bold(\"Options\")}\n${Object.keys(CONSOLE_FLAG_HELP)\n .map(flag => ` ${chalk.blue(flagLabel(flag).padEnd(22))} ${CONSOLE_FLAG_HELP[flag]}`)\n .join(\"\\n\")}\n\nIn scope:\n rebase dataAsAdmin, sql(query, { params }), withAuth(user) → { data }, close()\n collections the project's collections\n\nTop-level await works. Opening the database changes nothing in it: no table,\nrole or trigger is created. withAuth runs as the user under row-level security.\n\n${chalk.green.bold(\"Examples\")}\n rebase console\n rebase console -e \"rebase.dataAsAdmin.posts.find({ limit: 5 })\"\n rebase console -e \"(await rebase.withAuth({ uid: 'u1', roles: ['user'] })).data.posts.find()\"\n rebase console -e \"rebase.sql('select count(*) from posts')\"\n`);\n}\n\nexport async function consoleCommand(rawArgs: string[]): Promise<void> {\n if (wantsHelp(rawArgs)) {\n printConsoleHelp();\n return;\n }\n\n // Strictly, before the line is relayed: the driver would otherwise be the\n // first to see a mistyped flag, after a database had been started for it.\n const { flags } = parseCommandArgs({\n spec: CONSOLE_FLAGS,\n rawArgs,\n commandWords: 1,\n command: \"console\",\n maxPositionals: 0\n });\n\n const resolved = await resolveDriverCli();\n const { projectRoot, backendDir } = resolved;\n refuseMissingCollectionsPath(rawArgs, process.cwd(), backendDir, \"console\");\n await ensureDockerDatabase(projectRoot, rawArgs);\n\n // With --eval, stdout is the result and nothing else, so it can be piped\n // into `jq`; what the database resolution has to say goes to stderr.\n const say = flags[\"--eval\"] === undefined\n ? (line: string) => console.log(chalk.gray(` ${line}`))\n : (line: string) => console.error(chalk.gray(` ${line}`));\n const prepared = await prepareDatabaseEnv(projectRoot, {\n flagUrl: flags[\"--database-url\"] ?? null,\n flagDocker: flags[\"--docker\"] === true,\n onProgress: say\n });\n Object.assign(resolved.env, prepared.env);\n for (const line of managedNotices(prepared)) say(line);\n\n const childArgs = [\n ...absolutizeLocalPathArgs(argsFromCommand(rawArgs, \"console\"), process.cwd()),\n `--history=${consoleHistoryPath(projectRoot)}`\n ];\n\n try {\n await spawnDriverCli(resolved, childArgs);\n } catch (error) {\n // A child that exited non-zero has already said why, on the terminal it\n // shares — an `--eval` that threw, a database that refused.\n reportSpawnFailure(error);\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAsBA,IAAa,gBAAgB;CACzB,UAAU;CACV,MAAM;CACN,iBAAiB;CACjB,MAAM;CACN,kBAAkB;CAClB,YAAY;AAChB;;AAGA,IAAM,oBAA4C;CAC9C,UAAU;CACV,iBAAiB;CACjB,kBAAkB;CAClB,YAAY;AAChB;;AAGA,SAAgB,mBAAmB,aAA6B;CAC5D,OAAO,KAAK,KAAK,aAAa,WAAW,iBAAiB;AAC9D;AAEA,SAAS,UAAU,MAAsB;CAIrC,OAAO,CAAC,MAAM,GAHE,OAAO,QAAQ,aAAa,CAAC,CACxC,QAAQ,GAAG,YAAY,WAAW,IAAI,CAAC,CACvC,KAAK,CAAC,WAAW,KACL,CAAO,CAAC,CAAC,KAAK,IAAI;AACvC;AAEA,SAAgB,mBAAyB;CACrC,QAAQ,IAAI;EACd,MAAM,KAAK,gBAAgB,EAAE;;EAE7B,MAAM,MAAM,KAAK,OAAO,EAAE;;;EAG1B,MAAM,MAAM,KAAK,SAAS,EAAE;EAC5B,OAAO,KAAK,iBAAiB,CAAC,CACvB,KAAI,SAAQ,KAAK,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,kBAAkB,OAAO,CAAC,CACrF,KAAK,IAAI,EAAE;;;;;;;;;EASlB,MAAM,MAAM,KAAK,UAAU,EAAE;;;;;CAK9B;AACD;AAEA,eAAsB,eAAe,SAAkC;CACnE,IAAI,UAAU,OAAO,GAAG;EACpB,iBAAiB;EACjB;CACJ;CAIA,MAAM,EAAE,UAAU,iBAAiB;EAC/B,MAAM;EACN;EACA,cAAc;EACd,SAAS;EACT,gBAAgB;CACpB,CAAC;CAED,MAAM,WAAW,MAAM,iBAAiB;CACxC,MAAM,EAAE,aAAa,eAAe;CACpC,6BAA6B,SAAS,QAAQ,IAAI,GAAG,YAAY,SAAS;CAC1E,MAAM,qBAAqB,aAAa,OAAO;CAI/C,MAAM,MAAM,MAAM,cAAc,KAAA,KACzB,SAAiB,QAAQ,IAAI,MAAM,KAAK,KAAK,MAAM,CAAC,KACpD,SAAiB,QAAQ,MAAM,MAAM,KAAK,KAAK,MAAM,CAAC;CAC7D,MAAM,WAAW,MAAM,mBAAmB,aAAa;EACnD,SAAS,MAAM,qBAAqB;EACpC,YAAY,MAAM,gBAAgB;EAClC,YAAY;CAChB,CAAC;CACD,OAAO,OAAO,SAAS,KAAK,SAAS,GAAG;CACxC,KAAK,MAAM,QAAQ,eAAe,QAAQ,GAAG,IAAI,IAAI;CAErD,MAAM,YAAY,CACd,GAAG,wBAAwB,gBAAgB,SAAS,SAAS,GAAG,QAAQ,IAAI,CAAC,GAC7E,aAAa,mBAAmB,WAAW,GAC/C;CAEA,IAAI;EACA,MAAM,eAAe,UAAU,SAAS;CAC5C,SAAS,OAAO;EAGZ,mBAAmB,KAAK;EACxB,QAAQ,KAAK,CAAC;CAClB;AACJ"}
|