@eide/foir-cli 0.3.2 → 0.4.0
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/cli.js +240 -33
- package/dist/lib/config-helpers.d.ts +12 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { config } from "dotenv";
|
|
5
|
-
import { resolve as
|
|
5
|
+
import { resolve as resolve7, dirname as dirname4 } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { createRequire } from "module";
|
|
8
8
|
import { Command } from "commander";
|
|
@@ -300,13 +300,13 @@ function withErrorHandler(optsFn, fn) {
|
|
|
300
300
|
// src/commands/login.ts
|
|
301
301
|
async function findAvailablePort(start, end) {
|
|
302
302
|
for (let port = start; port <= end; port++) {
|
|
303
|
-
const available = await new Promise((
|
|
303
|
+
const available = await new Promise((resolve8) => {
|
|
304
304
|
const server = http.createServer();
|
|
305
305
|
server.listen(port, () => {
|
|
306
306
|
server.close();
|
|
307
|
-
|
|
307
|
+
resolve8(true);
|
|
308
308
|
});
|
|
309
|
-
server.on("error", () =>
|
|
309
|
+
server.on("error", () => resolve8(false));
|
|
310
310
|
});
|
|
311
311
|
if (available) return port;
|
|
312
312
|
}
|
|
@@ -344,7 +344,7 @@ async function loginAction(globalOpts) {
|
|
|
344
344
|
const state = crypto.randomBytes(16).toString("hex");
|
|
345
345
|
const port = await findAvailablePort(9876, 9900);
|
|
346
346
|
const redirectUri = `http://localhost:${port}/callback`;
|
|
347
|
-
const authCode = await new Promise((
|
|
347
|
+
const authCode = await new Promise((resolve8, reject) => {
|
|
348
348
|
let timeoutId;
|
|
349
349
|
const server = http.createServer((req, res) => {
|
|
350
350
|
const url = new URL(req.url, `http://localhost:${port}`);
|
|
@@ -383,7 +383,7 @@ async function loginAction(globalOpts) {
|
|
|
383
383
|
);
|
|
384
384
|
server.closeAllConnections();
|
|
385
385
|
server.close();
|
|
386
|
-
|
|
386
|
+
resolve8(code);
|
|
387
387
|
}
|
|
388
388
|
});
|
|
389
389
|
server.listen(port);
|
|
@@ -1860,7 +1860,14 @@ function createConfigsMethods(client) {
|
|
|
1860
1860
|
configData
|
|
1861
1861
|
})
|
|
1862
1862
|
);
|
|
1863
|
-
|
|
1863
|
+
const config2 = resp.config ?? null;
|
|
1864
|
+
if (!config2) return null;
|
|
1865
|
+
return {
|
|
1866
|
+
...config2,
|
|
1867
|
+
summary: resp.summary ?? null,
|
|
1868
|
+
provisionedApiKeys: resp.provisionedApiKeys ?? [],
|
|
1869
|
+
webhookSecret: resp.webhookSecret ?? null
|
|
1870
|
+
};
|
|
1864
1871
|
},
|
|
1865
1872
|
async deleteConfig(id) {
|
|
1866
1873
|
const resp = await client.deleteConfig(
|
|
@@ -2905,12 +2912,9 @@ function registerSelectProjectCommand(program2, globalOpts) {
|
|
|
2905
2912
|
selectedProject = projects.find((p) => p.id === projectId);
|
|
2906
2913
|
}
|
|
2907
2914
|
console.log("\nProvisioning API key for CLI access...");
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
"x-project-id": selectedProject.id
|
|
2912
|
-
});
|
|
2913
|
-
const { apiKey, apiKeyId } = await provisionApiKey(projectClient);
|
|
2915
|
+
await client.identity.switchTenant(selectedProject.tenantId);
|
|
2916
|
+
await client.identity.switchProject(selectedProject.id);
|
|
2917
|
+
const { apiKey, apiKeyId } = await provisionApiKey(client);
|
|
2914
2918
|
await writeProjectContext(
|
|
2915
2919
|
{
|
|
2916
2920
|
id: selectedProject.id,
|
|
@@ -4229,7 +4233,7 @@ Edit the files, then run:
|
|
|
4229
4233
|
|
|
4230
4234
|
// src/commands/push.ts
|
|
4231
4235
|
import chalk6 from "chalk";
|
|
4232
|
-
import { existsSync as existsSync4 } from "fs";
|
|
4236
|
+
import { existsSync as existsSync4, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
4233
4237
|
import { resolve as resolve4 } from "path";
|
|
4234
4238
|
var CONFIG_FILE_NAMES = [
|
|
4235
4239
|
"foir.config.ts",
|
|
@@ -4244,8 +4248,25 @@ function discoverConfigFile() {
|
|
|
4244
4248
|
}
|
|
4245
4249
|
return null;
|
|
4246
4250
|
}
|
|
4251
|
+
function writeEnvVar(envPath, key, value) {
|
|
4252
|
+
let content = "";
|
|
4253
|
+
if (existsSync4(envPath)) {
|
|
4254
|
+
content = readFileSync(envPath, "utf-8");
|
|
4255
|
+
const regex = new RegExp(`^${key}=`, "m");
|
|
4256
|
+
if (regex.test(content)) {
|
|
4257
|
+
return false;
|
|
4258
|
+
}
|
|
4259
|
+
}
|
|
4260
|
+
if (content && !content.endsWith("\n")) {
|
|
4261
|
+
content += "\n";
|
|
4262
|
+
}
|
|
4263
|
+
content += `${key}=${value}
|
|
4264
|
+
`;
|
|
4265
|
+
writeFileSync2(envPath, content, "utf-8");
|
|
4266
|
+
return true;
|
|
4267
|
+
}
|
|
4247
4268
|
function registerPushCommand(program2, globalOpts) {
|
|
4248
|
-
program2.command("push").description("Push foir.config.ts to the platform").option("--config <path>", "Path to config file (default: auto-discover)").option("--force", "Force reinstall (delete and recreate)", false).action(
|
|
4269
|
+
program2.command("push").description("Push foir.config.ts to the platform").option("--config <path>", "Path to config file (default: auto-discover)").option("--force", "Force reinstall (delete and recreate)", false).option("--env <path>", "Path to .env file (default: .env)").action(
|
|
4249
4270
|
withErrorHandler(
|
|
4250
4271
|
globalOpts,
|
|
4251
4272
|
async (opts) => {
|
|
@@ -4282,18 +4303,203 @@ function registerPushCommand(program2, globalOpts) {
|
|
|
4282
4303
|
);
|
|
4283
4304
|
}
|
|
4284
4305
|
console.log();
|
|
4285
|
-
console.log(chalk6.green("Config applied successfully
|
|
4286
|
-
console.log();
|
|
4306
|
+
console.log(chalk6.green("\u2713 Config applied successfully"));
|
|
4287
4307
|
console.log(` Config ID: ${chalk6.cyan(result.id)}`);
|
|
4288
4308
|
console.log(` Config Key: ${chalk6.cyan(result.key)}`);
|
|
4309
|
+
const summary = result.summary;
|
|
4310
|
+
if (summary) {
|
|
4311
|
+
console.log();
|
|
4312
|
+
const lines = [];
|
|
4313
|
+
if (summary.modelsCreated || summary.modelsUpdated) {
|
|
4314
|
+
lines.push(
|
|
4315
|
+
` Models: ${summary.modelsCreated ?? 0} created, ${summary.modelsUpdated ?? 0} updated`
|
|
4316
|
+
);
|
|
4317
|
+
}
|
|
4318
|
+
if (summary.operationsCreated || summary.operationsUpdated) {
|
|
4319
|
+
lines.push(
|
|
4320
|
+
` Operations: ${summary.operationsCreated ?? 0} created, ${summary.operationsUpdated ?? 0} updated`
|
|
4321
|
+
);
|
|
4322
|
+
}
|
|
4323
|
+
if (summary.hooksCreated || summary.hooksUpdated) {
|
|
4324
|
+
lines.push(
|
|
4325
|
+
` Hooks: ${summary.hooksCreated ?? 0} created, ${summary.hooksUpdated ?? 0} updated`
|
|
4326
|
+
);
|
|
4327
|
+
}
|
|
4328
|
+
if (summary.segmentsCreated || summary.segmentsUpdated) {
|
|
4329
|
+
lines.push(
|
|
4330
|
+
` Segments: ${summary.segmentsCreated ?? 0} created, ${summary.segmentsUpdated ?? 0} updated`
|
|
4331
|
+
);
|
|
4332
|
+
}
|
|
4333
|
+
if (summary.schedulesCreated || summary.schedulesUpdated) {
|
|
4334
|
+
lines.push(
|
|
4335
|
+
` Schedules: ${summary.schedulesCreated ?? 0} created, ${summary.schedulesUpdated ?? 0} updated`
|
|
4336
|
+
);
|
|
4337
|
+
}
|
|
4338
|
+
if (summary.authProvidersCreated || summary.authProvidersUpdated) {
|
|
4339
|
+
lines.push(
|
|
4340
|
+
` Auth: ${summary.authProvidersCreated ?? 0} created, ${summary.authProvidersUpdated ?? 0} updated`
|
|
4341
|
+
);
|
|
4342
|
+
}
|
|
4343
|
+
if (summary.resourcesDeleted) {
|
|
4344
|
+
lines.push(
|
|
4345
|
+
` Cleaned up: ${summary.resourcesDeleted} orphaned resource(s)`
|
|
4346
|
+
);
|
|
4347
|
+
}
|
|
4348
|
+
if (lines.length > 0) {
|
|
4349
|
+
for (const line of lines) {
|
|
4350
|
+
console.log(line);
|
|
4351
|
+
}
|
|
4352
|
+
}
|
|
4353
|
+
}
|
|
4354
|
+
const envPath = resolve4(opts.env ?? ".env");
|
|
4355
|
+
const r = result;
|
|
4356
|
+
const provisionedKeys = r.provisionedApiKeys;
|
|
4357
|
+
const webhookSecret = r.webhookSecret;
|
|
4358
|
+
const envWrites = [];
|
|
4359
|
+
if (provisionedKeys && provisionedKeys.length > 0) {
|
|
4360
|
+
for (const pk of provisionedKeys) {
|
|
4361
|
+
envWrites.push({
|
|
4362
|
+
key: pk.envVar,
|
|
4363
|
+
value: pk.rawKey,
|
|
4364
|
+
label: `${pk.name} (${pk.keyType})`
|
|
4365
|
+
});
|
|
4366
|
+
}
|
|
4367
|
+
}
|
|
4368
|
+
if (webhookSecret) {
|
|
4369
|
+
envWrites.push({
|
|
4370
|
+
key: "FOIR_WEBHOOK_SECRET",
|
|
4371
|
+
value: webhookSecret,
|
|
4372
|
+
label: "Webhook signing secret"
|
|
4373
|
+
});
|
|
4374
|
+
}
|
|
4375
|
+
if (envWrites.length > 0) {
|
|
4376
|
+
console.log();
|
|
4377
|
+
for (const { key, value, label } of envWrites) {
|
|
4378
|
+
const written = writeEnvVar(envPath, key, value);
|
|
4379
|
+
if (written) {
|
|
4380
|
+
console.log(
|
|
4381
|
+
chalk6.green(`\u2713 ${label}`) + chalk6.dim(` \u2192 ${key} written to ${envPath}`)
|
|
4382
|
+
);
|
|
4383
|
+
} else {
|
|
4384
|
+
console.log(
|
|
4385
|
+
chalk6.dim(` ${label}: ${key} already exists in ${envPath}, skipped`)
|
|
4386
|
+
);
|
|
4387
|
+
}
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4289
4390
|
console.log();
|
|
4290
4391
|
}
|
|
4291
4392
|
)
|
|
4292
4393
|
);
|
|
4293
4394
|
}
|
|
4294
4395
|
|
|
4295
|
-
// src/commands/
|
|
4396
|
+
// src/commands/pull.ts
|
|
4296
4397
|
import chalk7 from "chalk";
|
|
4398
|
+
import { existsSync as existsSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
4399
|
+
import { resolve as resolve5 } from "path";
|
|
4400
|
+
import prettier from "prettier";
|
|
4401
|
+
var DEFAULT_OUTPUT = "foir.config.ts";
|
|
4402
|
+
function registerPullCommand(program2, globalOpts) {
|
|
4403
|
+
program2.command("pull").description("Export platform config to foir.config.ts").option("--key <configKey>", "Config key to export").option("--out <path>", `Output file (default: ${DEFAULT_OUTPUT})`).option("--force", "Overwrite existing file without prompting", false).action(
|
|
4404
|
+
withErrorHandler(
|
|
4405
|
+
globalOpts,
|
|
4406
|
+
async (opts) => {
|
|
4407
|
+
const client = await createPlatformClient(globalOpts());
|
|
4408
|
+
let configKey = opts.key;
|
|
4409
|
+
if (!configKey) {
|
|
4410
|
+
const { configs } = await client.configs.listConfigs({ limit: 50 });
|
|
4411
|
+
if (!configs || configs.length === 0) {
|
|
4412
|
+
throw new Error(
|
|
4413
|
+
"No configs found in this project. Push one first with `foir push`."
|
|
4414
|
+
);
|
|
4415
|
+
}
|
|
4416
|
+
if (configs.length === 1) {
|
|
4417
|
+
configKey = configs[0].key;
|
|
4418
|
+
} else {
|
|
4419
|
+
console.log("Available configs:");
|
|
4420
|
+
for (const c of configs) {
|
|
4421
|
+
console.log(` ${chalk7.cyan(c.key)} \u2014 ${c.name}`);
|
|
4422
|
+
}
|
|
4423
|
+
throw new Error(
|
|
4424
|
+
"Multiple configs found. Use --key <configKey> to specify which one to export."
|
|
4425
|
+
);
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
console.log(chalk7.dim(`Fetching config "${configKey}"...`));
|
|
4429
|
+
const config2 = await client.configs.getConfigByKey(configKey);
|
|
4430
|
+
if (!config2) {
|
|
4431
|
+
throw new Error(`Config "${configKey}" not found.`);
|
|
4432
|
+
}
|
|
4433
|
+
const configData = config2.config;
|
|
4434
|
+
if (!configData) {
|
|
4435
|
+
throw new Error(
|
|
4436
|
+
`Config "${configKey}" has no config data. It may have been created via the admin UI without a manifest.`
|
|
4437
|
+
);
|
|
4438
|
+
}
|
|
4439
|
+
const manifest = {
|
|
4440
|
+
key: config2.key,
|
|
4441
|
+
name: config2.name,
|
|
4442
|
+
...config2.configType && config2.configType !== "custom" ? { configType: config2.configType } : {},
|
|
4443
|
+
...config2.direction ? { direction: config2.direction } : {},
|
|
4444
|
+
...config2.description ? { description: config2.description } : {},
|
|
4445
|
+
...config2.connectionDomain ? { operationBaseUrl: config2.connectionDomain } : {},
|
|
4446
|
+
...configData
|
|
4447
|
+
};
|
|
4448
|
+
delete manifest.force;
|
|
4449
|
+
const jsonContent = JSON.stringify(manifest, null, 2);
|
|
4450
|
+
const tsContent = `/**
|
|
4451
|
+
* ${manifest.name} \u2014 Foir Config
|
|
4452
|
+
*
|
|
4453
|
+
* Exported from platform via \`foir pull\`.
|
|
4454
|
+
* Push changes back with \`foir push\`.
|
|
4455
|
+
*/
|
|
4456
|
+
|
|
4457
|
+
import { defineConfig } from '@eide/foir-cli/configs';
|
|
4458
|
+
|
|
4459
|
+
export default defineConfig(${jsonContent});
|
|
4460
|
+
`;
|
|
4461
|
+
let formatted;
|
|
4462
|
+
try {
|
|
4463
|
+
formatted = await prettier.format(tsContent, {
|
|
4464
|
+
parser: "typescript",
|
|
4465
|
+
singleQuote: true,
|
|
4466
|
+
trailingComma: "all"
|
|
4467
|
+
});
|
|
4468
|
+
} catch {
|
|
4469
|
+
formatted = tsContent;
|
|
4470
|
+
}
|
|
4471
|
+
const outPath = resolve5(opts.out ?? DEFAULT_OUTPUT);
|
|
4472
|
+
if (existsSync5(outPath) && !opts.force) {
|
|
4473
|
+
throw new Error(
|
|
4474
|
+
`${outPath} already exists. Use --force to overwrite.`
|
|
4475
|
+
);
|
|
4476
|
+
}
|
|
4477
|
+
writeFileSync3(outPath, formatted, "utf-8");
|
|
4478
|
+
console.log(chalk7.green(`\u2713 Exported to ${outPath}`));
|
|
4479
|
+
const models = configData.models ?? [];
|
|
4480
|
+
const operations = configData.operations ?? [];
|
|
4481
|
+
const hooks = configData.hooks ?? [];
|
|
4482
|
+
const segments = configData.segments ?? [];
|
|
4483
|
+
const schedules = configData.schedules ?? [];
|
|
4484
|
+
const authProviders = configData.authProviders ?? [];
|
|
4485
|
+
const parts = [];
|
|
4486
|
+
if (models.length > 0) parts.push(`${models.length} model(s)`);
|
|
4487
|
+
if (operations.length > 0) parts.push(`${operations.length} operation(s)`);
|
|
4488
|
+
if (hooks.length > 0) parts.push(`${hooks.length} hook(s)`);
|
|
4489
|
+
if (segments.length > 0) parts.push(`${segments.length} segment(s)`);
|
|
4490
|
+
if (schedules.length > 0) parts.push(`${schedules.length} schedule(s)`);
|
|
4491
|
+
if (authProviders.length > 0) parts.push(`${authProviders.length} auth provider(s)`);
|
|
4492
|
+
if (configData.customerProfileSchema) parts.push("customer profile schema");
|
|
4493
|
+
if (parts.length > 0) {
|
|
4494
|
+
console.log(chalk7.dim(` Contains: ${parts.join(", ")}`));
|
|
4495
|
+
}
|
|
4496
|
+
}
|
|
4497
|
+
)
|
|
4498
|
+
);
|
|
4499
|
+
}
|
|
4500
|
+
|
|
4501
|
+
// src/commands/remove.ts
|
|
4502
|
+
import chalk8 from "chalk";
|
|
4297
4503
|
import inquirer5 from "inquirer";
|
|
4298
4504
|
function registerRemoveCommand(program2, globalOpts) {
|
|
4299
4505
|
program2.command("remove <key>").description("Remove a config and all its provisioned resources").option("--force", "Skip confirmation prompt", false).action(
|
|
@@ -4315,13 +4521,13 @@ function registerRemoveCommand(program2, globalOpts) {
|
|
|
4315
4521
|
}
|
|
4316
4522
|
]);
|
|
4317
4523
|
if (!confirmed) {
|
|
4318
|
-
console.log(
|
|
4524
|
+
console.log(chalk8.dim("Cancelled."));
|
|
4319
4525
|
return;
|
|
4320
4526
|
}
|
|
4321
4527
|
}
|
|
4322
4528
|
await client.configs.deleteConfig(config2.id);
|
|
4323
4529
|
console.log(
|
|
4324
|
-
|
|
4530
|
+
chalk8.green(`Removed config "${config2.name}" (${config2.key}).`)
|
|
4325
4531
|
);
|
|
4326
4532
|
}
|
|
4327
4533
|
)
|
|
@@ -4329,7 +4535,7 @@ function registerRemoveCommand(program2, globalOpts) {
|
|
|
4329
4535
|
}
|
|
4330
4536
|
|
|
4331
4537
|
// src/commands/profiles.ts
|
|
4332
|
-
import
|
|
4538
|
+
import chalk9 from "chalk";
|
|
4333
4539
|
function registerProfilesCommand(program2, globalOpts) {
|
|
4334
4540
|
const profiles = program2.command("profiles").description("Manage named project profiles");
|
|
4335
4541
|
profiles.command("list").description("List all saved project profiles").action(
|
|
@@ -4489,7 +4695,7 @@ function registerProfilesCommand(program2, globalOpts) {
|
|
|
4489
4695
|
if (opts.json || opts.jsonl) {
|
|
4490
4696
|
formatOutput({ deleted: name }, opts);
|
|
4491
4697
|
} else {
|
|
4492
|
-
console.log(
|
|
4698
|
+
console.log(chalk9.green(`Deleted profile "${name}".`));
|
|
4493
4699
|
}
|
|
4494
4700
|
}
|
|
4495
4701
|
)
|
|
@@ -4498,8 +4704,8 @@ function registerProfilesCommand(program2, globalOpts) {
|
|
|
4498
4704
|
|
|
4499
4705
|
// src/commands/register-commands.ts
|
|
4500
4706
|
import { readdirSync } from "fs";
|
|
4501
|
-
import { resolve as
|
|
4502
|
-
import
|
|
4707
|
+
import { resolve as resolve6 } from "path";
|
|
4708
|
+
import chalk10 from "chalk";
|
|
4503
4709
|
|
|
4504
4710
|
// src/command-registry/command-map.ts
|
|
4505
4711
|
var COMMANDS = [
|
|
@@ -6297,7 +6503,7 @@ function buildDispatchTable() {
|
|
|
6297
6503
|
unregisterConfig: async (v, c) => await c.configs.deleteConfig(str(v.id)),
|
|
6298
6504
|
triggerConfigSync: async (v, _c) => {
|
|
6299
6505
|
console.log(
|
|
6300
|
-
|
|
6506
|
+
chalk10.yellow(
|
|
6301
6507
|
`Config sync trigger for ${str(v.configId)} is not yet available via ConnectRPC.`
|
|
6302
6508
|
)
|
|
6303
6509
|
);
|
|
@@ -6467,11 +6673,11 @@ function registerDynamicCommands(program2, globalOpts) {
|
|
|
6467
6673
|
variables.limit = flags.limit;
|
|
6468
6674
|
}
|
|
6469
6675
|
if (flags.dir && entry.acceptsInput) {
|
|
6470
|
-
const dirPath =
|
|
6676
|
+
const dirPath = resolve6(String(flags.dir));
|
|
6471
6677
|
const files = readdirSync(dirPath).filter((f) => /\.(json|ts|js|mjs)$/.test(f)).sort();
|
|
6472
6678
|
if (files.length === 0) {
|
|
6473
6679
|
console.error(
|
|
6474
|
-
|
|
6680
|
+
chalk10.yellow(`No .json/.ts/.js files found in ${dirPath}`)
|
|
6475
6681
|
);
|
|
6476
6682
|
return;
|
|
6477
6683
|
}
|
|
@@ -6479,7 +6685,7 @@ function registerDynamicCommands(program2, globalOpts) {
|
|
|
6479
6685
|
let updated = 0;
|
|
6480
6686
|
let failed = 0;
|
|
6481
6687
|
for (const file of files) {
|
|
6482
|
-
const filePath =
|
|
6688
|
+
const filePath = resolve6(dirPath, file);
|
|
6483
6689
|
const fileData = await parseInputData({ file: filePath });
|
|
6484
6690
|
const argName = entry.inputArgName ?? "input";
|
|
6485
6691
|
const fileVars = { ...variables, [argName]: fileData };
|
|
@@ -6514,19 +6720,19 @@ function registerDynamicCommands(program2, globalOpts) {
|
|
|
6514
6720
|
} catch (updateErr) {
|
|
6515
6721
|
failed++;
|
|
6516
6722
|
const msg2 = updateErr instanceof Error ? updateErr.message : String(updateErr);
|
|
6517
|
-
console.error(
|
|
6723
|
+
console.error(chalk10.red(`\u2717 ${label}:`), msg2);
|
|
6518
6724
|
continue;
|
|
6519
6725
|
}
|
|
6520
6726
|
}
|
|
6521
6727
|
failed++;
|
|
6522
6728
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6523
|
-
console.error(
|
|
6729
|
+
console.error(chalk10.red(`\u2717 ${label}:`), msg);
|
|
6524
6730
|
}
|
|
6525
6731
|
}
|
|
6526
6732
|
if (!(opts.json || opts.jsonl || opts.quiet)) {
|
|
6527
6733
|
console.log("");
|
|
6528
6734
|
console.log(
|
|
6529
|
-
|
|
6735
|
+
chalk10.bold(
|
|
6530
6736
|
`Done: ${created} created${updated ? `, ${updated} updated` : ""}${failed ? `, ${failed} failed` : ""}`
|
|
6531
6737
|
)
|
|
6532
6738
|
);
|
|
@@ -6687,7 +6893,7 @@ function registerDynamicCommands(program2, globalOpts) {
|
|
|
6687
6893
|
}
|
|
6688
6894
|
} else if (!(opts.json || opts.jsonl || opts.quiet)) {
|
|
6689
6895
|
console.error(
|
|
6690
|
-
|
|
6896
|
+
chalk10.yellow(
|
|
6691
6897
|
"Could not auto-publish: no version found in response"
|
|
6692
6898
|
)
|
|
6693
6899
|
);
|
|
@@ -6702,7 +6908,7 @@ function registerDynamicCommands(program2, globalOpts) {
|
|
|
6702
6908
|
// src/cli.ts
|
|
6703
6909
|
var __filename = fileURLToPath(import.meta.url);
|
|
6704
6910
|
var __dirname = dirname4(__filename);
|
|
6705
|
-
config({ path:
|
|
6911
|
+
config({ path: resolve7(__dirname, "../.env.local") });
|
|
6706
6912
|
var require2 = createRequire(import.meta.url);
|
|
6707
6913
|
var { version } = require2("../package.json");
|
|
6708
6914
|
var program = new Command();
|
|
@@ -6725,6 +6931,7 @@ registerProfilesCommand(program, getGlobalOpts);
|
|
|
6725
6931
|
registerMediaCommands(program, getGlobalOpts);
|
|
6726
6932
|
registerSearchCommands(program, getGlobalOpts);
|
|
6727
6933
|
registerPushCommand(program, getGlobalOpts);
|
|
6934
|
+
registerPullCommand(program, getGlobalOpts);
|
|
6728
6935
|
registerRemoveCommand(program, getGlobalOpts);
|
|
6729
6936
|
registerCreateConfigCommand(program, getGlobalOpts);
|
|
6730
6937
|
registerInitCommands(program, getGlobalOpts);
|
|
@@ -98,6 +98,16 @@ interface ApplyConfigHookInput {
|
|
|
98
98
|
expression?: Record<string, unknown>;
|
|
99
99
|
hooks?: ApplyConfigHookInput[];
|
|
100
100
|
}
|
|
101
|
+
interface ApplyConfigApiKeyInput {
|
|
102
|
+
/** Name for this API key (e.g. "Tilly iOS", "Tilly BFF"). */
|
|
103
|
+
name: string;
|
|
104
|
+
/** Key type: 'public' for client apps, 'secret' for BFF/server. */
|
|
105
|
+
keyType: 'public' | 'secret';
|
|
106
|
+
/** Environment variable name to write the key to in .env (e.g. "FOIR_PUBLIC_KEY"). */
|
|
107
|
+
envVar: string;
|
|
108
|
+
/** Optional scopes to restrict the key. */
|
|
109
|
+
scopes?: Record<string, unknown>;
|
|
110
|
+
}
|
|
101
111
|
interface ApplyConfigInput {
|
|
102
112
|
key: string;
|
|
103
113
|
name: string;
|
|
@@ -110,6 +120,7 @@ interface ApplyConfigInput {
|
|
|
110
120
|
hooks?: ApplyConfigHookInput[];
|
|
111
121
|
authProviders?: ApplyConfigAuthProviderInput[];
|
|
112
122
|
placements?: ApplyConfigPlacementInput[];
|
|
123
|
+
apiKeys?: ApplyConfigApiKeyInput[];
|
|
113
124
|
[key: string]: unknown;
|
|
114
125
|
}
|
|
115
126
|
/** Define a complete config manifest. */
|
|
@@ -133,4 +144,4 @@ declare function defineHook(hook: ApplyConfigHookInput): ApplyConfigHookInput;
|
|
|
133
144
|
/** Define an editor placement (sidebar or main-editor tab). */
|
|
134
145
|
declare function definePlacement(placement: ApplyConfigPlacementInput): ApplyConfigPlacementInput;
|
|
135
146
|
|
|
136
|
-
export { type ApplyConfigAuthProviderInput, type ApplyConfigHookInput, type ApplyConfigInput, type ApplyConfigModelInput, type ApplyConfigOperationInput, type ApplyConfigPlacementInput, type ApplyConfigScheduleInput, type ApplyConfigSegmentInput, type FieldDefinitionInput, defineAuthProvider, defineConfig, defineExtension, defineField, defineHook, defineModel, defineOperation, definePlacement, defineSchedule, defineSegment };
|
|
147
|
+
export { type ApplyConfigApiKeyInput, type ApplyConfigAuthProviderInput, type ApplyConfigHookInput, type ApplyConfigInput, type ApplyConfigModelInput, type ApplyConfigOperationInput, type ApplyConfigPlacementInput, type ApplyConfigScheduleInput, type ApplyConfigSegmentInput, type FieldDefinitionInput, defineAuthProvider, defineConfig, defineExtension, defineField, defineHook, defineModel, defineOperation, definePlacement, defineSchedule, defineSegment };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eide/foir-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Universal platform CLI for Foir platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@bufbuild/protobuf": "^2.0.0",
|
|
50
50
|
"@connectrpc/connect": "^2.0.0",
|
|
51
51
|
"@connectrpc/connect-node": "^2.0.0",
|
|
52
|
-
"@eide/foir-proto-ts": "^0.1
|
|
52
|
+
"@eide/foir-proto-ts": "^0.3.1",
|
|
53
53
|
"chalk": "^5.3.0",
|
|
54
54
|
"commander": "^12.1.0",
|
|
55
55
|
"dotenv": "^16.4.5",
|