@spacelr/cli 0.1.1 → 0.1.3
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/dist/index.js +62 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -183,6 +183,28 @@ function generatePKCE() {
|
|
|
183
183
|
var fs2 = __toESM(require("fs"));
|
|
184
184
|
var path2 = __toESM(require("path"));
|
|
185
185
|
var CONFIG_FILENAME = "spacelr.json";
|
|
186
|
+
var RULES_FILENAME = "spacelr.rules.json";
|
|
187
|
+
var INDEXES_FILENAME = "spacelr.indexes.json";
|
|
188
|
+
function readJsonFile(filePath, label) {
|
|
189
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
190
|
+
try {
|
|
191
|
+
return JSON.parse(content);
|
|
192
|
+
} catch (err) {
|
|
193
|
+
const detail = err instanceof Error ? `: ${err.message}` : "";
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Invalid JSON in ${label}: ${filePath}${detail}
|
|
196
|
+
Please check the file for syntax errors.`
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function writeJsonFile(filePath, data) {
|
|
201
|
+
fs2.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
202
|
+
}
|
|
203
|
+
function resolveSiblingPath(filename, configPath) {
|
|
204
|
+
const resolved = configPath ?? findConfigPath();
|
|
205
|
+
const dir = resolved ? path2.dirname(resolved) : process.cwd();
|
|
206
|
+
return path2.join(dir, filename);
|
|
207
|
+
}
|
|
186
208
|
function findConfigPath(startDir) {
|
|
187
209
|
let dir = startDir ?? process.cwd();
|
|
188
210
|
while (true) {
|
|
@@ -200,19 +222,11 @@ function findConfigPath(startDir) {
|
|
|
200
222
|
function loadConfig(configPath) {
|
|
201
223
|
const resolved = configPath ?? findConfigPath();
|
|
202
224
|
if (!resolved || !fs2.existsSync(resolved)) return null;
|
|
203
|
-
|
|
204
|
-
try {
|
|
205
|
-
return JSON.parse(content);
|
|
206
|
-
} catch {
|
|
207
|
-
throw new Error(
|
|
208
|
-
`Invalid JSON in config file: ${resolved}
|
|
209
|
-
Please check the file for syntax errors.`
|
|
210
|
-
);
|
|
211
|
-
}
|
|
225
|
+
return readJsonFile(resolved, "config file");
|
|
212
226
|
}
|
|
213
227
|
function saveConfig(config, configPath) {
|
|
214
228
|
const resolved = configPath ?? findConfigPath() ?? path2.join(process.cwd(), CONFIG_FILENAME);
|
|
215
|
-
|
|
229
|
+
writeJsonFile(resolved, config);
|
|
216
230
|
}
|
|
217
231
|
function resolveProjectId(flagValue, config) {
|
|
218
232
|
const projectId = flagValue ?? config?.projectId;
|
|
@@ -226,6 +240,22 @@ function resolveProjectId(flagValue, config) {
|
|
|
226
240
|
function resolveApiUrl(flagValue, config) {
|
|
227
241
|
return flagValue ?? config?.apiUrl ?? process.env["SPACELR_API_URL"] ?? "https://api.spacelr.io";
|
|
228
242
|
}
|
|
243
|
+
function loadRules(configPath) {
|
|
244
|
+
const filePath = resolveSiblingPath(RULES_FILENAME, configPath);
|
|
245
|
+
if (!fs2.existsSync(filePath)) return null;
|
|
246
|
+
return readJsonFile(filePath, "rules file");
|
|
247
|
+
}
|
|
248
|
+
function saveRules(rules, configPath) {
|
|
249
|
+
writeJsonFile(resolveSiblingPath(RULES_FILENAME, configPath), rules);
|
|
250
|
+
}
|
|
251
|
+
function loadIndexes(configPath) {
|
|
252
|
+
const filePath = resolveSiblingPath(INDEXES_FILENAME, configPath);
|
|
253
|
+
if (!fs2.existsSync(filePath)) return null;
|
|
254
|
+
return readJsonFile(filePath, "indexes file");
|
|
255
|
+
}
|
|
256
|
+
function saveIndexes(indexes, configPath) {
|
|
257
|
+
writeJsonFile(resolveSiblingPath(INDEXES_FILENAME, configPath), indexes);
|
|
258
|
+
}
|
|
229
259
|
|
|
230
260
|
// libs/cli/src/commands/login.ts
|
|
231
261
|
var CLI_CLIENT_ID = "spacelr-cli";
|
|
@@ -815,10 +845,6 @@ function createInitCommand() {
|
|
|
815
845
|
apiUrl: apiUrl !== "https://api.spacelr.io" ? apiUrl : void 0,
|
|
816
846
|
hosting: {
|
|
817
847
|
directory: hostingDir
|
|
818
|
-
},
|
|
819
|
-
database: {
|
|
820
|
-
indexes: {},
|
|
821
|
-
rules: {}
|
|
822
848
|
}
|
|
823
849
|
};
|
|
824
850
|
saveConfig(config, configPath);
|
|
@@ -936,7 +962,7 @@ async function deploy(client, projectId, directory, options) {
|
|
|
936
962
|
verbose(`Deployment ID: ${deployment.deploymentId}`);
|
|
937
963
|
spin.text = `Uploading ${formatBytes(zipBuffer.length)}...`;
|
|
938
964
|
await client.uploadFile(
|
|
939
|
-
`/hosting/deployments/${deployment.deploymentId}/upload`,
|
|
965
|
+
`/hosting/${projectId}/deployments/${deployment.deploymentId}/upload`,
|
|
940
966
|
zipBuffer,
|
|
941
967
|
"deployment.zip"
|
|
942
968
|
);
|
|
@@ -951,6 +977,7 @@ async function deploy(client, projectId, directory, options) {
|
|
|
951
977
|
spin.text = "Processing deployment...";
|
|
952
978
|
const result = await pollDeploymentStatus(
|
|
953
979
|
client,
|
|
980
|
+
projectId,
|
|
954
981
|
deployment.deploymentId,
|
|
955
982
|
spin
|
|
956
983
|
);
|
|
@@ -974,12 +1001,12 @@ async function deploy(client, projectId, directory, options) {
|
|
|
974
1001
|
}
|
|
975
1002
|
}
|
|
976
1003
|
}
|
|
977
|
-
async function pollDeploymentStatus(client, deploymentId, spin) {
|
|
1004
|
+
async function pollDeploymentStatus(client, projectId, deploymentId, spin) {
|
|
978
1005
|
const maxAttempts = 120;
|
|
979
1006
|
for (let i = 0; i < maxAttempts; i++) {
|
|
980
1007
|
await sleep(5e3);
|
|
981
1008
|
const status = await client.get(
|
|
982
|
-
`/hosting/deployments/${deploymentId}/status`
|
|
1009
|
+
`/hosting/${projectId}/deployments/${deploymentId}/status`
|
|
983
1010
|
);
|
|
984
1011
|
verbose(`Poll ${i + 1}: status=${status.status}`);
|
|
985
1012
|
spin.text = `Processing deployment... (${status.status})`;
|
|
@@ -999,16 +1026,16 @@ var import_commander12 = require("commander");
|
|
|
999
1026
|
// libs/cli/src/commands/db/indexes-deploy.ts
|
|
1000
1027
|
var import_commander8 = require("commander");
|
|
1001
1028
|
function createIndexesDeployCommand() {
|
|
1002
|
-
return new import_commander8.Command("deploy").description("Deploy indexes from
|
|
1029
|
+
return new import_commander8.Command("deploy").description("Deploy indexes from spacelr.indexes.json to remote").option("--project <id>", "Project ID").option("--config <path>", "Config file path").option("--yes", "Skip confirmation").action(async (opts, cmd) => {
|
|
1003
1030
|
const globalOpts = cmd.optsWithGlobals();
|
|
1004
1031
|
const config = loadConfig(opts.config);
|
|
1005
1032
|
const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);
|
|
1006
1033
|
try {
|
|
1007
1034
|
const token = requireAuth(globalOpts.token);
|
|
1008
1035
|
const projectId = resolveProjectId(opts.project, config);
|
|
1009
|
-
const indexes = config
|
|
1036
|
+
const indexes = loadIndexes(opts.config);
|
|
1010
1037
|
if (!indexes || Object.keys(indexes).length === 0) {
|
|
1011
|
-
warn("No indexes
|
|
1038
|
+
warn("No indexes found in spacelr.indexes.json");
|
|
1012
1039
|
return;
|
|
1013
1040
|
}
|
|
1014
1041
|
const indexRules = convertIndexFormat(indexes);
|
|
@@ -1067,7 +1094,7 @@ function convertIndexFormat(indexes) {
|
|
|
1067
1094
|
// libs/cli/src/commands/db/indexes-pull.ts
|
|
1068
1095
|
var import_commander9 = require("commander");
|
|
1069
1096
|
function createIndexesPullCommand() {
|
|
1070
|
-
return new import_commander9.Command("pull").description("Pull current indexes from remote to
|
|
1097
|
+
return new import_commander9.Command("pull").description("Pull current indexes from remote to spacelr.indexes.json").option("--project <id>", "Project ID").option("--config <path>", "Config file path").action(async (opts, cmd) => {
|
|
1071
1098
|
const globalOpts = cmd.optsWithGlobals();
|
|
1072
1099
|
const config = loadConfig(opts.config);
|
|
1073
1100
|
const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);
|
|
@@ -1078,15 +1105,10 @@ function createIndexesPullCommand() {
|
|
|
1078
1105
|
const client = new ApiClient({ apiUrl, token });
|
|
1079
1106
|
const result = await client.get(`/databases/${projectId}/index-rules`);
|
|
1080
1107
|
const indexes = convertFromRemoteFormat(result.indexRules);
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
...config?.database,
|
|
1086
|
-
indexes
|
|
1087
|
-
}
|
|
1088
|
-
};
|
|
1089
|
-
saveConfig(updatedConfig, opts.config);
|
|
1108
|
+
saveIndexes(indexes, opts.config);
|
|
1109
|
+
if (opts.project && opts.project !== config?.projectId) {
|
|
1110
|
+
saveConfig({ ...config, projectId: opts.project }, opts.config);
|
|
1111
|
+
}
|
|
1090
1112
|
spin.succeed("Indexes pulled");
|
|
1091
1113
|
const collectionCount = Object.keys(indexes).length;
|
|
1092
1114
|
const totalIndexes = Object.values(indexes).reduce(
|
|
@@ -1099,7 +1121,7 @@ function createIndexesPullCommand() {
|
|
|
1099
1121
|
success(
|
|
1100
1122
|
`Pulled ${totalIndexes} index(es) from ${collectionCount} collection(s)`
|
|
1101
1123
|
);
|
|
1102
|
-
info("
|
|
1124
|
+
info("Indexes file updated");
|
|
1103
1125
|
}
|
|
1104
1126
|
} catch (err) {
|
|
1105
1127
|
error(err instanceof Error ? err.message : "Failed to pull indexes");
|
|
@@ -1131,16 +1153,16 @@ function convertFromRemoteFormat(remoteIndexes) {
|
|
|
1131
1153
|
// libs/cli/src/commands/db/rules-deploy.ts
|
|
1132
1154
|
var import_commander10 = require("commander");
|
|
1133
1155
|
function createRulesDeployCommand() {
|
|
1134
|
-
return new import_commander10.Command("deploy").description("Deploy rules from
|
|
1156
|
+
return new import_commander10.Command("deploy").description("Deploy rules from spacelr.rules.json to remote").option("--project <id>", "Project ID").option("--config <path>", "Config file path").option("--yes", "Skip confirmation").action(async (opts, cmd) => {
|
|
1135
1157
|
const globalOpts = cmd.optsWithGlobals();
|
|
1136
1158
|
const config = loadConfig(opts.config);
|
|
1137
1159
|
const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);
|
|
1138
1160
|
try {
|
|
1139
1161
|
const token = requireAuth(globalOpts.token);
|
|
1140
1162
|
const projectId = resolveProjectId(opts.project, config);
|
|
1141
|
-
const rules = config
|
|
1163
|
+
const rules = loadRules(opts.config);
|
|
1142
1164
|
if (!rules || Object.keys(rules).length === 0) {
|
|
1143
|
-
warn("No rules
|
|
1165
|
+
warn("No rules found in spacelr.rules.json");
|
|
1144
1166
|
return;
|
|
1145
1167
|
}
|
|
1146
1168
|
const ruleCount = Object.keys(rules).length;
|
|
@@ -1179,7 +1201,7 @@ function createRulesDeployCommand() {
|
|
|
1179
1201
|
// libs/cli/src/commands/db/rules-pull.ts
|
|
1180
1202
|
var import_commander11 = require("commander");
|
|
1181
1203
|
function createRulesPullCommand() {
|
|
1182
|
-
return new import_commander11.Command("pull").description("Pull current rules from remote to
|
|
1204
|
+
return new import_commander11.Command("pull").description("Pull current rules from remote to spacelr.rules.json").option("--project <id>", "Project ID").option("--config <path>", "Config file path").action(async (opts, cmd) => {
|
|
1183
1205
|
const globalOpts = cmd.optsWithGlobals();
|
|
1184
1206
|
const config = loadConfig(opts.config);
|
|
1185
1207
|
const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);
|
|
@@ -1192,22 +1214,17 @@ function createRulesPullCommand() {
|
|
|
1192
1214
|
`/databases/${projectId}/rules`
|
|
1193
1215
|
);
|
|
1194
1216
|
const rules = result.rules;
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
...config?.database,
|
|
1200
|
-
rules
|
|
1201
|
-
}
|
|
1202
|
-
};
|
|
1203
|
-
saveConfig(updatedConfig, opts.config);
|
|
1217
|
+
saveRules(rules, opts.config);
|
|
1218
|
+
if (opts.project && opts.project !== config?.projectId) {
|
|
1219
|
+
saveConfig({ ...config, projectId: opts.project }, opts.config);
|
|
1220
|
+
}
|
|
1204
1221
|
spin.succeed("Rules pulled");
|
|
1205
1222
|
const ruleCount = Object.keys(rules).length;
|
|
1206
1223
|
if (isJsonMode()) {
|
|
1207
1224
|
json(rules);
|
|
1208
1225
|
} else {
|
|
1209
1226
|
success(`Pulled rules for ${ruleCount} collection(s)`);
|
|
1210
|
-
info("
|
|
1227
|
+
info("Rules file updated");
|
|
1211
1228
|
}
|
|
1212
1229
|
} catch (err) {
|
|
1213
1230
|
error(err instanceof Error ? err.message : "Failed to pull rules");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../libs/cli/src/index.ts","../../../../libs/cli/src/lib/output.ts","../../../../libs/cli/src/commands/login.ts","../../../../libs/cli/src/lib/auth.ts","../../../../libs/cli/src/lib/config.ts","../../../../libs/cli/src/commands/logout.ts","../../../../libs/cli/src/commands/whoami.ts","../../../../libs/cli/src/lib/api-client.ts","../../../../libs/cli/src/commands/projects.ts","../../../../libs/cli/src/commands/use.ts","../../../../libs/cli/src/lib/prompt.ts","../../../../libs/cli/src/commands/init.ts","../../../../libs/cli/src/commands/deploy.ts","../../../../libs/cli/src/lib/zip.ts","../../../../libs/cli/src/commands/db/index.ts","../../../../libs/cli/src/commands/db/indexes-deploy.ts","../../../../libs/cli/src/commands/db/indexes-pull.ts","../../../../libs/cli/src/commands/db/rules-deploy.ts","../../../../libs/cli/src/commands/db/rules-pull.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { setOutputMode } from './lib/output';\nimport { createLoginCommand } from './commands/login';\nimport { createLogoutCommand } from './commands/logout';\nimport { createWhoamiCommand } from './commands/whoami';\nimport { createProjectsCommand } from './commands/projects';\nimport { createUseCommand } from './commands/use';\nimport { createInitCommand } from './commands/init';\nimport { createDeployCommand } from './commands/deploy';\nimport { createDbCommand } from './commands/db';\n\nconst program = new Command();\n\nprogram\n .name('spacelr')\n .description('CLI tool for the Spacelr platform')\n .version('0.1.0')\n .option('--api-url <url>', 'Override API URL')\n .option('--token <token>', 'Explicit auth token (CI mode)')\n .option('--json', 'Output as JSON')\n .option('--verbose', 'Verbose logging')\n .hook('preAction', (thisCommand) => {\n const opts = thisCommand.optsWithGlobals();\n setOutputMode({\n json: opts['json'] as boolean | undefined,\n verbose: opts['verbose'] as boolean | undefined,\n });\n });\n\nprogram.addCommand(createLoginCommand());\nprogram.addCommand(createLogoutCommand());\nprogram.addCommand(createWhoamiCommand());\nprogram.addCommand(createProjectsCommand());\nprogram.addCommand(createUseCommand());\nprogram.addCommand(createInitCommand());\nprogram.addCommand(createDeployCommand());\nprogram.addCommand(createDbCommand());\n\nprogram.parse();\n","import ora, { type Ora } from 'ora';\nimport pc from 'picocolors';\n\nlet jsonMode = false;\nlet verboseMode = false;\n\nexport function setOutputMode(options: {\n json?: boolean;\n verbose?: boolean;\n}): void {\n jsonMode = options.json ?? false;\n verboseMode = options.verbose ?? false;\n}\n\nexport function isJsonMode(): boolean {\n return jsonMode;\n}\n\nexport function success(message: string): void {\n if (!jsonMode) {\n console.log(pc.green(`\\u2713 ${message}`));\n }\n}\n\nexport function error(message: string): void {\n if (!jsonMode) {\n console.error(pc.red(`\\u2717 ${message}`));\n }\n}\n\nexport function warn(message: string): void {\n if (!jsonMode) {\n console.warn(pc.yellow(`! ${message}`));\n }\n}\n\nexport function info(message: string): void {\n if (!jsonMode) {\n console.log(pc.cyan(`\\u2139 ${message}`));\n }\n}\n\nexport function verbose(message: string): void {\n if (verboseMode && !jsonMode) {\n console.log(pc.dim(` ${message}`));\n }\n}\n\nexport function json(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\nexport function table(\n headers: string[],\n rows: string[][],\n): void {\n if (jsonMode) return;\n\n const colWidths = headers.map((h, i) => {\n const maxRow = rows.reduce(\n (max, row) => Math.max(max, (row[i] ?? '').length),\n 0,\n );\n return Math.max(h.length, maxRow);\n });\n\n const headerLine = headers\n .map((h, i) => pc.bold(h.padEnd(colWidths[i] ?? 0)))\n .join(' ');\n const separator = colWidths.map((w) => '-'.repeat(w)).join(' ');\n\n console.log(headerLine);\n console.log(separator);\n for (const row of rows) {\n console.log(\n row.map((cell, i) => cell.padEnd(colWidths[i] ?? 0)).join(' '),\n );\n }\n}\n\nexport function spinner(text: string): Ora {\n if (jsonMode) {\n return ora({ text, isSilent: true });\n }\n return ora(text).start();\n}\n\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const units = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const value = bytes / Math.pow(1024, i);\n return `${value.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;\n}\n","import * as http from 'node:http';\nimport * as crypto from 'node:crypto';\nimport { Command } from 'commander';\nimport open from 'open';\nimport { generatePKCE, storeCredentials } from '../lib/auth';\nimport { resolveApiUrl, loadConfig } from '../lib/config';\nimport { success, error, info, spinner, json, isJsonMode } from '../lib/output';\nimport type { GlobalOptions, TokenResponse, StoredCredentials } from '../lib/types';\n\nconst CLI_CLIENT_ID = 'spacelr-cli';\n\nexport function createLoginCommand(): Command {\n return new Command('login')\n .description('Authenticate with Spacelr via browser')\n .option('--auth-url <url>', 'OAuth server URL (defaults to --api-url)')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n const authUrl = (opts.authUrl as string | undefined) ?? apiUrl;\n\n try {\n const credentials = await performLogin(authUrl, apiUrl);\n storeCredentials(credentials);\n\n if (isJsonMode()) {\n json({ success: true, expiresAt: credentials.expiresAt });\n } else {\n success('Logged in successfully');\n info(`Credentials stored in ~/.spacelr/credentials.json`);\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Login failed');\n process.exitCode = 1;\n }\n });\n}\n\nasync function performLogin(authUrl: string, apiUrl: string): Promise<StoredCredentials> {\n const { codeVerifier, codeChallenge } = generatePKCE();\n const state = crypto.randomBytes(16).toString('base64url');\n\n // Start local HTTP server on a random port\n const { port, waitForCode, close } = await startCallbackServer(state);\n\n const authorizeUrl = buildAuthorizeUrl(authUrl, port, codeChallenge, state);\n\n info(`Opening browser for authentication...`);\n info(`If the browser doesn't open, visit: ${authorizeUrl}`);\n\n await open(authorizeUrl);\n\n const spin = spinner('Waiting for authentication...');\n\n try {\n const code = await waitForCode;\n spin.text = 'Exchanging authorization code...';\n\n const tokenResponse = await exchangeCode(\n authUrl,\n code,\n codeVerifier,\n port,\n );\n\n spin.succeed('Authentication complete');\n\n return {\n accessToken: tokenResponse.access_token,\n refreshToken: tokenResponse.refresh_token,\n expiresAt: Date.now() + tokenResponse.expires_in * 1000,\n apiUrl,\n };\n } catch (err) {\n spin.fail('Authentication failed');\n throw err;\n } finally {\n close();\n }\n}\n\nfunction buildAuthorizeUrl(\n apiUrl: string,\n port: number,\n codeChallenge: string,\n state: string,\n): string {\n const params = new URLSearchParams({\n client_id: CLI_CLIENT_ID,\n redirect_uri: `http://127.0.0.1:${port}/callback`,\n response_type: 'code',\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n scope: 'openid profile email',\n state,\n });\n return `${apiUrl}/auth/authorize?${params.toString()}`;\n}\n\nasync function startCallbackServer(expectedState: string): Promise<{\n port: number;\n waitForCode: Promise<string>;\n close: () => void;\n}> {\n return new Promise((resolveServer) => {\n let resolveCode: (code: string) => void;\n let rejectCode: (err: Error) => void;\n\n const waitForCode = new Promise<string>((resolve, reject) => {\n resolveCode = resolve;\n rejectCode = reject;\n });\n\n const server = http.createServer((req, res) => {\n const url = new URL(req.url ?? '/', `http://127.0.0.1`);\n\n if (url.pathname === '/callback') {\n const code = url.searchParams.get('code');\n const errorParam = url.searchParams.get('error');\n const returnedState = url.searchParams.get('state');\n\n if (errorParam) {\n const description =\n url.searchParams.get('error_description') ?? errorParam;\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(errorPage(description));\n rejectCode(new Error(`OAuth error: ${description}`));\n return;\n }\n\n // CSRF protection: verify state matches\n if (returnedState !== expectedState) {\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(errorPage('Invalid state parameter (possible CSRF attack)'));\n rejectCode(new Error('OAuth state mismatch'));\n return;\n }\n\n if (!code) {\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(errorPage('No authorization code received'));\n rejectCode(new Error('No authorization code received'));\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(successPage());\n resolveCode(code);\n } else {\n res.writeHead(404);\n res.end();\n }\n });\n\n // Timeout after 5 minutes\n const timeout = setTimeout(() => {\n rejectCode(new Error('Login timed out after 5 minutes'));\n server.close();\n }, 5 * 60 * 1000);\n\n server.listen(0, '127.0.0.1', () => {\n const address = server.address();\n const port =\n typeof address === 'object' && address ? address.port : 0;\n\n resolveServer({\n port,\n waitForCode,\n close: () => {\n clearTimeout(timeout);\n server.close();\n },\n });\n });\n });\n}\n\nasync function exchangeCode(\n apiUrl: string,\n code: string,\n codeVerifier: string,\n port: number,\n): Promise<TokenResponse> {\n const response = await fetch(`${apiUrl}/auth/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n code_verifier: codeVerifier,\n client_id: CLI_CLIENT_ID,\n redirect_uri: `http://127.0.0.1:${port}/callback`,\n }),\n });\n\n if (!response.ok) {\n let message: string;\n try {\n const body = (await response.json()) as { message?: string; error?: string };\n message = body.message ?? body.error ?? response.statusText;\n } catch {\n message = response.statusText;\n }\n throw new Error(`Token exchange failed: ${message}`);\n }\n\n return (await response.json()) as TokenResponse;\n}\n\nfunction successPage(): string {\n return `<!DOCTYPE html>\n<html><head><title>Spacelr CLI</title>\n<style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f8f9fa;}\n.box{text-align:center;padding:2rem;}.check{font-size:3rem;color:#22c55e;}</style></head>\n<body><div class=\"box\"><div class=\"check\">✓</div><h1>Authenticated</h1><p>You can close this window and return to the terminal.</p></div></body></html>`;\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\nfunction errorPage(message: string): string {\n return `<!DOCTYPE html>\n<html><head><title>Spacelr CLI</title>\n<style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f8f9fa;}\n.box{text-align:center;padding:2rem;}.x{font-size:3rem;color:#ef4444;}</style></head>\n<body><div class=\"box\"><div class=\"x\">✗</div><h1>Authentication Failed</h1><p>${escapeHtml(message)}</p></div></body></html>`;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\nimport type { StoredCredentials, PKCEChallenge } from './types';\n\nfunction getCredentialsDir(): string {\n return path.join(\n process.env['HOME'] ?? process.env['USERPROFILE'] ?? '~',\n '.spacelr',\n );\n}\n\nfunction getCredentialsFile(): string {\n return path.join(getCredentialsDir(), 'credentials.json');\n}\n\nexport function getStoredCredentials(): StoredCredentials | null {\n try {\n const file = getCredentialsFile();\n if (!fs.existsSync(file)) return null;\n const content = fs.readFileSync(file, 'utf-8');\n return JSON.parse(content) as StoredCredentials;\n } catch {\n return null;\n }\n}\n\nexport function storeCredentials(credentials: StoredCredentials): void {\n const dir = getCredentialsDir();\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n fs.writeFileSync(\n getCredentialsFile(),\n JSON.stringify(credentials, null, 2),\n { mode: 0o600 },\n );\n}\n\nexport function clearCredentials(): void {\n try {\n const file = getCredentialsFile();\n if (fs.existsSync(file)) {\n fs.unlinkSync(file);\n }\n } catch {\n // Ignore errors during cleanup\n }\n}\n\nexport function isTokenExpired(credentials: StoredCredentials): boolean {\n // Add 60 second buffer\n return Date.now() >= credentials.expiresAt - 60_000;\n}\n\nexport function resolveToken(flagToken?: string): string | null {\n if (flagToken) return flagToken;\n if (process.env['SPACELR_TOKEN']) return process.env['SPACELR_TOKEN'];\n const credentials = getStoredCredentials();\n if (credentials && !isTokenExpired(credentials)) {\n return credentials.accessToken;\n }\n return null;\n}\n\nexport class AuthRequiredError extends Error {\n constructor() {\n super('Not logged in. Run \"spacelr login\" to authenticate.');\n this.name = 'AuthRequiredError';\n }\n}\n\n/**\n * Resolves a token or throws AuthRequiredError.\n * Use in commands that require authentication.\n */\nexport function requireAuth(flagToken?: string): string {\n const token = resolveToken(flagToken);\n if (!token) {\n throw new AuthRequiredError();\n }\n return token;\n}\n\nexport function generatePKCE(): PKCEChallenge {\n const codeVerifier = crypto.randomBytes(32).toString('base64url');\n const codeChallenge = crypto\n .createHash('sha256')\n .update(codeVerifier)\n .digest('base64url');\n return { codeVerifier, codeChallenge };\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { SpacelrConfig } from './types';\n\nconst CONFIG_FILENAME = 'spacelr.json';\n\nexport function findConfigPath(startDir?: string): string | null {\n let dir = startDir ?? process.cwd();\n\n while (true) {\n const candidate = path.join(dir, CONFIG_FILENAME);\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n const parent = path.dirname(dir);\n if (parent === dir) {\n return null;\n }\n dir = parent;\n }\n}\n\nexport function loadConfig(configPath?: string): SpacelrConfig | null {\n const resolved = configPath ?? findConfigPath();\n if (!resolved || !fs.existsSync(resolved)) return null;\n\n const content = fs.readFileSync(resolved, 'utf-8');\n try {\n return JSON.parse(content) as SpacelrConfig;\n } catch {\n throw new Error(\n `Invalid JSON in config file: ${resolved}\\nPlease check the file for syntax errors.`,\n );\n }\n}\n\nexport function saveConfig(\n config: SpacelrConfig,\n configPath?: string,\n): void {\n const resolved = configPath ?? findConfigPath() ?? path.join(process.cwd(), CONFIG_FILENAME);\n fs.writeFileSync(resolved, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function resolveProjectId(\n flagValue?: string,\n config?: SpacelrConfig | null,\n): string {\n const projectId = flagValue ?? config?.projectId;\n if (!projectId) {\n throw new Error(\n 'Project ID is required. Provide --project <id> or set \"projectId\" in spacelr.json',\n );\n }\n return projectId;\n}\n\nexport function resolveApiUrl(\n flagValue?: string,\n config?: SpacelrConfig | null,\n): string {\n return (\n flagValue ??\n config?.apiUrl ??\n process.env['SPACELR_API_URL'] ??\n 'https://api.spacelr.io'\n );\n}\n","import { Command } from 'commander';\nimport { clearCredentials, getStoredCredentials } from '../lib/auth';\nimport { success, warn, json, isJsonMode } from '../lib/output';\nimport type { GlobalOptions } from '../lib/types';\n\nexport function createLogoutCommand(): Command {\n return new Command('logout')\n .description('Clear stored credentials')\n .action(async (_opts, cmd: Command) => {\n cmd.optsWithGlobals<GlobalOptions>();\n\n const existing = getStoredCredentials();\n clearCredentials();\n\n if (isJsonMode()) {\n json({ success: true, hadCredentials: !!existing });\n } else if (existing) {\n success('Logged out successfully');\n } else {\n warn('No credentials found');\n }\n });\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport { resolveApiUrl, loadConfig } from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { success, error, info, json, isJsonMode } from '../lib/output';\nimport type { GlobalOptions, UserInfo } from '../lib/types';\n\nexport function createWhoamiCommand(): Command {\n return new Command('whoami')\n .description('Show current authenticated user')\n .action(async (_opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const client = new ApiClient({ apiUrl, token });\n const response = await client.get<{ user: UserInfo }>('/auth/me');\n const user = response.user;\n\n if (isJsonMode()) {\n json(user);\n } else {\n success(`Logged in as ${user.email ?? user.username ?? user.id}`);\n if (user.displayName) info(`Name: ${user.displayName}`);\n if (user.roles?.length) info(`Roles: ${user.roles.join(', ')}`);\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to get user info');\n process.exitCode = 1;\n }\n });\n}\n","import {\n getStoredCredentials,\n storeCredentials,\n isTokenExpired,\n} from './auth';\nimport { verbose } from './output';\nimport type { StoredCredentials } from './types';\n\ninterface ApiClientOptions {\n apiUrl: string;\n token?: string;\n}\n\ninterface RequestOptions {\n method?: string;\n body?: BodyInit | Record<string, unknown>;\n headers?: Record<string, string>;\n timeout?: number;\n}\n\nexport class ApiClient {\n private readonly apiUrl: string;\n private explicitToken?: string;\n private refreshing: Promise<string | null> | null = null;\n\n constructor(options: ApiClientOptions) {\n this.apiUrl = options.apiUrl.replace(/\\/+$/, '');\n this.explicitToken = options.token;\n }\n\n private async getToken(): Promise<string | null> {\n if (this.explicitToken) return this.explicitToken;\n\n const envToken = process.env['SPACELR_TOKEN'];\n if (envToken) return envToken;\n\n const credentials = getStoredCredentials();\n if (!credentials) return null;\n\n if (!isTokenExpired(credentials)) {\n return credentials.accessToken;\n }\n\n // Token expired, try refreshing\n if (credentials.refreshToken) {\n return this.refreshAccessToken(credentials);\n }\n\n return null;\n }\n\n private async refreshAccessToken(\n credentials: StoredCredentials,\n ): Promise<string | null> {\n // Deduplicate concurrent refreshes\n if (this.refreshing) return this.refreshing;\n\n this.refreshing = (async () => {\n try {\n verbose('Refreshing access token...');\n const response = await fetch(`${this.apiUrl}/auth/refresh`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n refreshToken: credentials.refreshToken ?? '',\n }),\n });\n\n if (!response.ok) {\n verbose('Token refresh failed');\n return null;\n }\n\n const data = (await response.json()) as { access_token: string; refresh_token?: string };\n const newCredentials: StoredCredentials = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token ?? credentials.refreshToken,\n // Admin refresh endpoint doesn't return expires_in; default to 1 hour\n expiresAt: Date.now() + 3600 * 1000,\n apiUrl: credentials.apiUrl,\n };\n storeCredentials(newCredentials);\n verbose('Token refreshed successfully');\n return data.access_token;\n } catch {\n verbose('Token refresh error');\n return null;\n } finally {\n this.refreshing = null;\n }\n })();\n\n return this.refreshing;\n }\n\n private serializeBody(\n body: RequestOptions['body'],\n contentType: string | undefined,\n ): BodyInit | undefined {\n if (!body) return undefined;\n if (contentType === 'application/json') {\n return JSON.stringify(body);\n }\n // Buffer, string, URLSearchParams, etc. are already valid BodyInit\n return body as BodyInit;\n }\n\n private async request<T>(\n path: string,\n options: RequestOptions = {},\n ): Promise<T> {\n const { method = 'GET', body, headers = {}, timeout = 30_000 } = options;\n const url = `${this.apiUrl}${path}`;\n\n const token = await this.getToken();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n if (body && !headers['Content-Type']) {\n headers['Content-Type'] = 'application/json';\n }\n\n const serializedBody = this.serializeBody(body, headers['Content-Type']);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n\n verbose(`${method} ${url}`);\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: serializedBody,\n signal: controller.signal,\n });\n\n if (response.status === 401 && !this.explicitToken) {\n // Try refresh once\n const credentials = getStoredCredentials();\n if (credentials?.refreshToken) {\n const newToken = await this.refreshAccessToken(credentials);\n if (newToken) {\n headers['Authorization'] = `Bearer ${newToken}`;\n const retryController = new AbortController();\n const retryTimer = setTimeout(() => retryController.abort(), timeout);\n const retryResponse = await fetch(url, {\n method,\n headers,\n body: serializedBody,\n signal: retryController.signal,\n });\n clearTimeout(retryTimer);\n if (!retryResponse.ok) {\n await this.throwApiError(retryResponse);\n }\n return (await retryResponse.json()) as T;\n }\n }\n throw new Error(\n 'Authentication required. Run \"spacelr login\" to authenticate.',\n );\n }\n\n if (!response.ok) {\n await this.throwApiError(response);\n }\n\n const contentType = response.headers.get('content-type');\n if (contentType?.includes('application/json')) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n throw new Error(`Request timed out: ${method} ${path}`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async throwApiError(response: Response): Promise<never> {\n let message: string;\n try {\n const body = (await response.json()) as { message?: string; error?: string };\n message = body.message ?? body.error ?? response.statusText;\n } catch {\n message = response.statusText;\n }\n throw new Error(`API error (${response.status}): ${message}`);\n }\n\n async get<T>(path: string, timeout?: number): Promise<T> {\n return this.request<T>(path, { timeout });\n }\n\n async post<T>(path: string, body?: Record<string, unknown> | BodyInit, timeout?: number): Promise<T> {\n return this.request<T>(path, { method: 'POST', body, timeout });\n }\n\n async put<T>(path: string, body?: Record<string, unknown> | BodyInit, timeout?: number): Promise<T> {\n return this.request<T>(path, { method: 'PUT', body, timeout });\n }\n\n async delete<T>(path: string, timeout?: number): Promise<T> {\n return this.request<T>(path, { method: 'DELETE', timeout });\n }\n\n async uploadFile(\n path: string,\n fileBuffer: Buffer,\n filename: string,\n ): Promise<DeploymentUploadResponse> {\n const boundary = `----spacelr${Date.now()}`;\n const parts: Buffer[] = [];\n\n // Build multipart body manually (no form-data dependency needed)\n const header = Buffer.from(\n `--${boundary}\\r\\n` +\n `Content-Disposition: form-data; name=\"file\"; filename=\"${filename}\"\\r\\n` +\n `Content-Type: application/zip\\r\\n\\r\\n`,\n );\n const footer = Buffer.from(`\\r\\n--${boundary}--\\r\\n`);\n parts.push(header, fileBuffer, footer);\n const body = Buffer.concat(parts);\n\n return this.request<DeploymentUploadResponse>(path, {\n method: 'POST',\n body,\n headers: {\n 'Content-Type': `multipart/form-data; boundary=${boundary}`,\n },\n timeout: 300_000, // 5 minutes for uploads\n });\n }\n}\n\ninterface DeploymentUploadResponse {\n deploymentId: string;\n status: string;\n fileCount: number;\n totalSizeBytes: number;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport { resolveApiUrl, loadConfig } from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { error, spinner, json, isJsonMode, table, info } from '../lib/output';\nimport type { GlobalOptions, ProjectInfo } from '../lib/types';\n\nexport function createProjectsCommand(): Command {\n return new Command('projects')\n .description('List your projects')\n .action(async (_opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const client = new ApiClient({ apiUrl, token });\n const spin = spinner('Fetching projects...');\n const result = await client.get<{ projects: ProjectInfo[] }>('/projects');\n spin.stop();\n\n const projects = result.projects;\n\n if (projects.length === 0) {\n info('No projects found');\n return;\n }\n\n const activeProjectId = config?.projectId;\n\n if (isJsonMode()) {\n json(projects);\n } else {\n table(\n ['', 'ID', 'Name', 'Slug'],\n projects.map((p) => [\n p.id === activeProjectId ? '*' : ' ',\n p.id,\n p.name,\n p.slug,\n ]),\n );\n if (activeProjectId) {\n info(`\\n* = active project (from spacelr.json)`);\n }\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to list projects');\n process.exitCode = 1;\n }\n });\n}\n\nexport async function fetchProjects(\n client: ApiClient,\n): Promise<ProjectInfo[]> {\n const result = await client.get<{ projects: ProjectInfo[] }>('/projects');\n return result.projects;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport { resolveApiUrl, loadConfig, saveConfig } from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { success, error, spinner, json, isJsonMode, info } from '../lib/output';\nimport { promptChoice } from '../lib/prompt';\nimport { fetchProjects } from './projects';\nimport type { GlobalOptions, ProjectInfo } from '../lib/types';\n\nexport function createUseCommand(): Command {\n return new Command('use')\n .description('Set the active project')\n .argument('[project]', 'Project ID or slug')\n .action(async (project: string | undefined, _opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const client = new ApiClient({ apiUrl, token });\n const spin = spinner('Fetching projects...');\n const projects = await fetchProjects(client);\n spin.stop();\n\n if (projects.length === 0) {\n error('No projects found. Create a project first.');\n process.exitCode = 1;\n return;\n }\n\n let selected: ProjectInfo;\n\n if (project) {\n // Find by ID or slug\n const match = projects.find(\n (p) => p.id === project || p.slug === project,\n );\n if (!match) {\n error(`Project \"${project}\" not found`);\n info('Available projects:');\n for (const p of projects) {\n info(` ${p.slug} (${p.id})`);\n }\n process.exitCode = 1;\n return;\n }\n selected = match;\n } else {\n // Interactive selection\n selected = await promptChoice(\n 'Select a project:',\n projects.map((p) => ({\n ...p,\n label: `${p.name} (${p.slug})`,\n })),\n );\n }\n\n // Update config\n const updatedConfig = { ...config, projectId: selected.id };\n saveConfig(updatedConfig);\n\n if (isJsonMode()) {\n json({ projectId: selected.id, name: selected.name, slug: selected.slug });\n } else {\n success(`Now using project \"${selected.name}\" (${selected.slug})`);\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to select project');\n process.exitCode = 1;\n }\n });\n}\n","import * as readline from 'node:readline';\n\nexport async function promptChoice<T extends { label: string }>(\n message: string,\n choices: T[],\n): Promise<T> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n\n console.error(`\\n${message}\\n`);\n choices.forEach((choice, i) => {\n console.error(` ${i + 1}) ${choice.label}`);\n });\n console.error();\n\n return new Promise((resolve, reject) => {\n rl.question(' Enter number: ', (answer) => {\n rl.close();\n const index = parseInt(answer, 10) - 1;\n if (isNaN(index) || index < 0 || index >= choices.length) {\n reject(new Error('Invalid selection'));\n return;\n }\n resolve(choices[index]);\n });\n });\n}\n\nexport async function promptConfirm(message: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n\n return new Promise((resolve) => {\n rl.question(`${message} (y/N) `, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');\n });\n });\n}\n\nexport async function promptInput(message: string, defaultValue?: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n\n const suffix = defaultValue ? ` (${defaultValue})` : '';\n\n return new Promise((resolve) => {\n rl.question(`${message}${suffix}: `, (answer) => {\n rl.close();\n resolve(answer.trim() || defaultValue || '');\n });\n });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport { resolveApiUrl, loadConfig, saveConfig } from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { success, error, warn, spinner, json, isJsonMode, info } from '../lib/output';\nimport { promptChoice, promptInput } from '../lib/prompt';\nimport { fetchProjects } from './projects';\nimport type { GlobalOptions, SpacelrConfig } from '../lib/types';\n\nexport function createInitCommand(): Command {\n return new Command('init')\n .description('Initialize a spacelr.json config in the current directory')\n .action(async (_opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const existingConfig = loadConfig();\n\n const configPath = path.join(process.cwd(), 'spacelr.json');\n if (fs.existsSync(configPath)) {\n warn(`spacelr.json already exists in ${process.cwd()}`);\n info('Use \"spacelr use\" to change the active project');\n return;\n }\n\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, existingConfig);\n\n try {\n const token = requireAuth(globalOpts.token);\n const client = new ApiClient({ apiUrl, token });\n const spin = spinner('Fetching projects...');\n const projects = await fetchProjects(client);\n spin.stop();\n\n if (projects.length === 0) {\n error('No projects found. Create a project in the admin panel first.');\n process.exitCode = 1;\n return;\n }\n\n // Select project\n const selected = await promptChoice(\n 'Select a project:',\n projects.map((p) => ({\n ...p,\n label: `${p.name} (${p.slug})`,\n })),\n );\n\n // Ask for hosting directory\n const hostingDir = await promptInput(\n 'Hosting directory',\n './dist',\n );\n\n const config: SpacelrConfig = {\n projectId: selected.id,\n apiUrl: apiUrl !== 'https://api.spacelr.io' ? apiUrl : undefined,\n hosting: {\n directory: hostingDir,\n },\n database: {\n indexes: {},\n rules: {},\n },\n };\n\n saveConfig(config, configPath);\n\n if (isJsonMode()) {\n json(config);\n } else {\n success(`Created spacelr.json for \"${selected.name}\"`);\n info(`Project: ${selected.slug} (${selected.id})`);\n info(`Hosting directory: ${hostingDir}`);\n info('');\n info('Next steps:');\n info(' spacelr deploy Deploy your site');\n info(' spacelr db indexes pull Pull database indexes');\n info(' spacelr db rules pull Pull database rules');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Initialization failed');\n process.exitCode = 1;\n }\n });\n}\n","import * as path from 'node:path';\nimport { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n} from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { createZipBuffer, countFiles } from '../lib/zip';\nimport {\n error,\n info,\n spinner,\n json,\n isJsonMode,\n formatBytes,\n verbose,\n} from '../lib/output';\nimport type {\n GlobalOptions,\n DeploymentResponse,\n} from '../lib/types';\n\nexport function createDeployCommand(): Command {\n return new Command('deploy')\n .description('Deploy a directory to Spacelr hosting')\n .argument('[directory]', 'Directory to deploy')\n .option('--project <id>', 'Project ID')\n .option('--description <text>', 'Deployment description')\n .option('--no-wait', 'Do not wait for processing to complete')\n .option('--dry-run', 'Show what would be deployed without uploading')\n .action(async (directory: string | undefined, opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n const deployDir = directory ?? config?.hosting?.directory ?? '.';\n const absDir = path.resolve(deployDir);\n\n const client = new ApiClient({ apiUrl, token });\n await deploy(client, projectId, absDir, {\n description: opts.description,\n wait: opts.wait !== false,\n dryRun: opts.dryRun === true,\n });\n } catch (err) {\n error(err instanceof Error ? err.message : 'Deployment failed');\n process.exitCode = 1;\n }\n });\n}\n\ninterface DeployOptions {\n description?: string;\n wait: boolean;\n dryRun: boolean;\n}\n\nasync function deploy(\n client: ApiClient,\n projectId: string,\n directory: string,\n options: DeployOptions,\n): Promise<void> {\n // Step 1: Count files and create ZIP\n const spin = spinner('Preparing deployment...');\n\n const fileCount = countFiles(directory);\n verbose(`Found ${fileCount} files in ${directory}`);\n\n spin.text = 'Creating archive...';\n const zipBuffer = await createZipBuffer(directory);\n verbose(`Archive size: ${formatBytes(zipBuffer.length)}`);\n\n if (options.dryRun) {\n spin.succeed('Dry run complete');\n if (isJsonMode()) {\n json({ dryRun: true, fileCount, archiveSize: zipBuffer.length, directory });\n } else {\n info(`Directory: ${directory}`);\n info(`Files: ${fileCount}`);\n info(`Archive size: ${formatBytes(zipBuffer.length)}`);\n }\n return;\n }\n\n // Step 2: Create deployment\n spin.text = 'Creating deployment...';\n const deployment = await client.post<DeploymentResponse>(\n '/hosting/deployments',\n {\n projectId,\n description: options.description,\n },\n );\n verbose(`Deployment ID: ${deployment.deploymentId}`);\n\n // Step 3: Upload ZIP\n spin.text = `Uploading ${formatBytes(zipBuffer.length)}...`;\n await client.uploadFile(\n `/hosting/deployments/${deployment.deploymentId}/upload`,\n zipBuffer,\n 'deployment.zip',\n );\n\n if (!options.wait) {\n spin.succeed('Upload complete');\n info(`Deployment ${deployment.deploymentId} is processing`);\n if (isJsonMode()) {\n json({ deploymentId: deployment.deploymentId, status: 'processing' });\n }\n return;\n }\n\n // Step 4: Poll for status\n spin.text = 'Processing deployment...';\n const result = await pollDeploymentStatus(\n client,\n deployment.deploymentId,\n spin,\n );\n\n if (result.status === 'active') {\n spin.succeed('Deployment active');\n if (isJsonMode()) {\n json(result);\n } else {\n info(`Deployment ID: ${result.deploymentId}`);\n info(`Files: ${result.fileCount}`);\n info(`Size: ${formatBytes(result.totalSizeBytes)}`);\n }\n } else if (result.status === 'failed') {\n spin.fail('Deployment failed');\n error(result.errorMessage ?? 'Unknown error');\n process.exitCode = 1;\n } else {\n spin.warn(`Deployment status: ${result.status}`);\n if (isJsonMode()) {\n json(result);\n }\n }\n}\n\nasync function pollDeploymentStatus(\n client: ApiClient,\n deploymentId: string,\n spin: { text: string },\n): Promise<DeploymentResponse> {\n const maxAttempts = 120; // 10 minutes (5s intervals)\n for (let i = 0; i < maxAttempts; i++) {\n await sleep(5000);\n const status = await client.get<DeploymentResponse>(\n `/hosting/deployments/${deploymentId}/status`,\n );\n\n verbose(`Poll ${i + 1}: status=${status.status}`);\n spin.text = `Processing deployment... (${status.status})`;\n\n if (\n status.status === 'active' ||\n status.status === 'failed'\n ) {\n return status;\n }\n }\n\n throw new Error('Deployment timed out after 10 minutes');\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport archiver from 'archiver';\n\nexport async function createZipBuffer(directory: string): Promise<Buffer> {\n const absDir = path.resolve(directory);\n if (!fs.existsSync(absDir)) {\n throw new Error(`Directory not found: ${absDir}`);\n }\n if (!fs.statSync(absDir).isDirectory()) {\n throw new Error(`Not a directory: ${absDir}`);\n }\n\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n const archive = archiver('zip', { zlib: { level: 9 } });\n\n archive.on('data', (chunk: Buffer) => chunks.push(chunk));\n archive.on('end', () => resolve(Buffer.concat(chunks)));\n archive.on('error', reject);\n\n archive.directory(absDir, false);\n archive.finalize();\n });\n}\n\nexport function countFiles(directory: string): number {\n const absDir = path.resolve(directory);\n let count = 0;\n\n function walk(dir: string): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile()) {\n count++;\n } else if (entry.isDirectory()) {\n walk(path.join(dir, entry.name));\n }\n }\n }\n\n walk(absDir);\n return count;\n}\n","import { Command } from 'commander';\nimport { createIndexesDeployCommand } from './indexes-deploy';\nimport { createIndexesPullCommand } from './indexes-pull';\nimport { createRulesDeployCommand } from './rules-deploy';\nimport { createRulesPullCommand } from './rules-pull';\n\nexport function createDbCommand(): Command {\n const indexes = new Command('indexes')\n .description('Manage database indexes');\n\n indexes.addCommand(createIndexesDeployCommand());\n indexes.addCommand(createIndexesPullCommand());\n\n const rules = new Command('rules')\n .description('Manage database rules');\n\n rules.addCommand(createRulesDeployCommand());\n rules.addCommand(createRulesPullCommand());\n\n const db = new Command('db')\n .description('Database management commands');\n\n db.addCommand(indexes);\n db.addCommand(rules);\n\n return db;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n} from '../../lib/config';\nimport { requireAuth } from '../../lib/auth';\nimport { success, error, info, spinner, json, isJsonMode, warn } from '../../lib/output';\nimport { promptConfirm } from '../../lib/prompt';\nimport type { GlobalOptions, IndexRuleEntry } from '../../lib/types';\n\nexport function createIndexesDeployCommand(): Command {\n return new Command('deploy')\n .description('Deploy indexes from config to remote')\n .option('--project <id>', 'Project ID')\n .option('--config <path>', 'Config file path')\n .option('--yes', 'Skip confirmation')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig(opts.config);\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n const indexes = config?.database?.indexes;\n\n if (!indexes || Object.keys(indexes).length === 0) {\n warn('No indexes defined in config');\n return;\n }\n\n // Convert index format: config uses 1/-1, API expects asc/desc\n const indexRules = convertIndexFormat(indexes);\n\n const collectionCount = Object.keys(indexRules).length;\n const totalIndexes = Object.values(indexRules).reduce(\n (sum, arr) => sum + arr.length,\n 0,\n );\n\n if (!opts.yes) {\n info(\n `Will deploy ${totalIndexes} index(es) across ${collectionCount} collection(s)`,\n );\n const confirmed = await promptConfirm('Proceed with deployment?');\n if (!confirmed) {\n info('Aborted');\n return;\n }\n }\n\n const spin = spinner('Deploying indexes...');\n const client = new ApiClient({ apiUrl, token });\n const result = await client.put<{ message: string }>(\n `/databases/${projectId}/index-rules`,\n { indexRules },\n );\n\n spin.succeed('Indexes deployed');\n\n if (isJsonMode()) {\n json(result);\n } else {\n success(result.message ?? 'Indexes synced successfully');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to deploy indexes');\n process.exitCode = 1;\n }\n });\n}\n\nfunction convertIndexFormat(\n indexes: Record<string, IndexRuleEntry[]>,\n): Record<string, Array<{ fields: Record<string, 'asc' | 'desc'>; unique?: boolean; sparse?: boolean; ttlSeconds?: number }>> {\n const result: Record<string, Array<{ fields: Record<string, 'asc' | 'desc'>; unique?: boolean; sparse?: boolean; ttlSeconds?: number }>> = {};\n\n for (const [collection, entries] of Object.entries(indexes)) {\n result[collection] = entries.map((entry) => {\n const fields: Record<string, 'asc' | 'desc'> = {};\n for (const [field, direction] of Object.entries(entry.fields)) {\n fields[field] = direction === 1 ? 'asc' : 'desc';\n }\n return {\n fields,\n ...(entry.unique !== undefined && { unique: entry.unique }),\n ...(entry.sparse !== undefined && { sparse: entry.sparse }),\n ...(entry.ttlSeconds !== undefined && { ttlSeconds: entry.ttlSeconds }),\n };\n });\n }\n\n return result;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n saveConfig,\n} from '../../lib/config';\nimport { requireAuth } from '../../lib/auth';\nimport { success, error, spinner, json, isJsonMode, info } from '../../lib/output';\nimport type { GlobalOptions, SpacelrConfig, IndexRuleEntry } from '../../lib/types';\n\ninterface RemoteIndexEntry {\n fields: Record<string, 'asc' | 'desc'>;\n unique?: boolean;\n sparse?: boolean;\n ttlSeconds?: number;\n}\n\nexport function createIndexesPullCommand(): Command {\n return new Command('pull')\n .description('Pull current indexes from remote to config')\n .option('--project <id>', 'Project ID')\n .option('--config <path>', 'Config file path')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig(opts.config);\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n\n const spin = spinner('Pulling indexes...');\n const client = new ApiClient({ apiUrl, token });\n const result = await client.get<{\n indexRules: Record<string, RemoteIndexEntry[]>;\n }>(`/databases/${projectId}/index-rules`);\n\n // Convert from API format (asc/desc) to config format (1/-1)\n const indexes = convertFromRemoteFormat(result.indexRules);\n\n // Update config\n const updatedConfig: SpacelrConfig = {\n ...config,\n projectId: config?.projectId ?? projectId,\n database: {\n ...config?.database,\n indexes,\n },\n };\n\n saveConfig(updatedConfig, opts.config);\n spin.succeed('Indexes pulled');\n\n const collectionCount = Object.keys(indexes).length;\n const totalIndexes = Object.values(indexes).reduce(\n (sum, arr) => sum + arr.length,\n 0,\n );\n\n if (isJsonMode()) {\n json(indexes);\n } else {\n success(\n `Pulled ${totalIndexes} index(es) from ${collectionCount} collection(s)`,\n );\n info('Config file updated');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to pull indexes');\n process.exitCode = 1;\n }\n });\n}\n\nfunction convertFromRemoteFormat(\n remoteIndexes: Record<string, RemoteIndexEntry[]>,\n): Record<string, IndexRuleEntry[]> {\n const result: Record<string, IndexRuleEntry[]> = {};\n\n for (const [collection, entries] of Object.entries(remoteIndexes)) {\n result[collection] = entries.map((entry) => {\n const fields: Record<string, 1 | -1> = {};\n for (const [field, direction] of Object.entries(entry.fields)) {\n fields[field] = direction === 'asc' ? 1 : -1;\n }\n return {\n fields,\n ...(entry.unique !== undefined && { unique: entry.unique }),\n ...(entry.sparse !== undefined && { sparse: entry.sparse }),\n ...(entry.ttlSeconds !== undefined && {\n ttlSeconds: entry.ttlSeconds,\n }),\n };\n });\n }\n\n return result;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n} from '../../lib/config';\nimport { requireAuth } from '../../lib/auth';\nimport { success, error, info, spinner, json, isJsonMode, warn } from '../../lib/output';\nimport { promptConfirm } from '../../lib/prompt';\nimport type { GlobalOptions } from '../../lib/types';\n\nexport function createRulesDeployCommand(): Command {\n return new Command('deploy')\n .description('Deploy rules from config to remote')\n .option('--project <id>', 'Project ID')\n .option('--config <path>', 'Config file path')\n .option('--yes', 'Skip confirmation')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig(opts.config);\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n const rules = config?.database?.rules;\n\n if (!rules || Object.keys(rules).length === 0) {\n warn('No rules defined in config');\n return;\n }\n\n const ruleCount = Object.keys(rules).length;\n\n if (!opts.yes) {\n info(`Will deploy rules for ${ruleCount} collection(s)`);\n const confirmed = await promptConfirm('Proceed with deployment?');\n if (!confirmed) {\n info('Aborted');\n return;\n }\n }\n\n // Validate first\n const spin = spinner('Validating rules...');\n const client = new ApiClient({ apiUrl, token });\n\n await client.post<{ valid: boolean }>(\n `/databases/${projectId}/rules/validate`,\n { rules },\n );\n\n // Deploy\n spin.text = 'Deploying rules...';\n const result = await client.put<{ message: string }>(\n `/databases/${projectId}/rules`,\n { rules },\n );\n\n spin.succeed('Rules deployed');\n\n if (isJsonMode()) {\n json(result);\n } else {\n success(result.message ?? 'Rules deployed successfully');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to deploy rules');\n process.exitCode = 1;\n }\n });\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n saveConfig,\n} from '../../lib/config';\nimport { requireAuth } from '../../lib/auth';\nimport { success, error, spinner, json, isJsonMode, info } from '../../lib/output';\nimport type { GlobalOptions, SpacelrConfig } from '../../lib/types';\n\nexport function createRulesPullCommand(): Command {\n return new Command('pull')\n .description('Pull current rules from remote to config')\n .option('--project <id>', 'Project ID')\n .option('--config <path>', 'Config file path')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig(opts.config);\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n\n const spin = spinner('Pulling rules...');\n const client = new ApiClient({ apiUrl, token });\n const result = await client.get<{ rules: Record<string, unknown> }>(\n `/databases/${projectId}/rules`,\n );\n\n const rules = result.rules;\n\n // Update config\n const updatedConfig: SpacelrConfig = {\n ...config,\n projectId: config?.projectId ?? projectId,\n database: {\n ...config?.database,\n rules,\n },\n };\n\n saveConfig(updatedConfig, opts.config);\n spin.succeed('Rules pulled');\n\n const ruleCount = Object.keys(rules).length;\n\n if (isJsonMode()) {\n json(rules);\n } else {\n success(`Pulled rules for ${ruleCount} collection(s)`);\n info('Config file updated');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to pull rules');\n process.exitCode = 1;\n }\n });\n}\n"],"mappings":"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","names":["import_commander","pc","ora","crypto","fs","path","open","resolve","import_commander","import_commander","path","import_commander","import_commander","resolve","fs","path","import_commander","path","import_commander","fs","path","resolve","archiver","resolve","import_commander","import_commander","import_commander","import_commander","import_commander"]}
|
|
1
|
+
{"version":3,"sources":["../../../../libs/cli/src/index.ts","../../../../libs/cli/src/lib/output.ts","../../../../libs/cli/src/commands/login.ts","../../../../libs/cli/src/lib/auth.ts","../../../../libs/cli/src/lib/config.ts","../../../../libs/cli/src/commands/logout.ts","../../../../libs/cli/src/commands/whoami.ts","../../../../libs/cli/src/lib/api-client.ts","../../../../libs/cli/src/commands/projects.ts","../../../../libs/cli/src/commands/use.ts","../../../../libs/cli/src/lib/prompt.ts","../../../../libs/cli/src/commands/init.ts","../../../../libs/cli/src/commands/deploy.ts","../../../../libs/cli/src/lib/zip.ts","../../../../libs/cli/src/commands/db/index.ts","../../../../libs/cli/src/commands/db/indexes-deploy.ts","../../../../libs/cli/src/commands/db/indexes-pull.ts","../../../../libs/cli/src/commands/db/rules-deploy.ts","../../../../libs/cli/src/commands/db/rules-pull.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { setOutputMode } from './lib/output';\nimport { createLoginCommand } from './commands/login';\nimport { createLogoutCommand } from './commands/logout';\nimport { createWhoamiCommand } from './commands/whoami';\nimport { createProjectsCommand } from './commands/projects';\nimport { createUseCommand } from './commands/use';\nimport { createInitCommand } from './commands/init';\nimport { createDeployCommand } from './commands/deploy';\nimport { createDbCommand } from './commands/db';\n\nconst program = new Command();\n\nprogram\n .name('spacelr')\n .description('CLI tool for the Spacelr platform')\n .version('0.1.0')\n .option('--api-url <url>', 'Override API URL')\n .option('--token <token>', 'Explicit auth token (CI mode)')\n .option('--json', 'Output as JSON')\n .option('--verbose', 'Verbose logging')\n .hook('preAction', (thisCommand) => {\n const opts = thisCommand.optsWithGlobals();\n setOutputMode({\n json: opts['json'] as boolean | undefined,\n verbose: opts['verbose'] as boolean | undefined,\n });\n });\n\nprogram.addCommand(createLoginCommand());\nprogram.addCommand(createLogoutCommand());\nprogram.addCommand(createWhoamiCommand());\nprogram.addCommand(createProjectsCommand());\nprogram.addCommand(createUseCommand());\nprogram.addCommand(createInitCommand());\nprogram.addCommand(createDeployCommand());\nprogram.addCommand(createDbCommand());\n\nprogram.parse();\n","import ora, { type Ora } from 'ora';\nimport pc from 'picocolors';\n\nlet jsonMode = false;\nlet verboseMode = false;\n\nexport function setOutputMode(options: {\n json?: boolean;\n verbose?: boolean;\n}): void {\n jsonMode = options.json ?? false;\n verboseMode = options.verbose ?? false;\n}\n\nexport function isJsonMode(): boolean {\n return jsonMode;\n}\n\nexport function success(message: string): void {\n if (!jsonMode) {\n console.log(pc.green(`\\u2713 ${message}`));\n }\n}\n\nexport function error(message: string): void {\n if (!jsonMode) {\n console.error(pc.red(`\\u2717 ${message}`));\n }\n}\n\nexport function warn(message: string): void {\n if (!jsonMode) {\n console.warn(pc.yellow(`! ${message}`));\n }\n}\n\nexport function info(message: string): void {\n if (!jsonMode) {\n console.log(pc.cyan(`\\u2139 ${message}`));\n }\n}\n\nexport function verbose(message: string): void {\n if (verboseMode && !jsonMode) {\n console.log(pc.dim(` ${message}`));\n }\n}\n\nexport function json(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\nexport function table(\n headers: string[],\n rows: string[][],\n): void {\n if (jsonMode) return;\n\n const colWidths = headers.map((h, i) => {\n const maxRow = rows.reduce(\n (max, row) => Math.max(max, (row[i] ?? '').length),\n 0,\n );\n return Math.max(h.length, maxRow);\n });\n\n const headerLine = headers\n .map((h, i) => pc.bold(h.padEnd(colWidths[i] ?? 0)))\n .join(' ');\n const separator = colWidths.map((w) => '-'.repeat(w)).join(' ');\n\n console.log(headerLine);\n console.log(separator);\n for (const row of rows) {\n console.log(\n row.map((cell, i) => cell.padEnd(colWidths[i] ?? 0)).join(' '),\n );\n }\n}\n\nexport function spinner(text: string): Ora {\n if (jsonMode) {\n return ora({ text, isSilent: true });\n }\n return ora(text).start();\n}\n\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const units = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const value = bytes / Math.pow(1024, i);\n return `${value.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;\n}\n","import * as http from 'node:http';\nimport * as crypto from 'node:crypto';\nimport { Command } from 'commander';\nimport open from 'open';\nimport { generatePKCE, storeCredentials } from '../lib/auth';\nimport { resolveApiUrl, loadConfig } from '../lib/config';\nimport { success, error, info, spinner, json, isJsonMode } from '../lib/output';\nimport type { GlobalOptions, TokenResponse, StoredCredentials } from '../lib/types';\n\nconst CLI_CLIENT_ID = 'spacelr-cli';\n\nexport function createLoginCommand(): Command {\n return new Command('login')\n .description('Authenticate with Spacelr via browser')\n .option('--auth-url <url>', 'OAuth server URL (defaults to --api-url)')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n const authUrl = (opts.authUrl as string | undefined) ?? apiUrl;\n\n try {\n const credentials = await performLogin(authUrl, apiUrl);\n storeCredentials(credentials);\n\n if (isJsonMode()) {\n json({ success: true, expiresAt: credentials.expiresAt });\n } else {\n success('Logged in successfully');\n info(`Credentials stored in ~/.spacelr/credentials.json`);\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Login failed');\n process.exitCode = 1;\n }\n });\n}\n\nasync function performLogin(authUrl: string, apiUrl: string): Promise<StoredCredentials> {\n const { codeVerifier, codeChallenge } = generatePKCE();\n const state = crypto.randomBytes(16).toString('base64url');\n\n // Start local HTTP server on a random port\n const { port, waitForCode, close } = await startCallbackServer(state);\n\n const authorizeUrl = buildAuthorizeUrl(authUrl, port, codeChallenge, state);\n\n info(`Opening browser for authentication...`);\n info(`If the browser doesn't open, visit: ${authorizeUrl}`);\n\n await open(authorizeUrl);\n\n const spin = spinner('Waiting for authentication...');\n\n try {\n const code = await waitForCode;\n spin.text = 'Exchanging authorization code...';\n\n const tokenResponse = await exchangeCode(\n authUrl,\n code,\n codeVerifier,\n port,\n );\n\n spin.succeed('Authentication complete');\n\n return {\n accessToken: tokenResponse.access_token,\n refreshToken: tokenResponse.refresh_token,\n expiresAt: Date.now() + tokenResponse.expires_in * 1000,\n apiUrl,\n };\n } catch (err) {\n spin.fail('Authentication failed');\n throw err;\n } finally {\n close();\n }\n}\n\nfunction buildAuthorizeUrl(\n apiUrl: string,\n port: number,\n codeChallenge: string,\n state: string,\n): string {\n const params = new URLSearchParams({\n client_id: CLI_CLIENT_ID,\n redirect_uri: `http://127.0.0.1:${port}/callback`,\n response_type: 'code',\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n scope: 'openid profile email',\n state,\n });\n return `${apiUrl}/auth/authorize?${params.toString()}`;\n}\n\nasync function startCallbackServer(expectedState: string): Promise<{\n port: number;\n waitForCode: Promise<string>;\n close: () => void;\n}> {\n return new Promise((resolveServer) => {\n let resolveCode: (code: string) => void;\n let rejectCode: (err: Error) => void;\n\n const waitForCode = new Promise<string>((resolve, reject) => {\n resolveCode = resolve;\n rejectCode = reject;\n });\n\n const server = http.createServer((req, res) => {\n const url = new URL(req.url ?? '/', `http://127.0.0.1`);\n\n if (url.pathname === '/callback') {\n const code = url.searchParams.get('code');\n const errorParam = url.searchParams.get('error');\n const returnedState = url.searchParams.get('state');\n\n if (errorParam) {\n const description =\n url.searchParams.get('error_description') ?? errorParam;\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(errorPage(description));\n rejectCode(new Error(`OAuth error: ${description}`));\n return;\n }\n\n // CSRF protection: verify state matches\n if (returnedState !== expectedState) {\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(errorPage('Invalid state parameter (possible CSRF attack)'));\n rejectCode(new Error('OAuth state mismatch'));\n return;\n }\n\n if (!code) {\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(errorPage('No authorization code received'));\n rejectCode(new Error('No authorization code received'));\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(successPage());\n resolveCode(code);\n } else {\n res.writeHead(404);\n res.end();\n }\n });\n\n // Timeout after 5 minutes\n const timeout = setTimeout(() => {\n rejectCode(new Error('Login timed out after 5 minutes'));\n server.close();\n }, 5 * 60 * 1000);\n\n server.listen(0, '127.0.0.1', () => {\n const address = server.address();\n const port =\n typeof address === 'object' && address ? address.port : 0;\n\n resolveServer({\n port,\n waitForCode,\n close: () => {\n clearTimeout(timeout);\n server.close();\n },\n });\n });\n });\n}\n\nasync function exchangeCode(\n apiUrl: string,\n code: string,\n codeVerifier: string,\n port: number,\n): Promise<TokenResponse> {\n const response = await fetch(`${apiUrl}/auth/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n code_verifier: codeVerifier,\n client_id: CLI_CLIENT_ID,\n redirect_uri: `http://127.0.0.1:${port}/callback`,\n }),\n });\n\n if (!response.ok) {\n let message: string;\n try {\n const body = (await response.json()) as { message?: string; error?: string };\n message = body.message ?? body.error ?? response.statusText;\n } catch {\n message = response.statusText;\n }\n throw new Error(`Token exchange failed: ${message}`);\n }\n\n return (await response.json()) as TokenResponse;\n}\n\nfunction successPage(): string {\n return `<!DOCTYPE html>\n<html><head><title>Spacelr CLI</title>\n<style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f8f9fa;}\n.box{text-align:center;padding:2rem;}.check{font-size:3rem;color:#22c55e;}</style></head>\n<body><div class=\"box\"><div class=\"check\">✓</div><h1>Authenticated</h1><p>You can close this window and return to the terminal.</p></div></body></html>`;\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\nfunction errorPage(message: string): string {\n return `<!DOCTYPE html>\n<html><head><title>Spacelr CLI</title>\n<style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f8f9fa;}\n.box{text-align:center;padding:2rem;}.x{font-size:3rem;color:#ef4444;}</style></head>\n<body><div class=\"box\"><div class=\"x\">✗</div><h1>Authentication Failed</h1><p>${escapeHtml(message)}</p></div></body></html>`;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\nimport type { StoredCredentials, PKCEChallenge } from './types';\n\nfunction getCredentialsDir(): string {\n return path.join(\n process.env['HOME'] ?? process.env['USERPROFILE'] ?? '~',\n '.spacelr',\n );\n}\n\nfunction getCredentialsFile(): string {\n return path.join(getCredentialsDir(), 'credentials.json');\n}\n\nexport function getStoredCredentials(): StoredCredentials | null {\n try {\n const file = getCredentialsFile();\n if (!fs.existsSync(file)) return null;\n const content = fs.readFileSync(file, 'utf-8');\n return JSON.parse(content) as StoredCredentials;\n } catch {\n return null;\n }\n}\n\nexport function storeCredentials(credentials: StoredCredentials): void {\n const dir = getCredentialsDir();\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n fs.writeFileSync(\n getCredentialsFile(),\n JSON.stringify(credentials, null, 2),\n { mode: 0o600 },\n );\n}\n\nexport function clearCredentials(): void {\n try {\n const file = getCredentialsFile();\n if (fs.existsSync(file)) {\n fs.unlinkSync(file);\n }\n } catch {\n // Ignore errors during cleanup\n }\n}\n\nexport function isTokenExpired(credentials: StoredCredentials): boolean {\n // Add 60 second buffer\n return Date.now() >= credentials.expiresAt - 60_000;\n}\n\nexport function resolveToken(flagToken?: string): string | null {\n if (flagToken) return flagToken;\n if (process.env['SPACELR_TOKEN']) return process.env['SPACELR_TOKEN'];\n const credentials = getStoredCredentials();\n if (credentials && !isTokenExpired(credentials)) {\n return credentials.accessToken;\n }\n return null;\n}\n\nexport class AuthRequiredError extends Error {\n constructor() {\n super('Not logged in. Run \"spacelr login\" to authenticate.');\n this.name = 'AuthRequiredError';\n }\n}\n\n/**\n * Resolves a token or throws AuthRequiredError.\n * Use in commands that require authentication.\n */\nexport function requireAuth(flagToken?: string): string {\n const token = resolveToken(flagToken);\n if (!token) {\n throw new AuthRequiredError();\n }\n return token;\n}\n\nexport function generatePKCE(): PKCEChallenge {\n const codeVerifier = crypto.randomBytes(32).toString('base64url');\n const codeChallenge = crypto\n .createHash('sha256')\n .update(codeVerifier)\n .digest('base64url');\n return { codeVerifier, codeChallenge };\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { SpacelrConfig, DatabaseRules, DatabaseIndexes } from './types';\n\nconst CONFIG_FILENAME = 'spacelr.json';\nexport const RULES_FILENAME = 'spacelr.rules.json';\nexport const INDEXES_FILENAME = 'spacelr.indexes.json';\n\nfunction readJsonFile<T>(filePath: string, label: string): T {\n const content = fs.readFileSync(filePath, 'utf-8');\n try {\n return JSON.parse(content) as T;\n } catch (err) {\n const detail = err instanceof Error ? `: ${err.message}` : '';\n throw new Error(\n `Invalid JSON in ${label}: ${filePath}${detail}\\nPlease check the file for syntax errors.`,\n );\n }\n}\n\nfunction writeJsonFile(filePath: string, data: unknown): void {\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\\n', 'utf-8');\n}\n\nfunction resolveSiblingPath(filename: string, configPath?: string): string {\n const resolved = configPath ?? findConfigPath();\n const dir = resolved ? path.dirname(resolved) : process.cwd();\n return path.join(dir, filename);\n}\n\nexport function findConfigPath(startDir?: string): string | null {\n let dir = startDir ?? process.cwd();\n\n while (true) {\n const candidate = path.join(dir, CONFIG_FILENAME);\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n const parent = path.dirname(dir);\n if (parent === dir) {\n return null;\n }\n dir = parent;\n }\n}\n\nexport function loadConfig(configPath?: string): SpacelrConfig | null {\n const resolved = configPath ?? findConfigPath();\n if (!resolved || !fs.existsSync(resolved)) return null;\n return readJsonFile<SpacelrConfig>(resolved, 'config file');\n}\n\nexport function saveConfig(\n config: SpacelrConfig,\n configPath?: string,\n): void {\n const resolved = configPath ?? findConfigPath() ?? path.join(process.cwd(), CONFIG_FILENAME);\n writeJsonFile(resolved, config);\n}\n\nexport function resolveProjectId(\n flagValue?: string,\n config?: SpacelrConfig | null,\n): string {\n const projectId = flagValue ?? config?.projectId;\n if (!projectId) {\n throw new Error(\n 'Project ID is required. Provide --project <id> or set \"projectId\" in spacelr.json',\n );\n }\n return projectId;\n}\n\nexport function resolveApiUrl(\n flagValue?: string,\n config?: SpacelrConfig | null,\n): string {\n return (\n flagValue ??\n config?.apiUrl ??\n process.env['SPACELR_API_URL'] ??\n 'https://api.spacelr.io'\n );\n}\n\nexport function loadRules(configPath?: string): DatabaseRules | null {\n const filePath = resolveSiblingPath(RULES_FILENAME, configPath);\n if (!fs.existsSync(filePath)) return null;\n return readJsonFile<DatabaseRules>(filePath, 'rules file');\n}\n\nexport function saveRules(rules: DatabaseRules, configPath?: string): void {\n writeJsonFile(resolveSiblingPath(RULES_FILENAME, configPath), rules);\n}\n\nexport function loadIndexes(configPath?: string): DatabaseIndexes | null {\n const filePath = resolveSiblingPath(INDEXES_FILENAME, configPath);\n if (!fs.existsSync(filePath)) return null;\n return readJsonFile<DatabaseIndexes>(filePath, 'indexes file');\n}\n\nexport function saveIndexes(indexes: DatabaseIndexes, configPath?: string): void {\n writeJsonFile(resolveSiblingPath(INDEXES_FILENAME, configPath), indexes);\n}\n","import { Command } from 'commander';\nimport { clearCredentials, getStoredCredentials } from '../lib/auth';\nimport { success, warn, json, isJsonMode } from '../lib/output';\nimport type { GlobalOptions } from '../lib/types';\n\nexport function createLogoutCommand(): Command {\n return new Command('logout')\n .description('Clear stored credentials')\n .action(async (_opts, cmd: Command) => {\n cmd.optsWithGlobals<GlobalOptions>();\n\n const existing = getStoredCredentials();\n clearCredentials();\n\n if (isJsonMode()) {\n json({ success: true, hadCredentials: !!existing });\n } else if (existing) {\n success('Logged out successfully');\n } else {\n warn('No credentials found');\n }\n });\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport { resolveApiUrl, loadConfig } from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { success, error, info, json, isJsonMode } from '../lib/output';\nimport type { GlobalOptions, UserInfo } from '../lib/types';\n\nexport function createWhoamiCommand(): Command {\n return new Command('whoami')\n .description('Show current authenticated user')\n .action(async (_opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const client = new ApiClient({ apiUrl, token });\n const response = await client.get<{ user: UserInfo }>('/auth/me');\n const user = response.user;\n\n if (isJsonMode()) {\n json(user);\n } else {\n success(`Logged in as ${user.email ?? user.username ?? user.id}`);\n if (user.displayName) info(`Name: ${user.displayName}`);\n if (user.roles?.length) info(`Roles: ${user.roles.join(', ')}`);\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to get user info');\n process.exitCode = 1;\n }\n });\n}\n","import {\n getStoredCredentials,\n storeCredentials,\n isTokenExpired,\n} from './auth';\nimport { verbose } from './output';\nimport type { StoredCredentials } from './types';\n\ninterface ApiClientOptions {\n apiUrl: string;\n token?: string;\n}\n\ninterface RequestOptions {\n method?: string;\n body?: BodyInit | Record<string, unknown>;\n headers?: Record<string, string>;\n timeout?: number;\n}\n\nexport class ApiClient {\n private readonly apiUrl: string;\n private explicitToken?: string;\n private refreshing: Promise<string | null> | null = null;\n\n constructor(options: ApiClientOptions) {\n this.apiUrl = options.apiUrl.replace(/\\/+$/, '');\n this.explicitToken = options.token;\n }\n\n private async getToken(): Promise<string | null> {\n if (this.explicitToken) return this.explicitToken;\n\n const envToken = process.env['SPACELR_TOKEN'];\n if (envToken) return envToken;\n\n const credentials = getStoredCredentials();\n if (!credentials) return null;\n\n if (!isTokenExpired(credentials)) {\n return credentials.accessToken;\n }\n\n // Token expired, try refreshing\n if (credentials.refreshToken) {\n return this.refreshAccessToken(credentials);\n }\n\n return null;\n }\n\n private async refreshAccessToken(\n credentials: StoredCredentials,\n ): Promise<string | null> {\n // Deduplicate concurrent refreshes\n if (this.refreshing) return this.refreshing;\n\n this.refreshing = (async () => {\n try {\n verbose('Refreshing access token...');\n const response = await fetch(`${this.apiUrl}/auth/refresh`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n refreshToken: credentials.refreshToken ?? '',\n }),\n });\n\n if (!response.ok) {\n verbose('Token refresh failed');\n return null;\n }\n\n const data = (await response.json()) as { access_token: string; refresh_token?: string };\n const newCredentials: StoredCredentials = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token ?? credentials.refreshToken,\n // Admin refresh endpoint doesn't return expires_in; default to 1 hour\n expiresAt: Date.now() + 3600 * 1000,\n apiUrl: credentials.apiUrl,\n };\n storeCredentials(newCredentials);\n verbose('Token refreshed successfully');\n return data.access_token;\n } catch {\n verbose('Token refresh error');\n return null;\n } finally {\n this.refreshing = null;\n }\n })();\n\n return this.refreshing;\n }\n\n private serializeBody(\n body: RequestOptions['body'],\n contentType: string | undefined,\n ): BodyInit | undefined {\n if (!body) return undefined;\n if (contentType === 'application/json') {\n return JSON.stringify(body);\n }\n // Buffer, string, URLSearchParams, etc. are already valid BodyInit\n return body as BodyInit;\n }\n\n private async request<T>(\n path: string,\n options: RequestOptions = {},\n ): Promise<T> {\n const { method = 'GET', body, headers = {}, timeout = 30_000 } = options;\n const url = `${this.apiUrl}${path}`;\n\n const token = await this.getToken();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n if (body && !headers['Content-Type']) {\n headers['Content-Type'] = 'application/json';\n }\n\n const serializedBody = this.serializeBody(body, headers['Content-Type']);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n\n verbose(`${method} ${url}`);\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: serializedBody,\n signal: controller.signal,\n });\n\n if (response.status === 401 && !this.explicitToken) {\n // Try refresh once\n const credentials = getStoredCredentials();\n if (credentials?.refreshToken) {\n const newToken = await this.refreshAccessToken(credentials);\n if (newToken) {\n headers['Authorization'] = `Bearer ${newToken}`;\n const retryController = new AbortController();\n const retryTimer = setTimeout(() => retryController.abort(), timeout);\n const retryResponse = await fetch(url, {\n method,\n headers,\n body: serializedBody,\n signal: retryController.signal,\n });\n clearTimeout(retryTimer);\n if (!retryResponse.ok) {\n await this.throwApiError(retryResponse);\n }\n return (await retryResponse.json()) as T;\n }\n }\n throw new Error(\n 'Authentication required. Run \"spacelr login\" to authenticate.',\n );\n }\n\n if (!response.ok) {\n await this.throwApiError(response);\n }\n\n const contentType = response.headers.get('content-type');\n if (contentType?.includes('application/json')) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n throw new Error(`Request timed out: ${method} ${path}`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async throwApiError(response: Response): Promise<never> {\n let message: string;\n try {\n const body = (await response.json()) as { message?: string; error?: string };\n message = body.message ?? body.error ?? response.statusText;\n } catch {\n message = response.statusText;\n }\n throw new Error(`API error (${response.status}): ${message}`);\n }\n\n async get<T>(path: string, timeout?: number): Promise<T> {\n return this.request<T>(path, { timeout });\n }\n\n async post<T>(path: string, body?: Record<string, unknown> | BodyInit, timeout?: number): Promise<T> {\n return this.request<T>(path, { method: 'POST', body, timeout });\n }\n\n async put<T>(path: string, body?: Record<string, unknown> | BodyInit, timeout?: number): Promise<T> {\n return this.request<T>(path, { method: 'PUT', body, timeout });\n }\n\n async delete<T>(path: string, timeout?: number): Promise<T> {\n return this.request<T>(path, { method: 'DELETE', timeout });\n }\n\n async uploadFile(\n path: string,\n fileBuffer: Buffer,\n filename: string,\n ): Promise<DeploymentUploadResponse> {\n const boundary = `----spacelr${Date.now()}`;\n const parts: Buffer[] = [];\n\n // Build multipart body manually (no form-data dependency needed)\n const header = Buffer.from(\n `--${boundary}\\r\\n` +\n `Content-Disposition: form-data; name=\"file\"; filename=\"${filename}\"\\r\\n` +\n `Content-Type: application/zip\\r\\n\\r\\n`,\n );\n const footer = Buffer.from(`\\r\\n--${boundary}--\\r\\n`);\n parts.push(header, fileBuffer, footer);\n const body = Buffer.concat(parts);\n\n return this.request<DeploymentUploadResponse>(path, {\n method: 'POST',\n body,\n headers: {\n 'Content-Type': `multipart/form-data; boundary=${boundary}`,\n },\n timeout: 300_000, // 5 minutes for uploads\n });\n }\n}\n\ninterface DeploymentUploadResponse {\n deploymentId: string;\n status: string;\n fileCount: number;\n totalSizeBytes: number;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport { resolveApiUrl, loadConfig } from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { error, spinner, json, isJsonMode, table, info } from '../lib/output';\nimport type { GlobalOptions, ProjectInfo } from '../lib/types';\n\nexport function createProjectsCommand(): Command {\n return new Command('projects')\n .description('List your projects')\n .action(async (_opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const client = new ApiClient({ apiUrl, token });\n const spin = spinner('Fetching projects...');\n const result = await client.get<{ projects: ProjectInfo[] }>('/projects');\n spin.stop();\n\n const projects = result.projects;\n\n if (projects.length === 0) {\n info('No projects found');\n return;\n }\n\n const activeProjectId = config?.projectId;\n\n if (isJsonMode()) {\n json(projects);\n } else {\n table(\n ['', 'ID', 'Name', 'Slug'],\n projects.map((p) => [\n p.id === activeProjectId ? '*' : ' ',\n p.id,\n p.name,\n p.slug,\n ]),\n );\n if (activeProjectId) {\n info(`\\n* = active project (from spacelr.json)`);\n }\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to list projects');\n process.exitCode = 1;\n }\n });\n}\n\nexport async function fetchProjects(\n client: ApiClient,\n): Promise<ProjectInfo[]> {\n const result = await client.get<{ projects: ProjectInfo[] }>('/projects');\n return result.projects;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport { resolveApiUrl, loadConfig, saveConfig } from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { success, error, spinner, json, isJsonMode, info } from '../lib/output';\nimport { promptChoice } from '../lib/prompt';\nimport { fetchProjects } from './projects';\nimport type { GlobalOptions, ProjectInfo } from '../lib/types';\n\nexport function createUseCommand(): Command {\n return new Command('use')\n .description('Set the active project')\n .argument('[project]', 'Project ID or slug')\n .action(async (project: string | undefined, _opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const client = new ApiClient({ apiUrl, token });\n const spin = spinner('Fetching projects...');\n const projects = await fetchProjects(client);\n spin.stop();\n\n if (projects.length === 0) {\n error('No projects found. Create a project first.');\n process.exitCode = 1;\n return;\n }\n\n let selected: ProjectInfo;\n\n if (project) {\n // Find by ID or slug\n const match = projects.find(\n (p) => p.id === project || p.slug === project,\n );\n if (!match) {\n error(`Project \"${project}\" not found`);\n info('Available projects:');\n for (const p of projects) {\n info(` ${p.slug} (${p.id})`);\n }\n process.exitCode = 1;\n return;\n }\n selected = match;\n } else {\n // Interactive selection\n selected = await promptChoice(\n 'Select a project:',\n projects.map((p) => ({\n ...p,\n label: `${p.name} (${p.slug})`,\n })),\n );\n }\n\n // Update config\n const updatedConfig = { ...config, projectId: selected.id };\n saveConfig(updatedConfig);\n\n if (isJsonMode()) {\n json({ projectId: selected.id, name: selected.name, slug: selected.slug });\n } else {\n success(`Now using project \"${selected.name}\" (${selected.slug})`);\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to select project');\n process.exitCode = 1;\n }\n });\n}\n","import * as readline from 'node:readline';\n\nexport async function promptChoice<T extends { label: string }>(\n message: string,\n choices: T[],\n): Promise<T> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n\n console.error(`\\n${message}\\n`);\n choices.forEach((choice, i) => {\n console.error(` ${i + 1}) ${choice.label}`);\n });\n console.error();\n\n return new Promise((resolve, reject) => {\n rl.question(' Enter number: ', (answer) => {\n rl.close();\n const index = parseInt(answer, 10) - 1;\n if (isNaN(index) || index < 0 || index >= choices.length) {\n reject(new Error('Invalid selection'));\n return;\n }\n resolve(choices[index]);\n });\n });\n}\n\nexport async function promptConfirm(message: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n\n return new Promise((resolve) => {\n rl.question(`${message} (y/N) `, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');\n });\n });\n}\n\nexport async function promptInput(message: string, defaultValue?: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n\n const suffix = defaultValue ? ` (${defaultValue})` : '';\n\n return new Promise((resolve) => {\n rl.question(`${message}${suffix}: `, (answer) => {\n rl.close();\n resolve(answer.trim() || defaultValue || '');\n });\n });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport { resolveApiUrl, loadConfig, saveConfig } from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { success, error, warn, spinner, json, isJsonMode, info } from '../lib/output';\nimport { promptChoice, promptInput } from '../lib/prompt';\nimport { fetchProjects } from './projects';\nimport type { GlobalOptions, SpacelrConfig } from '../lib/types';\n\nexport function createInitCommand(): Command {\n return new Command('init')\n .description('Initialize a spacelr.json config in the current directory')\n .action(async (_opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const existingConfig = loadConfig();\n\n const configPath = path.join(process.cwd(), 'spacelr.json');\n if (fs.existsSync(configPath)) {\n warn(`spacelr.json already exists in ${process.cwd()}`);\n info('Use \"spacelr use\" to change the active project');\n return;\n }\n\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, existingConfig);\n\n try {\n const token = requireAuth(globalOpts.token);\n const client = new ApiClient({ apiUrl, token });\n const spin = spinner('Fetching projects...');\n const projects = await fetchProjects(client);\n spin.stop();\n\n if (projects.length === 0) {\n error('No projects found. Create a project in the admin panel first.');\n process.exitCode = 1;\n return;\n }\n\n // Select project\n const selected = await promptChoice(\n 'Select a project:',\n projects.map((p) => ({\n ...p,\n label: `${p.name} (${p.slug})`,\n })),\n );\n\n // Ask for hosting directory\n const hostingDir = await promptInput(\n 'Hosting directory',\n './dist',\n );\n\n const config: SpacelrConfig = {\n projectId: selected.id,\n apiUrl: apiUrl !== 'https://api.spacelr.io' ? apiUrl : undefined,\n hosting: {\n directory: hostingDir,\n },\n };\n\n saveConfig(config, configPath);\n\n if (isJsonMode()) {\n json(config);\n } else {\n success(`Created spacelr.json for \"${selected.name}\"`);\n info(`Project: ${selected.slug} (${selected.id})`);\n info(`Hosting directory: ${hostingDir}`);\n info('');\n info('Next steps:');\n info(' spacelr deploy Deploy your site');\n info(' spacelr db indexes pull Pull database indexes');\n info(' spacelr db rules pull Pull database rules');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Initialization failed');\n process.exitCode = 1;\n }\n });\n}\n","import * as path from 'node:path';\nimport { Command } from 'commander';\nimport { ApiClient } from '../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n} from '../lib/config';\nimport { requireAuth } from '../lib/auth';\nimport { createZipBuffer, countFiles } from '../lib/zip';\nimport {\n error,\n info,\n spinner,\n json,\n isJsonMode,\n formatBytes,\n verbose,\n} from '../lib/output';\nimport type {\n GlobalOptions,\n DeploymentResponse,\n} from '../lib/types';\n\nexport function createDeployCommand(): Command {\n return new Command('deploy')\n .description('Deploy a directory to Spacelr hosting')\n .argument('[directory]', 'Directory to deploy')\n .option('--project <id>', 'Project ID')\n .option('--description <text>', 'Deployment description')\n .option('--no-wait', 'Do not wait for processing to complete')\n .option('--dry-run', 'Show what would be deployed without uploading')\n .action(async (directory: string | undefined, opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig();\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n const deployDir = directory ?? config?.hosting?.directory ?? '.';\n const absDir = path.resolve(deployDir);\n\n const client = new ApiClient({ apiUrl, token });\n await deploy(client, projectId, absDir, {\n description: opts.description,\n wait: opts.wait !== false,\n dryRun: opts.dryRun === true,\n });\n } catch (err) {\n error(err instanceof Error ? err.message : 'Deployment failed');\n process.exitCode = 1;\n }\n });\n}\n\ninterface DeployOptions {\n description?: string;\n wait: boolean;\n dryRun: boolean;\n}\n\nasync function deploy(\n client: ApiClient,\n projectId: string,\n directory: string,\n options: DeployOptions,\n): Promise<void> {\n // Step 1: Count files and create ZIP\n const spin = spinner('Preparing deployment...');\n\n const fileCount = countFiles(directory);\n verbose(`Found ${fileCount} files in ${directory}`);\n\n spin.text = 'Creating archive...';\n const zipBuffer = await createZipBuffer(directory);\n verbose(`Archive size: ${formatBytes(zipBuffer.length)}`);\n\n if (options.dryRun) {\n spin.succeed('Dry run complete');\n if (isJsonMode()) {\n json({ dryRun: true, fileCount, archiveSize: zipBuffer.length, directory });\n } else {\n info(`Directory: ${directory}`);\n info(`Files: ${fileCount}`);\n info(`Archive size: ${formatBytes(zipBuffer.length)}`);\n }\n return;\n }\n\n // Step 2: Create deployment\n spin.text = 'Creating deployment...';\n const deployment = await client.post<DeploymentResponse>(\n '/hosting/deployments',\n {\n projectId,\n description: options.description,\n },\n );\n verbose(`Deployment ID: ${deployment.deploymentId}`);\n\n // Step 3: Upload ZIP\n spin.text = `Uploading ${formatBytes(zipBuffer.length)}...`;\n await client.uploadFile(\n `/hosting/${projectId}/deployments/${deployment.deploymentId}/upload`,\n zipBuffer,\n 'deployment.zip',\n );\n\n if (!options.wait) {\n spin.succeed('Upload complete');\n info(`Deployment ${deployment.deploymentId} is processing`);\n if (isJsonMode()) {\n json({ deploymentId: deployment.deploymentId, status: 'processing' });\n }\n return;\n }\n\n // Step 4: Poll for status\n spin.text = 'Processing deployment...';\n const result = await pollDeploymentStatus(\n client,\n projectId,\n deployment.deploymentId,\n spin,\n );\n\n if (result.status === 'active') {\n spin.succeed('Deployment active');\n if (isJsonMode()) {\n json(result);\n } else {\n info(`Deployment ID: ${result.deploymentId}`);\n info(`Files: ${result.fileCount}`);\n info(`Size: ${formatBytes(result.totalSizeBytes)}`);\n }\n } else if (result.status === 'failed') {\n spin.fail('Deployment failed');\n error(result.errorMessage ?? 'Unknown error');\n process.exitCode = 1;\n } else {\n spin.warn(`Deployment status: ${result.status}`);\n if (isJsonMode()) {\n json(result);\n }\n }\n}\n\nasync function pollDeploymentStatus(\n client: ApiClient,\n projectId: string,\n deploymentId: string,\n spin: { text: string },\n): Promise<DeploymentResponse> {\n const maxAttempts = 120; // 10 minutes (5s intervals)\n for (let i = 0; i < maxAttempts; i++) {\n await sleep(5000);\n const status = await client.get<DeploymentResponse>(\n `/hosting/${projectId}/deployments/${deploymentId}/status`,\n );\n\n verbose(`Poll ${i + 1}: status=${status.status}`);\n spin.text = `Processing deployment... (${status.status})`;\n\n if (\n status.status === 'active' ||\n status.status === 'failed'\n ) {\n return status;\n }\n }\n\n throw new Error('Deployment timed out after 10 minutes');\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport archiver from 'archiver';\n\nexport async function createZipBuffer(directory: string): Promise<Buffer> {\n const absDir = path.resolve(directory);\n if (!fs.existsSync(absDir)) {\n throw new Error(`Directory not found: ${absDir}`);\n }\n if (!fs.statSync(absDir).isDirectory()) {\n throw new Error(`Not a directory: ${absDir}`);\n }\n\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n const archive = archiver('zip', { zlib: { level: 9 } });\n\n archive.on('data', (chunk: Buffer) => chunks.push(chunk));\n archive.on('end', () => resolve(Buffer.concat(chunks)));\n archive.on('error', reject);\n\n archive.directory(absDir, false);\n archive.finalize();\n });\n}\n\nexport function countFiles(directory: string): number {\n const absDir = path.resolve(directory);\n let count = 0;\n\n function walk(dir: string): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile()) {\n count++;\n } else if (entry.isDirectory()) {\n walk(path.join(dir, entry.name));\n }\n }\n }\n\n walk(absDir);\n return count;\n}\n","import { Command } from 'commander';\nimport { createIndexesDeployCommand } from './indexes-deploy';\nimport { createIndexesPullCommand } from './indexes-pull';\nimport { createRulesDeployCommand } from './rules-deploy';\nimport { createRulesPullCommand } from './rules-pull';\n\nexport function createDbCommand(): Command {\n const indexes = new Command('indexes')\n .description('Manage database indexes');\n\n indexes.addCommand(createIndexesDeployCommand());\n indexes.addCommand(createIndexesPullCommand());\n\n const rules = new Command('rules')\n .description('Manage database rules');\n\n rules.addCommand(createRulesDeployCommand());\n rules.addCommand(createRulesPullCommand());\n\n const db = new Command('db')\n .description('Database management commands');\n\n db.addCommand(indexes);\n db.addCommand(rules);\n\n return db;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n loadIndexes,\n} from '../../lib/config';\nimport { requireAuth } from '../../lib/auth';\nimport { success, error, info, spinner, json, isJsonMode, warn } from '../../lib/output';\nimport { promptConfirm } from '../../lib/prompt';\nimport type { GlobalOptions, IndexRuleEntry, RemoteIndexEntry } from '../../lib/types';\n\nexport function createIndexesDeployCommand(): Command {\n return new Command('deploy')\n .description('Deploy indexes from spacelr.indexes.json to remote')\n .option('--project <id>', 'Project ID')\n .option('--config <path>', 'Config file path')\n .option('--yes', 'Skip confirmation')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig(opts.config);\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n const indexes = loadIndexes(opts.config);\n\n if (!indexes || Object.keys(indexes).length === 0) {\n warn('No indexes found in spacelr.indexes.json');\n return;\n }\n\n // Convert index format: config uses 1/-1, API expects asc/desc\n const indexRules = convertIndexFormat(indexes);\n\n const collectionCount = Object.keys(indexRules).length;\n const totalIndexes = Object.values(indexRules).reduce(\n (sum, arr) => sum + arr.length,\n 0,\n );\n\n if (!opts.yes) {\n info(\n `Will deploy ${totalIndexes} index(es) across ${collectionCount} collection(s)`,\n );\n const confirmed = await promptConfirm('Proceed with deployment?');\n if (!confirmed) {\n info('Aborted');\n return;\n }\n }\n\n const spin = spinner('Deploying indexes...');\n const client = new ApiClient({ apiUrl, token });\n const result = await client.put<{ message: string }>(\n `/databases/${projectId}/index-rules`,\n { indexRules },\n );\n\n spin.succeed('Indexes deployed');\n\n if (isJsonMode()) {\n json(result);\n } else {\n success(result.message ?? 'Indexes synced successfully');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to deploy indexes');\n process.exitCode = 1;\n }\n });\n}\n\nfunction convertIndexFormat(\n indexes: Record<string, IndexRuleEntry[]>,\n): Record<string, RemoteIndexEntry[]> {\n const result: Record<string, RemoteIndexEntry[]> = {};\n\n for (const [collection, entries] of Object.entries(indexes)) {\n result[collection] = entries.map((entry) => {\n const fields: Record<string, 'asc' | 'desc'> = {};\n for (const [field, direction] of Object.entries(entry.fields)) {\n fields[field] = direction === 1 ? 'asc' : 'desc';\n }\n return {\n fields,\n ...(entry.unique !== undefined && { unique: entry.unique }),\n ...(entry.sparse !== undefined && { sparse: entry.sparse }),\n ...(entry.ttlSeconds !== undefined && { ttlSeconds: entry.ttlSeconds }),\n };\n });\n }\n\n return result;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n saveConfig,\n saveIndexes,\n} from '../../lib/config';\nimport { requireAuth } from '../../lib/auth';\nimport { success, error, spinner, json, isJsonMode, info } from '../../lib/output';\nimport type { GlobalOptions, IndexRuleEntry, RemoteIndexEntry } from '../../lib/types';\n\nexport function createIndexesPullCommand(): Command {\n return new Command('pull')\n .description('Pull current indexes from remote to spacelr.indexes.json')\n .option('--project <id>', 'Project ID')\n .option('--config <path>', 'Config file path')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig(opts.config);\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n\n const spin = spinner('Pulling indexes...');\n const client = new ApiClient({ apiUrl, token });\n const result = await client.get<{\n indexRules: Record<string, RemoteIndexEntry[]>;\n }>(`/databases/${projectId}/index-rules`);\n\n // Convert from API format (asc/desc) to config format (1/-1)\n const indexes = convertFromRemoteFormat(result.indexRules);\n\n saveIndexes(indexes, opts.config);\n\n if (opts.project && opts.project !== config?.projectId) {\n saveConfig({ ...config, projectId: opts.project }, opts.config);\n }\n\n spin.succeed('Indexes pulled');\n\n const collectionCount = Object.keys(indexes).length;\n const totalIndexes = Object.values(indexes).reduce(\n (sum, arr) => sum + arr.length,\n 0,\n );\n\n if (isJsonMode()) {\n json(indexes);\n } else {\n success(\n `Pulled ${totalIndexes} index(es) from ${collectionCount} collection(s)`,\n );\n info('Indexes file updated');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to pull indexes');\n process.exitCode = 1;\n }\n });\n}\n\nfunction convertFromRemoteFormat(\n remoteIndexes: Record<string, RemoteIndexEntry[]>,\n): Record<string, IndexRuleEntry[]> {\n const result: Record<string, IndexRuleEntry[]> = {};\n\n for (const [collection, entries] of Object.entries(remoteIndexes)) {\n result[collection] = entries.map((entry) => {\n const fields: Record<string, 1 | -1> = {};\n for (const [field, direction] of Object.entries(entry.fields)) {\n fields[field] = direction === 'asc' ? 1 : -1;\n }\n return {\n fields,\n ...(entry.unique !== undefined && { unique: entry.unique }),\n ...(entry.sparse !== undefined && { sparse: entry.sparse }),\n ...(entry.ttlSeconds !== undefined && {\n ttlSeconds: entry.ttlSeconds,\n }),\n };\n });\n }\n\n return result;\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n loadRules,\n} from '../../lib/config';\nimport { requireAuth } from '../../lib/auth';\nimport { success, error, info, spinner, json, isJsonMode, warn } from '../../lib/output';\nimport { promptConfirm } from '../../lib/prompt';\nimport type { GlobalOptions } from '../../lib/types';\n\nexport function createRulesDeployCommand(): Command {\n return new Command('deploy')\n .description('Deploy rules from spacelr.rules.json to remote')\n .option('--project <id>', 'Project ID')\n .option('--config <path>', 'Config file path')\n .option('--yes', 'Skip confirmation')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig(opts.config);\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n const rules = loadRules(opts.config);\n\n if (!rules || Object.keys(rules).length === 0) {\n warn('No rules found in spacelr.rules.json');\n return;\n }\n\n const ruleCount = Object.keys(rules).length;\n\n if (!opts.yes) {\n info(`Will deploy rules for ${ruleCount} collection(s)`);\n const confirmed = await promptConfirm('Proceed with deployment?');\n if (!confirmed) {\n info('Aborted');\n return;\n }\n }\n\n // Validate first\n const spin = spinner('Validating rules...');\n const client = new ApiClient({ apiUrl, token });\n\n await client.post<{ valid: boolean }>(\n `/databases/${projectId}/rules/validate`,\n { rules },\n );\n\n // Deploy\n spin.text = 'Deploying rules...';\n const result = await client.put<{ message: string }>(\n `/databases/${projectId}/rules`,\n { rules },\n );\n\n spin.succeed('Rules deployed');\n\n if (isJsonMode()) {\n json(result);\n } else {\n success(result.message ?? 'Rules deployed successfully');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to deploy rules');\n process.exitCode = 1;\n }\n });\n}\n","import { Command } from 'commander';\nimport { ApiClient } from '../../lib/api-client';\nimport {\n resolveApiUrl,\n resolveProjectId,\n loadConfig,\n saveConfig,\n saveRules,\n} from '../../lib/config';\nimport { requireAuth } from '../../lib/auth';\nimport { success, error, spinner, json, isJsonMode, info } from '../../lib/output';\nimport type { GlobalOptions } from '../../lib/types';\n\nexport function createRulesPullCommand(): Command {\n return new Command('pull')\n .description('Pull current rules from remote to spacelr.rules.json')\n .option('--project <id>', 'Project ID')\n .option('--config <path>', 'Config file path')\n .action(async (opts, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>();\n const config = loadConfig(opts.config);\n const apiUrl = resolveApiUrl(globalOpts.apiUrl, config);\n\n try {\n const token = requireAuth(globalOpts.token);\n const projectId = resolveProjectId(opts.project, config);\n\n const spin = spinner('Pulling rules...');\n const client = new ApiClient({ apiUrl, token });\n const result = await client.get<{ rules: Record<string, unknown> }>(\n `/databases/${projectId}/rules`,\n );\n\n const rules = result.rules;\n\n saveRules(rules, opts.config);\n\n if (opts.project && opts.project !== config?.projectId) {\n saveConfig({ ...config, projectId: opts.project }, opts.config);\n }\n\n spin.succeed('Rules pulled');\n\n const ruleCount = Object.keys(rules).length;\n\n if (isJsonMode()) {\n json(rules);\n } else {\n success(`Pulled rules for ${ruleCount} collection(s)`);\n info('Rules file updated');\n }\n } catch (err) {\n error(err instanceof Error ? err.message : 'Failed to pull rules');\n process.exitCode = 1;\n }\n });\n}\n"],"mappings":"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","names":["import_commander","pc","ora","crypto","fs","path","open","resolve","import_commander","import_commander","path","import_commander","import_commander","resolve","fs","path","import_commander","path","import_commander","fs","path","resolve","archiver","resolve","import_commander","import_commander","import_commander","import_commander","import_commander"]}
|