@eide/foir-cli 0.1.45 → 0.1.47
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 +316 -294
- package/dist/{generated-xEC9Cfzw.d.ts → lib/config-helpers.d.ts} +97 -77
- package/dist/lib/config-helpers.js +41 -0
- package/dist/schema.graphql +96 -63
- package/package.json +5 -13
- package/dist/lib/extension-helpers.d.ts +0 -100
- package/dist/lib/extension-helpers.js +0 -23
- package/dist/lib/hook-helpers.d.ts +0 -108
- package/dist/lib/hook-helpers.js +0 -15
- package/dist/lib/seed-helpers.d.ts +0 -124
- package/dist/lib/seed-helpers.js +0 -23
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 resolve6, dirname as dirname5 } from "path";
|
|
6
6
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7
7
|
import { createRequire } from "module";
|
|
8
8
|
import { Command } from "commander";
|
|
@@ -343,13 +343,13 @@ function withErrorHandler(optsFn, fn) {
|
|
|
343
343
|
// src/commands/login.ts
|
|
344
344
|
async function findAvailablePort(start, end) {
|
|
345
345
|
for (let port = start; port <= end; port++) {
|
|
346
|
-
const available = await new Promise((
|
|
346
|
+
const available = await new Promise((resolve7) => {
|
|
347
347
|
const server = http.createServer();
|
|
348
348
|
server.listen(port, () => {
|
|
349
349
|
server.close();
|
|
350
|
-
|
|
350
|
+
resolve7(true);
|
|
351
351
|
});
|
|
352
|
-
server.on("error", () =>
|
|
352
|
+
server.on("error", () => resolve7(false));
|
|
353
353
|
});
|
|
354
354
|
if (available) return port;
|
|
355
355
|
}
|
|
@@ -387,7 +387,7 @@ async function loginAction(globalOpts) {
|
|
|
387
387
|
const state = crypto.randomBytes(16).toString("hex");
|
|
388
388
|
const port = await findAvailablePort(9876, 9900);
|
|
389
389
|
const redirectUri = `http://localhost:${port}/callback`;
|
|
390
|
-
const authCode = await new Promise((
|
|
390
|
+
const authCode = await new Promise((resolve7, reject) => {
|
|
391
391
|
const server = http.createServer((req, res) => {
|
|
392
392
|
const url = new URL(req.url, `http://localhost:${port}`);
|
|
393
393
|
if (url.pathname === "/callback") {
|
|
@@ -420,7 +420,7 @@ async function loginAction(globalOpts) {
|
|
|
420
420
|
`<html><head><meta http-equiv="refresh" content="2;url=${mainUrl}"></head><body style="font-family:system-ui;text-align:center;padding:50px"><h1>Authentication successful!</h1><p>You can close this window.</p></body></html>`
|
|
421
421
|
);
|
|
422
422
|
server.close();
|
|
423
|
-
|
|
423
|
+
resolve7(code);
|
|
424
424
|
}
|
|
425
425
|
});
|
|
426
426
|
server.listen(port);
|
|
@@ -497,7 +497,7 @@ var CLI_API_KEY_SCOPES = [
|
|
|
497
497
|
"records:publish",
|
|
498
498
|
"files:read",
|
|
499
499
|
"files:write",
|
|
500
|
-
"
|
|
500
|
+
"configs:read",
|
|
501
501
|
"operations:read",
|
|
502
502
|
"operations:execute"
|
|
503
503
|
];
|
|
@@ -921,7 +921,7 @@ function registerMediaCommands(program2, globalOpts) {
|
|
|
921
921
|
);
|
|
922
922
|
}
|
|
923
923
|
|
|
924
|
-
// src/commands/create-
|
|
924
|
+
// src/commands/create-config.ts
|
|
925
925
|
import chalk4 from "chalk";
|
|
926
926
|
import inquirer2 from "inquirer";
|
|
927
927
|
|
|
@@ -977,14 +977,14 @@ function getManagerInfo(manager) {
|
|
|
977
977
|
}
|
|
978
978
|
|
|
979
979
|
// src/scaffold/scaffold.ts
|
|
980
|
-
async function scaffold(projectName,
|
|
980
|
+
async function scaffold(projectName, configType, apiUrl) {
|
|
981
981
|
const projectDir = path2.resolve(process.cwd(), projectName);
|
|
982
982
|
if (fs4.existsSync(projectDir)) {
|
|
983
983
|
throw new Error(
|
|
984
984
|
`Directory "${projectName}" already exists. Choose a different name or remove the existing directory.`
|
|
985
985
|
);
|
|
986
986
|
}
|
|
987
|
-
const files = getFiles(projectName,
|
|
987
|
+
const files = getFiles(projectName, configType, apiUrl);
|
|
988
988
|
for (const [filePath, content] of Object.entries(files)) {
|
|
989
989
|
const fullPath = path2.join(projectDir, filePath);
|
|
990
990
|
const dir = path2.dirname(fullPath);
|
|
@@ -1009,11 +1009,12 @@ async function scaffold(projectName, extensionType, apiUrl) {
|
|
|
1009
1009
|
console.log(` ${pm.name === "npm" ? "npm run" : pm.name} dev`);
|
|
1010
1010
|
console.log();
|
|
1011
1011
|
}
|
|
1012
|
-
function getFiles(projectName,
|
|
1012
|
+
function getFiles(projectName, configType, apiUrl) {
|
|
1013
1013
|
return {
|
|
1014
1014
|
// Root
|
|
1015
1015
|
"package.json": getRootPackageJson(projectName),
|
|
1016
|
-
|
|
1016
|
+
// Config manifest
|
|
1017
|
+
"foir.config.ts": getFoirConfig(projectName, configType),
|
|
1017
1018
|
// UI (Vite SPA)
|
|
1018
1019
|
"ui/package.json": getUiPackageJson(projectName),
|
|
1019
1020
|
"ui/tsconfig.json": getUiTsconfig(),
|
|
@@ -1022,7 +1023,7 @@ function getFiles(projectName, extensionType, apiUrl) {
|
|
|
1022
1023
|
"ui/.env.example": getUiEnvExample(apiUrl),
|
|
1023
1024
|
"ui/.gitignore": getUiGitignore(),
|
|
1024
1025
|
"ui/src/main.tsx": getUiMain(),
|
|
1025
|
-
"ui/src/App.tsx": getUiApp(
|
|
1026
|
+
"ui/src/App.tsx": getUiApp(configType),
|
|
1026
1027
|
"ui/src/index.css": getUiCss(),
|
|
1027
1028
|
"ui/src/vite-env.d.ts": '/// <reference types="vite/client" />\n',
|
|
1028
1029
|
// API (Hono)
|
|
@@ -1032,8 +1033,7 @@ function getFiles(projectName, extensionType, apiUrl) {
|
|
|
1032
1033
|
"api/.gitignore": "node_modules\ndist\n.env\n.env.local\n",
|
|
1033
1034
|
"api/src/index.ts": getApiIndex(),
|
|
1034
1035
|
"api/src/routes/webhooks.ts": getApiWebhooks(),
|
|
1035
|
-
"api/src/routes/health.ts": getApiHealth()
|
|
1036
|
-
"api/src/lib/platform.ts": getApiPlatform()
|
|
1036
|
+
"api/src/routes/health.ts": getApiHealth()
|
|
1037
1037
|
};
|
|
1038
1038
|
}
|
|
1039
1039
|
function getRootPackageJson(name) {
|
|
@@ -1046,20 +1046,31 @@ function getRootPackageJson(name) {
|
|
|
1046
1046
|
build: "pnpm --filter ./ui build && pnpm --filter ./api build"
|
|
1047
1047
|
},
|
|
1048
1048
|
devDependencies: {
|
|
1049
|
-
concurrently: "^9.0.0"
|
|
1049
|
+
concurrently: "^9.0.0",
|
|
1050
|
+
"@eide/foir-cli": "^0.1.0"
|
|
1050
1051
|
}
|
|
1051
1052
|
};
|
|
1052
1053
|
return JSON.stringify(pkg, null, 2) + "\n";
|
|
1053
1054
|
}
|
|
1054
|
-
function
|
|
1055
|
-
const
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1055
|
+
function getFoirConfig(name, configType) {
|
|
1056
|
+
const displayName = name.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
1057
|
+
return `import { defineConfig } from '@eide/foir-cli/configs';
|
|
1058
|
+
|
|
1059
|
+
export default defineConfig({
|
|
1060
|
+
key: '${name}',
|
|
1061
|
+
name: '${displayName}',
|
|
1062
|
+
configType: '${configType}',
|
|
1063
|
+
|
|
1064
|
+
// Uncomment and configure as needed:
|
|
1065
|
+
// models: [],
|
|
1066
|
+
// operations: [],
|
|
1067
|
+
// schedules: [],
|
|
1068
|
+
// hooks: [],
|
|
1069
|
+
// segments: [],
|
|
1070
|
+
// authProviders: [],
|
|
1071
|
+
// placements: [],
|
|
1072
|
+
});
|
|
1073
|
+
`;
|
|
1063
1074
|
}
|
|
1064
1075
|
function getUiPackageJson(name) {
|
|
1065
1076
|
const pkg = {
|
|
@@ -1073,7 +1084,7 @@ function getUiPackageJson(name) {
|
|
|
1073
1084
|
preview: "vite preview"
|
|
1074
1085
|
},
|
|
1075
1086
|
dependencies: {
|
|
1076
|
-
"@eide/
|
|
1087
|
+
"@eide/foir-editor-sdk": "^0.1.0",
|
|
1077
1088
|
react: "^19.0.0",
|
|
1078
1089
|
"react-dom": "^19.0.0"
|
|
1079
1090
|
},
|
|
@@ -1170,13 +1181,13 @@ dist
|
|
|
1170
1181
|
function getUiMain() {
|
|
1171
1182
|
return `import { StrictMode } from 'react';
|
|
1172
1183
|
import { createRoot } from 'react-dom/client';
|
|
1173
|
-
import {
|
|
1184
|
+
import { EditorProvider, useEditor } from '@eide/foir-editor-sdk';
|
|
1174
1185
|
import { useEffect } from 'react';
|
|
1175
1186
|
import { App } from './App';
|
|
1176
1187
|
import './index.css';
|
|
1177
1188
|
|
|
1178
1189
|
function ThemeSync({ children }: { children: React.ReactNode }) {
|
|
1179
|
-
const { theme } =
|
|
1190
|
+
const { theme } = useEditor();
|
|
1180
1191
|
|
|
1181
1192
|
useEffect(() => {
|
|
1182
1193
|
const root = document.documentElement;
|
|
@@ -1189,17 +1200,17 @@ function ThemeSync({ children }: { children: React.ReactNode }) {
|
|
|
1189
1200
|
|
|
1190
1201
|
createRoot(document.getElementById('root')!).render(
|
|
1191
1202
|
<StrictMode>
|
|
1192
|
-
<
|
|
1203
|
+
<EditorProvider>
|
|
1193
1204
|
<ThemeSync>
|
|
1194
1205
|
<App />
|
|
1195
1206
|
</ThemeSync>
|
|
1196
|
-
</
|
|
1207
|
+
</EditorProvider>
|
|
1197
1208
|
</StrictMode>
|
|
1198
1209
|
);
|
|
1199
1210
|
`;
|
|
1200
1211
|
}
|
|
1201
|
-
function getUiApp(
|
|
1202
|
-
switch (
|
|
1212
|
+
function getUiApp(configType) {
|
|
1213
|
+
switch (configType) {
|
|
1203
1214
|
case "custom-editor":
|
|
1204
1215
|
return getCustomEditorApp();
|
|
1205
1216
|
case "widget":
|
|
@@ -1209,10 +1220,10 @@ function getUiApp(extensionType) {
|
|
|
1209
1220
|
}
|
|
1210
1221
|
}
|
|
1211
1222
|
function getCustomEditorApp() {
|
|
1212
|
-
return `import {
|
|
1223
|
+
return `import { useEditor, useAutoResize } from '@eide/foir-editor-sdk';
|
|
1213
1224
|
|
|
1214
1225
|
export function App() {
|
|
1215
|
-
const { isReady, init, updateField, setDirty } =
|
|
1226
|
+
const { isReady, init, updateField, setDirty } = useEditor();
|
|
1216
1227
|
const containerRef = useAutoResize({ minHeight: 600 });
|
|
1217
1228
|
|
|
1218
1229
|
if (!isReady) return null;
|
|
@@ -1220,7 +1231,7 @@ export function App() {
|
|
|
1220
1231
|
return (
|
|
1221
1232
|
<div ref={containerRef} className="p-6 space-y-4">
|
|
1222
1233
|
<h1 className="text-lg font-semibold">
|
|
1223
|
-
Editing: {init?.
|
|
1234
|
+
Editing: {init?.modelKey}
|
|
1224
1235
|
</h1>
|
|
1225
1236
|
<p className="text-sm text-gray-500">
|
|
1226
1237
|
Record: {init?.recordId}
|
|
@@ -1232,10 +1243,10 @@ export function App() {
|
|
|
1232
1243
|
`;
|
|
1233
1244
|
}
|
|
1234
1245
|
function getWidgetApp() {
|
|
1235
|
-
return `import {
|
|
1246
|
+
return `import { useEditor, useAutoResize } from '@eide/foir-editor-sdk';
|
|
1236
1247
|
|
|
1237
1248
|
export function App() {
|
|
1238
|
-
const { isReady, init, client } =
|
|
1249
|
+
const { isReady, init, client } = useEditor();
|
|
1239
1250
|
const containerRef = useAutoResize({ minHeight: 300 });
|
|
1240
1251
|
|
|
1241
1252
|
if (!isReady) return null;
|
|
@@ -1244,7 +1255,7 @@ export function App() {
|
|
|
1244
1255
|
<div ref={containerRef} className="p-6 space-y-4">
|
|
1245
1256
|
<h2 className="text-lg font-semibold">Dashboard Widget</h2>
|
|
1246
1257
|
<p className="text-sm text-gray-500">
|
|
1247
|
-
Connected to: {init?.
|
|
1258
|
+
Connected to: {init?.modelKey}
|
|
1248
1259
|
</p>
|
|
1249
1260
|
{/* Add your widget content here */}
|
|
1250
1261
|
</div>
|
|
@@ -1253,19 +1264,19 @@ export function App() {
|
|
|
1253
1264
|
`;
|
|
1254
1265
|
}
|
|
1255
1266
|
function getWorkflowApp() {
|
|
1256
|
-
return `import {
|
|
1267
|
+
return `import { useEditor, useAutoResize } from '@eide/foir-editor-sdk';
|
|
1257
1268
|
|
|
1258
1269
|
export function App() {
|
|
1259
|
-
const { isReady, init, client, requestSave } =
|
|
1270
|
+
const { isReady, init, client, requestSave } = useEditor();
|
|
1260
1271
|
const containerRef = useAutoResize({ minHeight: 400 });
|
|
1261
1272
|
|
|
1262
1273
|
if (!isReady) return null;
|
|
1263
1274
|
|
|
1264
1275
|
return (
|
|
1265
1276
|
<div ref={containerRef} className="p-6 space-y-4">
|
|
1266
|
-
<h1 className="text-lg font-semibold">Workflow
|
|
1277
|
+
<h1 className="text-lg font-semibold">Workflow Config</h1>
|
|
1267
1278
|
<p className="text-sm text-gray-500">
|
|
1268
|
-
Processing: {init?.
|
|
1279
|
+
Processing: {init?.modelKey} / {init?.recordId}
|
|
1269
1280
|
</p>
|
|
1270
1281
|
{/* Add your workflow steps here */}
|
|
1271
1282
|
</div>
|
|
@@ -1305,7 +1316,7 @@ function getApiPackageJson(name) {
|
|
|
1305
1316
|
start: "node dist/index.js"
|
|
1306
1317
|
},
|
|
1307
1318
|
dependencies: {
|
|
1308
|
-
"@eide/
|
|
1319
|
+
"@eide/foir-editor-sdk": "^0.1.0",
|
|
1309
1320
|
hono: "^4.0.0",
|
|
1310
1321
|
"@hono/node-server": "^1.0.0"
|
|
1311
1322
|
},
|
|
@@ -1341,8 +1352,8 @@ function getApiEnvExample(apiUrl) {
|
|
|
1341
1352
|
PLATFORM_BASE_URL=${baseUrl}
|
|
1342
1353
|
PLATFORM_API_KEY=sk_your_api_key_here
|
|
1343
1354
|
|
|
1344
|
-
#
|
|
1345
|
-
|
|
1355
|
+
# Config
|
|
1356
|
+
CONFIG_KEY=${"{your-config-key}"}
|
|
1346
1357
|
WEBHOOK_SECRET=your_webhook_secret_here
|
|
1347
1358
|
|
|
1348
1359
|
# Server
|
|
@@ -1363,25 +1374,25 @@ app.route('/', health);
|
|
|
1363
1374
|
|
|
1364
1375
|
const port = parseInt(process.env.PORT || '3002', 10);
|
|
1365
1376
|
|
|
1366
|
-
console.log(\`
|
|
1377
|
+
console.log(\`Config API running on http://localhost:\${port}\`);
|
|
1367
1378
|
|
|
1368
1379
|
serve({ fetch: app.fetch, port });
|
|
1369
1380
|
`;
|
|
1370
1381
|
}
|
|
1371
1382
|
function getApiWebhooks() {
|
|
1372
1383
|
return `import { Hono } from 'hono';
|
|
1373
|
-
import { verifyWebhookSignature } from '@eide/
|
|
1384
|
+
import { verifyWebhookSignature } from '@eide/foir-editor-sdk/server';
|
|
1374
1385
|
|
|
1375
1386
|
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET || '';
|
|
1376
1387
|
|
|
1377
1388
|
export const webhooks = new Hono();
|
|
1378
1389
|
|
|
1379
1390
|
/**
|
|
1380
|
-
* Receive
|
|
1391
|
+
* Receive record lifecycle events from the platform.
|
|
1381
1392
|
*/
|
|
1382
|
-
webhooks.post('/
|
|
1393
|
+
webhooks.post('/record-changed', async (c) => {
|
|
1383
1394
|
const body = await c.req.text();
|
|
1384
|
-
const signature = c.req.header('x-
|
|
1395
|
+
const signature = c.req.header('x-foir-signature') ?? '';
|
|
1385
1396
|
|
|
1386
1397
|
const valid = await verifyWebhookSignature(body, signature, WEBHOOK_SECRET);
|
|
1387
1398
|
if (!valid) {
|
|
@@ -1389,7 +1400,7 @@ webhooks.post('/entity-changed', async (c) => {
|
|
|
1389
1400
|
}
|
|
1390
1401
|
|
|
1391
1402
|
const payload = JSON.parse(body);
|
|
1392
|
-
console.log('[Webhook]
|
|
1403
|
+
console.log('[Webhook] Record changed:', payload.event, payload.recordId);
|
|
1393
1404
|
|
|
1394
1405
|
// TODO: Handle the event (sync, transform, notify, etc.)
|
|
1395
1406
|
|
|
@@ -1407,36 +1418,14 @@ health.get('/health', (c) => {
|
|
|
1407
1418
|
});
|
|
1408
1419
|
`;
|
|
1409
1420
|
}
|
|
1410
|
-
function getApiPlatform() {
|
|
1411
|
-
return `import { createExtensionClient } from '@eide/extension-sdk/server';
|
|
1412
|
-
|
|
1413
|
-
/**
|
|
1414
|
-
* Pre-configured platform client for this extension.
|
|
1415
|
-
*
|
|
1416
|
-
* Uses env vars for configuration:
|
|
1417
|
-
* - PLATFORM_BASE_URL: Platform API base URL
|
|
1418
|
-
* - PLATFORM_API_KEY: Project-scoped API key (sk_*)
|
|
1419
|
-
* - EXTENSION_KEY: This extension's extension key
|
|
1420
|
-
*/
|
|
1421
|
-
export const platform = createExtensionClient({
|
|
1422
|
-
baseUrl: process.env.PLATFORM_BASE_URL || 'http://localhost:4000',
|
|
1423
|
-
apiKey: process.env.PLATFORM_API_KEY || '',
|
|
1424
|
-
extensionKey: process.env.EXTENSION_KEY || '',
|
|
1425
|
-
});
|
|
1426
|
-
`;
|
|
1427
|
-
}
|
|
1428
1421
|
|
|
1429
|
-
// src/commands/create-
|
|
1430
|
-
var
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
"widget"
|
|
1434
|
-
];
|
|
1435
|
-
function isValidExtensionType(value) {
|
|
1436
|
-
return EXTENSION_TYPES.includes(value);
|
|
1422
|
+
// src/commands/create-config.ts
|
|
1423
|
+
var CONFIG_TYPES = ["custom-editor", "workflow", "widget"];
|
|
1424
|
+
function isValidConfigType(value) {
|
|
1425
|
+
return CONFIG_TYPES.includes(value);
|
|
1437
1426
|
}
|
|
1438
|
-
function
|
|
1439
|
-
program2.command("create-
|
|
1427
|
+
function registerCreateConfigCommand(program2, globalOpts) {
|
|
1428
|
+
program2.command("create-config [name]").description("Scaffold a new Foir config").option("--type <type>", "Config type: custom-editor, workflow, widget").option(
|
|
1440
1429
|
"--api-url <url>",
|
|
1441
1430
|
"Platform API URL",
|
|
1442
1431
|
"http://localhost:4000/graphql"
|
|
@@ -1445,205 +1434,50 @@ function registerCreateExtensionCommand(program2, globalOpts) {
|
|
|
1445
1434
|
globalOpts,
|
|
1446
1435
|
async (name, cmdOpts) => {
|
|
1447
1436
|
console.log();
|
|
1448
|
-
console.log(chalk4.bold(" Create Foir
|
|
1449
|
-
console.log(chalk4.gray("
|
|
1437
|
+
console.log(chalk4.bold(" Create Foir Config"));
|
|
1438
|
+
console.log(chalk4.gray(" ------------------"));
|
|
1450
1439
|
console.log();
|
|
1451
|
-
let
|
|
1452
|
-
if (!
|
|
1440
|
+
let configName = name;
|
|
1441
|
+
if (!configName) {
|
|
1453
1442
|
const { inputName } = await inquirer2.prompt([
|
|
1454
1443
|
{
|
|
1455
1444
|
type: "input",
|
|
1456
1445
|
name: "inputName",
|
|
1457
|
-
message: "
|
|
1458
|
-
default: "my-
|
|
1446
|
+
message: "Config name:",
|
|
1447
|
+
default: "my-config"
|
|
1459
1448
|
}
|
|
1460
1449
|
]);
|
|
1461
|
-
|
|
1450
|
+
configName = inputName;
|
|
1462
1451
|
}
|
|
1463
|
-
let
|
|
1464
|
-
if (cmdOpts?.type &&
|
|
1465
|
-
|
|
1452
|
+
let configType;
|
|
1453
|
+
if (cmdOpts?.type && isValidConfigType(cmdOpts.type)) {
|
|
1454
|
+
configType = cmdOpts.type;
|
|
1466
1455
|
} else {
|
|
1467
1456
|
const { selectedType } = await inquirer2.prompt([
|
|
1468
1457
|
{
|
|
1469
1458
|
type: "list",
|
|
1470
1459
|
name: "selectedType",
|
|
1471
|
-
message: "
|
|
1472
|
-
choices:
|
|
1460
|
+
message: "Config type:",
|
|
1461
|
+
choices: CONFIG_TYPES,
|
|
1473
1462
|
default: "custom-editor"
|
|
1474
1463
|
}
|
|
1475
1464
|
]);
|
|
1476
|
-
|
|
1465
|
+
configType = selectedType;
|
|
1477
1466
|
}
|
|
1478
1467
|
const apiUrl = cmdOpts?.apiUrl ?? "http://localhost:4000/graphql";
|
|
1479
1468
|
console.log();
|
|
1480
1469
|
console.log(
|
|
1481
|
-
` Scaffolding ${chalk4.cyan(`"${
|
|
1470
|
+
` Scaffolding ${chalk4.cyan(`"${configName}"`)} (${configType})...`
|
|
1482
1471
|
);
|
|
1483
1472
|
console.log();
|
|
1484
|
-
await scaffold(
|
|
1473
|
+
await scaffold(configName, configType, apiUrl);
|
|
1485
1474
|
}
|
|
1486
1475
|
)
|
|
1487
1476
|
);
|
|
1488
1477
|
}
|
|
1489
1478
|
|
|
1490
1479
|
// src/graphql/generated.ts
|
|
1491
|
-
var GlobalSearchDocument = {
|
|
1492
|
-
kind: "Document",
|
|
1493
|
-
definitions: [
|
|
1494
|
-
{
|
|
1495
|
-
kind: "OperationDefinition",
|
|
1496
|
-
operation: "query",
|
|
1497
|
-
name: { kind: "Name", value: "GlobalSearch" },
|
|
1498
|
-
variableDefinitions: [
|
|
1499
|
-
{
|
|
1500
|
-
kind: "VariableDefinition",
|
|
1501
|
-
variable: {
|
|
1502
|
-
kind: "Variable",
|
|
1503
|
-
name: { kind: "Name", value: "query" }
|
|
1504
|
-
},
|
|
1505
|
-
type: {
|
|
1506
|
-
kind: "NonNullType",
|
|
1507
|
-
type: {
|
|
1508
|
-
kind: "NamedType",
|
|
1509
|
-
name: { kind: "Name", value: "String" }
|
|
1510
|
-
}
|
|
1511
|
-
}
|
|
1512
|
-
},
|
|
1513
|
-
{
|
|
1514
|
-
kind: "VariableDefinition",
|
|
1515
|
-
variable: {
|
|
1516
|
-
kind: "Variable",
|
|
1517
|
-
name: { kind: "Name", value: "limit" }
|
|
1518
|
-
},
|
|
1519
|
-
type: { kind: "NamedType", name: { kind: "Name", value: "Int" } }
|
|
1520
|
-
},
|
|
1521
|
-
{
|
|
1522
|
-
kind: "VariableDefinition",
|
|
1523
|
-
variable: {
|
|
1524
|
-
kind: "Variable",
|
|
1525
|
-
name: { kind: "Name", value: "modelKeys" }
|
|
1526
|
-
},
|
|
1527
|
-
type: {
|
|
1528
|
-
kind: "ListType",
|
|
1529
|
-
type: {
|
|
1530
|
-
kind: "NonNullType",
|
|
1531
|
-
type: {
|
|
1532
|
-
kind: "NamedType",
|
|
1533
|
-
name: { kind: "Name", value: "String" }
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
}
|
|
1537
|
-
},
|
|
1538
|
-
{
|
|
1539
|
-
kind: "VariableDefinition",
|
|
1540
|
-
variable: {
|
|
1541
|
-
kind: "Variable",
|
|
1542
|
-
name: { kind: "Name", value: "includeMedia" }
|
|
1543
|
-
},
|
|
1544
|
-
type: { kind: "NamedType", name: { kind: "Name", value: "Boolean" } }
|
|
1545
|
-
}
|
|
1546
|
-
],
|
|
1547
|
-
selectionSet: {
|
|
1548
|
-
kind: "SelectionSet",
|
|
1549
|
-
selections: [
|
|
1550
|
-
{
|
|
1551
|
-
kind: "Field",
|
|
1552
|
-
name: { kind: "Name", value: "globalSearch" },
|
|
1553
|
-
arguments: [
|
|
1554
|
-
{
|
|
1555
|
-
kind: "Argument",
|
|
1556
|
-
name: { kind: "Name", value: "query" },
|
|
1557
|
-
value: {
|
|
1558
|
-
kind: "Variable",
|
|
1559
|
-
name: { kind: "Name", value: "query" }
|
|
1560
|
-
}
|
|
1561
|
-
},
|
|
1562
|
-
{
|
|
1563
|
-
kind: "Argument",
|
|
1564
|
-
name: { kind: "Name", value: "limit" },
|
|
1565
|
-
value: {
|
|
1566
|
-
kind: "Variable",
|
|
1567
|
-
name: { kind: "Name", value: "limit" }
|
|
1568
|
-
}
|
|
1569
|
-
},
|
|
1570
|
-
{
|
|
1571
|
-
kind: "Argument",
|
|
1572
|
-
name: { kind: "Name", value: "modelKeys" },
|
|
1573
|
-
value: {
|
|
1574
|
-
kind: "Variable",
|
|
1575
|
-
name: { kind: "Name", value: "modelKeys" }
|
|
1576
|
-
}
|
|
1577
|
-
},
|
|
1578
|
-
{
|
|
1579
|
-
kind: "Argument",
|
|
1580
|
-
name: { kind: "Name", value: "includeMedia" },
|
|
1581
|
-
value: {
|
|
1582
|
-
kind: "Variable",
|
|
1583
|
-
name: { kind: "Name", value: "includeMedia" }
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
],
|
|
1587
|
-
selectionSet: {
|
|
1588
|
-
kind: "SelectionSet",
|
|
1589
|
-
selections: [
|
|
1590
|
-
{
|
|
1591
|
-
kind: "Field",
|
|
1592
|
-
name: { kind: "Name", value: "records" },
|
|
1593
|
-
selectionSet: {
|
|
1594
|
-
kind: "SelectionSet",
|
|
1595
|
-
selections: [
|
|
1596
|
-
{ kind: "Field", name: { kind: "Name", value: "id" } },
|
|
1597
|
-
{
|
|
1598
|
-
kind: "Field",
|
|
1599
|
-
name: { kind: "Name", value: "modelKey" }
|
|
1600
|
-
},
|
|
1601
|
-
{ kind: "Field", name: { kind: "Name", value: "title" } },
|
|
1602
|
-
{
|
|
1603
|
-
kind: "Field",
|
|
1604
|
-
name: { kind: "Name", value: "naturalKey" }
|
|
1605
|
-
},
|
|
1606
|
-
{
|
|
1607
|
-
kind: "Field",
|
|
1608
|
-
name: { kind: "Name", value: "subtitle" }
|
|
1609
|
-
},
|
|
1610
|
-
{
|
|
1611
|
-
kind: "Field",
|
|
1612
|
-
name: { kind: "Name", value: "updatedAt" }
|
|
1613
|
-
}
|
|
1614
|
-
]
|
|
1615
|
-
}
|
|
1616
|
-
},
|
|
1617
|
-
{
|
|
1618
|
-
kind: "Field",
|
|
1619
|
-
name: { kind: "Name", value: "media" },
|
|
1620
|
-
selectionSet: {
|
|
1621
|
-
kind: "SelectionSet",
|
|
1622
|
-
selections: [
|
|
1623
|
-
{ kind: "Field", name: { kind: "Name", value: "id" } },
|
|
1624
|
-
{
|
|
1625
|
-
kind: "Field",
|
|
1626
|
-
name: { kind: "Name", value: "fileName" }
|
|
1627
|
-
},
|
|
1628
|
-
{
|
|
1629
|
-
kind: "Field",
|
|
1630
|
-
name: { kind: "Name", value: "altText" }
|
|
1631
|
-
},
|
|
1632
|
-
{
|
|
1633
|
-
kind: "Field",
|
|
1634
|
-
name: { kind: "Name", value: "fileUrl" }
|
|
1635
|
-
}
|
|
1636
|
-
]
|
|
1637
|
-
}
|
|
1638
|
-
}
|
|
1639
|
-
]
|
|
1640
|
-
}
|
|
1641
|
-
}
|
|
1642
|
-
]
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
]
|
|
1646
|
-
};
|
|
1480
|
+
var GlobalSearchDocument = { "kind": "Document", "definitions": [{ "kind": "OperationDefinition", "operation": "query", "name": { "kind": "Name", "value": "GlobalSearch" }, "variableDefinitions": [{ "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "query" } }, "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "limit" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Int" } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "modelKeys" } }, "type": { "kind": "ListType", "type": { "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "String" } } } } }, { "kind": "VariableDefinition", "variable": { "kind": "Variable", "name": { "kind": "Name", "value": "includeMedia" } }, "type": { "kind": "NamedType", "name": { "kind": "Name", "value": "Boolean" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "globalSearch" }, "arguments": [{ "kind": "Argument", "name": { "kind": "Name", "value": "query" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "query" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "limit" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "limit" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "modelKeys" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "modelKeys" } } }, { "kind": "Argument", "name": { "kind": "Name", "value": "includeMedia" }, "value": { "kind": "Variable", "name": { "kind": "Name", "value": "includeMedia" } } }], "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "records" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "modelKey" } }, { "kind": "Field", "name": { "kind": "Name", "value": "title" } }, { "kind": "Field", "name": { "kind": "Name", "value": "naturalKey" } }, { "kind": "Field", "name": { "kind": "Name", "value": "subtitle" } }, { "kind": "Field", "name": { "kind": "Name", "value": "updatedAt" } }] } }, { "kind": "Field", "name": { "kind": "Name", "value": "media" }, "selectionSet": { "kind": "SelectionSet", "selections": [{ "kind": "Field", "name": { "kind": "Name", "value": "id" } }, { "kind": "Field", "name": { "kind": "Name", "value": "fileName" } }, { "kind": "Field", "name": { "kind": "Name", "value": "altText" } }, { "kind": "Field", "name": { "kind": "Name", "value": "fileUrl" } }] } }] } }] } }] };
|
|
1647
1481
|
|
|
1648
1482
|
// src/commands/search.ts
|
|
1649
1483
|
function registerSearchCommands(program2, globalOpts) {
|
|
@@ -1916,11 +1750,10 @@ Edit the files, then run:
|
|
|
1916
1750
|
);
|
|
1917
1751
|
}
|
|
1918
1752
|
|
|
1919
|
-
// src/commands/
|
|
1753
|
+
// src/commands/push.ts
|
|
1920
1754
|
import chalk6 from "chalk";
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
import inquirer4 from "inquirer";
|
|
1755
|
+
import { existsSync as existsSync4 } from "fs";
|
|
1756
|
+
import { resolve as resolve4 } from "path";
|
|
1924
1757
|
|
|
1925
1758
|
// src/lib/config-loader.ts
|
|
1926
1759
|
import { readFile } from "fs/promises";
|
|
@@ -1945,7 +1778,194 @@ async function loadConfig(filePath) {
|
|
|
1945
1778
|
);
|
|
1946
1779
|
}
|
|
1947
1780
|
|
|
1781
|
+
// src/commands/push.ts
|
|
1782
|
+
var CONFIG_FILE_NAMES = [
|
|
1783
|
+
"foir.config.ts",
|
|
1784
|
+
"foir.config.js",
|
|
1785
|
+
"foir.config.mjs",
|
|
1786
|
+
"foir.config.json"
|
|
1787
|
+
];
|
|
1788
|
+
var APPLY_CONFIG_MUTATION = (
|
|
1789
|
+
/* GraphQL */
|
|
1790
|
+
`
|
|
1791
|
+
mutation ApplyConfig($input: ApplyConfigInput!) {
|
|
1792
|
+
applyConfig(input: $input) {
|
|
1793
|
+
configId
|
|
1794
|
+
configKey
|
|
1795
|
+
credentials {
|
|
1796
|
+
platformApiKey
|
|
1797
|
+
platformEditorKey
|
|
1798
|
+
webhookSecret
|
|
1799
|
+
}
|
|
1800
|
+
modelsCreated
|
|
1801
|
+
modelsUpdated
|
|
1802
|
+
operationsCreated
|
|
1803
|
+
operationsUpdated
|
|
1804
|
+
segmentsCreated
|
|
1805
|
+
segmentsUpdated
|
|
1806
|
+
schedulesCreated
|
|
1807
|
+
schedulesUpdated
|
|
1808
|
+
hooksCreated
|
|
1809
|
+
hooksUpdated
|
|
1810
|
+
isUpdate
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
`
|
|
1814
|
+
);
|
|
1815
|
+
function discoverConfigFile() {
|
|
1816
|
+
for (const name of CONFIG_FILE_NAMES) {
|
|
1817
|
+
const path3 = resolve4(process.cwd(), name);
|
|
1818
|
+
if (existsSync4(path3)) return path3;
|
|
1819
|
+
}
|
|
1820
|
+
return null;
|
|
1821
|
+
}
|
|
1822
|
+
function registerPushCommand(program2, globalOpts) {
|
|
1823
|
+
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(
|
|
1824
|
+
withErrorHandler(
|
|
1825
|
+
globalOpts,
|
|
1826
|
+
async (opts) => {
|
|
1827
|
+
const configPath = opts.config ? resolve4(opts.config) : discoverConfigFile();
|
|
1828
|
+
if (!configPath) {
|
|
1829
|
+
throw new Error(
|
|
1830
|
+
"No config file found. Create a foir.config.ts or use --config <path>."
|
|
1831
|
+
);
|
|
1832
|
+
}
|
|
1833
|
+
if (!existsSync4(configPath)) {
|
|
1834
|
+
throw new Error(`Config file not found: ${configPath}`);
|
|
1835
|
+
}
|
|
1836
|
+
console.log(chalk6.dim(`Loading ${configPath}...`));
|
|
1837
|
+
const config2 = await loadConfig(configPath);
|
|
1838
|
+
if (!config2?.key || !config2?.name) {
|
|
1839
|
+
throw new Error(
|
|
1840
|
+
'Config must have at least "key" and "name" fields.'
|
|
1841
|
+
);
|
|
1842
|
+
}
|
|
1843
|
+
if (opts.force) {
|
|
1844
|
+
config2.force = true;
|
|
1845
|
+
}
|
|
1846
|
+
const client = await createClient(globalOpts());
|
|
1847
|
+
console.log(
|
|
1848
|
+
chalk6.dim(`Pushing config "${config2.key}" to platform...`)
|
|
1849
|
+
);
|
|
1850
|
+
const data = await client.request(
|
|
1851
|
+
APPLY_CONFIG_MUTATION,
|
|
1852
|
+
{ input: config2 }
|
|
1853
|
+
);
|
|
1854
|
+
const result = data.applyConfig;
|
|
1855
|
+
console.log();
|
|
1856
|
+
if (result.isUpdate) {
|
|
1857
|
+
console.log(chalk6.green("Config updated successfully."));
|
|
1858
|
+
} else {
|
|
1859
|
+
console.log(chalk6.green("Config applied successfully."));
|
|
1860
|
+
}
|
|
1861
|
+
console.log();
|
|
1862
|
+
console.log(` Config ID: ${chalk6.cyan(result.configId)}`);
|
|
1863
|
+
console.log(` Config Key: ${chalk6.cyan(result.configKey)}`);
|
|
1864
|
+
console.log();
|
|
1865
|
+
const stats = [
|
|
1866
|
+
["Models", result.modelsCreated, result.modelsUpdated],
|
|
1867
|
+
["Operations", result.operationsCreated, result.operationsUpdated],
|
|
1868
|
+
["Segments", result.segmentsCreated, result.segmentsUpdated],
|
|
1869
|
+
["Schedules", result.schedulesCreated, result.schedulesUpdated],
|
|
1870
|
+
["Hooks", result.hooksCreated, result.hooksUpdated]
|
|
1871
|
+
].filter(([, c, u]) => c > 0 || u > 0);
|
|
1872
|
+
if (stats.length > 0) {
|
|
1873
|
+
for (const [label, created, updated] of stats) {
|
|
1874
|
+
const parts = [];
|
|
1875
|
+
if (created > 0)
|
|
1876
|
+
parts.push(chalk6.green(`${created} created`));
|
|
1877
|
+
if (updated > 0)
|
|
1878
|
+
parts.push(chalk6.yellow(`${updated} updated`));
|
|
1879
|
+
console.log(` ${label}: ${parts.join(", ")}`);
|
|
1880
|
+
}
|
|
1881
|
+
console.log();
|
|
1882
|
+
}
|
|
1883
|
+
if (result.credentials) {
|
|
1884
|
+
console.log(chalk6.bold.yellow("Credentials (save these now):"));
|
|
1885
|
+
console.log();
|
|
1886
|
+
console.log(
|
|
1887
|
+
` PLATFORM_API_KEY: ${chalk6.cyan(result.credentials.platformApiKey)}`
|
|
1888
|
+
);
|
|
1889
|
+
console.log(
|
|
1890
|
+
` PLATFORM_EDITOR_KEY: ${chalk6.cyan(result.credentials.platformEditorKey)}`
|
|
1891
|
+
);
|
|
1892
|
+
console.log(
|
|
1893
|
+
` WEBHOOK_SECRET: ${chalk6.cyan(result.credentials.webhookSecret)}`
|
|
1894
|
+
);
|
|
1895
|
+
console.log();
|
|
1896
|
+
console.log(
|
|
1897
|
+
chalk6.dim(
|
|
1898
|
+
"These credentials are only shown once. Store them securely."
|
|
1899
|
+
)
|
|
1900
|
+
);
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
)
|
|
1904
|
+
);
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
// src/commands/remove.ts
|
|
1908
|
+
import chalk7 from "chalk";
|
|
1909
|
+
import inquirer4 from "inquirer";
|
|
1910
|
+
var GET_CONFIG_QUERY = (
|
|
1911
|
+
/* GraphQL */
|
|
1912
|
+
`
|
|
1913
|
+
query GetConfigByKey($key: String!) {
|
|
1914
|
+
configByKey(key: $key) {
|
|
1915
|
+
id
|
|
1916
|
+
key
|
|
1917
|
+
name
|
|
1918
|
+
configType
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
`
|
|
1922
|
+
);
|
|
1923
|
+
var UNREGISTER_MUTATION = (
|
|
1924
|
+
/* GraphQL */
|
|
1925
|
+
`
|
|
1926
|
+
mutation UnregisterConfig($id: ID!) {
|
|
1927
|
+
unregisterConfig(id: $id)
|
|
1928
|
+
}
|
|
1929
|
+
`
|
|
1930
|
+
);
|
|
1931
|
+
function registerRemoveCommand(program2, globalOpts) {
|
|
1932
|
+
program2.command("remove <key>").description("Remove a config and all its provisioned resources").option("--force", "Skip confirmation prompt", false).action(
|
|
1933
|
+
withErrorHandler(
|
|
1934
|
+
globalOpts,
|
|
1935
|
+
async (key, opts) => {
|
|
1936
|
+
const client = await createClient(globalOpts());
|
|
1937
|
+
const { configByKey: config2 } = await client.request(GET_CONFIG_QUERY, { key });
|
|
1938
|
+
if (!config2) {
|
|
1939
|
+
throw new Error(`Config not found: ${key}`);
|
|
1940
|
+
}
|
|
1941
|
+
if (!opts.force) {
|
|
1942
|
+
const { confirmed } = await inquirer4.prompt([
|
|
1943
|
+
{
|
|
1944
|
+
type: "confirm",
|
|
1945
|
+
name: "confirmed",
|
|
1946
|
+
message: `Remove config "${config2.name}" (${config2.key})? This will delete all its models, operations, hooks, and schedules.`,
|
|
1947
|
+
default: false
|
|
1948
|
+
}
|
|
1949
|
+
]);
|
|
1950
|
+
if (!confirmed) {
|
|
1951
|
+
console.log(chalk7.dim("Cancelled."));
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
await client.request(UNREGISTER_MUTATION, { id: config2.id });
|
|
1956
|
+
console.log(
|
|
1957
|
+
chalk7.green(`Removed config "${config2.name}" (${config2.key}).`)
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
)
|
|
1961
|
+
);
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
// src/commands/profiles.ts
|
|
1965
|
+
import chalk8 from "chalk";
|
|
1966
|
+
|
|
1948
1967
|
// src/lib/input.ts
|
|
1968
|
+
import inquirer5 from "inquirer";
|
|
1949
1969
|
async function parseInputData(opts) {
|
|
1950
1970
|
if (opts.data) {
|
|
1951
1971
|
return JSON.parse(opts.data);
|
|
@@ -1974,7 +1994,7 @@ function isUUID(value) {
|
|
|
1974
1994
|
}
|
|
1975
1995
|
async function confirmAction(message, opts) {
|
|
1976
1996
|
if (opts?.confirm) return true;
|
|
1977
|
-
const { confirmed } = await
|
|
1997
|
+
const { confirmed } = await inquirer5.prompt([
|
|
1978
1998
|
{
|
|
1979
1999
|
type: "confirm",
|
|
1980
2000
|
name: "confirmed",
|
|
@@ -2145,7 +2165,7 @@ function registerProfilesCommand(program2, globalOpts) {
|
|
|
2145
2165
|
if (opts.json || opts.jsonl) {
|
|
2146
2166
|
formatOutput({ deleted: name }, opts);
|
|
2147
2167
|
} else {
|
|
2148
|
-
console.log(
|
|
2168
|
+
console.log(chalk8.green(`Deleted profile "${name}".`));
|
|
2149
2169
|
}
|
|
2150
2170
|
}
|
|
2151
2171
|
)
|
|
@@ -2154,9 +2174,9 @@ function registerProfilesCommand(program2, globalOpts) {
|
|
|
2154
2174
|
|
|
2155
2175
|
// src/commands/register-commands.ts
|
|
2156
2176
|
import { readFileSync, readdirSync } from "fs";
|
|
2157
|
-
import { resolve as
|
|
2177
|
+
import { resolve as resolve5, dirname as dirname4 } from "path";
|
|
2158
2178
|
import { fileURLToPath } from "url";
|
|
2159
|
-
import
|
|
2179
|
+
import chalk9 from "chalk";
|
|
2160
2180
|
|
|
2161
2181
|
// ../command-registry/src/command-map.ts
|
|
2162
2182
|
var COMMANDS = [
|
|
@@ -2782,65 +2802,65 @@ var COMMANDS = [
|
|
|
2782
2802
|
// EXTENSIONS
|
|
2783
2803
|
// =========================================================================
|
|
2784
2804
|
{
|
|
2785
|
-
group: "
|
|
2805
|
+
group: "configs",
|
|
2786
2806
|
name: "list",
|
|
2787
|
-
description: "List
|
|
2788
|
-
operation: "
|
|
2807
|
+
description: "List configs",
|
|
2808
|
+
operation: "configs",
|
|
2789
2809
|
operationType: "query",
|
|
2790
2810
|
columns: [
|
|
2791
2811
|
{ key: "id", header: "ID", width: 28 },
|
|
2792
2812
|
{ key: "key", header: "Key", width: 20 },
|
|
2793
2813
|
{ key: "name", header: "Name", width: 20 },
|
|
2794
|
-
{ key: "
|
|
2814
|
+
{ key: "configType", header: "Type", width: 12 },
|
|
2795
2815
|
{ key: "enabled", header: "Enabled", width: 8, format: "boolean" },
|
|
2796
2816
|
{ key: "syncStatus", header: "Sync", width: 10 }
|
|
2797
2817
|
]
|
|
2798
2818
|
},
|
|
2799
2819
|
{
|
|
2800
|
-
group: "
|
|
2820
|
+
group: "configs",
|
|
2801
2821
|
name: "get",
|
|
2802
|
-
description: "Get
|
|
2803
|
-
operation: "
|
|
2822
|
+
description: "Get a config",
|
|
2823
|
+
operation: "config",
|
|
2804
2824
|
operationType: "query",
|
|
2805
2825
|
positionalArgs: [{ name: "id", graphqlArg: "id" }],
|
|
2806
|
-
alternateGet: { operation: "
|
|
2826
|
+
alternateGet: { operation: "configByKey", argName: "key" }
|
|
2807
2827
|
},
|
|
2808
2828
|
{
|
|
2809
|
-
group: "
|
|
2829
|
+
group: "configs",
|
|
2810
2830
|
name: "register",
|
|
2811
|
-
description: "Register
|
|
2812
|
-
operation: "
|
|
2831
|
+
description: "Register a config",
|
|
2832
|
+
operation: "registerConfig",
|
|
2813
2833
|
operationType: "mutation",
|
|
2814
2834
|
acceptsInput: true,
|
|
2815
|
-
successMessage: "Registered
|
|
2835
|
+
successMessage: "Registered config"
|
|
2816
2836
|
},
|
|
2817
2837
|
{
|
|
2818
|
-
group: "
|
|
2819
|
-
name: "
|
|
2820
|
-
description: "
|
|
2821
|
-
operation: "
|
|
2838
|
+
group: "configs",
|
|
2839
|
+
name: "apply",
|
|
2840
|
+
description: "Apply a config",
|
|
2841
|
+
operation: "applyConfig",
|
|
2822
2842
|
operationType: "mutation",
|
|
2823
2843
|
acceptsInput: true,
|
|
2824
|
-
successMessage: "
|
|
2844
|
+
successMessage: "Applied config"
|
|
2825
2845
|
},
|
|
2826
2846
|
{
|
|
2827
|
-
group: "
|
|
2847
|
+
group: "configs",
|
|
2828
2848
|
name: "uninstall",
|
|
2829
|
-
description: "Unregister
|
|
2830
|
-
operation: "
|
|
2849
|
+
description: "Unregister a config",
|
|
2850
|
+
operation: "unregisterConfig",
|
|
2831
2851
|
operationType: "mutation",
|
|
2832
2852
|
positionalArgs: [{ name: "id", graphqlArg: "id" }],
|
|
2833
2853
|
requiresConfirmation: true,
|
|
2834
2854
|
scalarResult: true,
|
|
2835
|
-
successMessage: "Unregistered
|
|
2855
|
+
successMessage: "Unregistered config"
|
|
2836
2856
|
},
|
|
2837
2857
|
{
|
|
2838
|
-
group: "
|
|
2858
|
+
group: "configs",
|
|
2839
2859
|
name: "sync",
|
|
2840
|
-
description: "Trigger
|
|
2841
|
-
operation: "
|
|
2860
|
+
description: "Trigger config sync",
|
|
2861
|
+
operation: "triggerConfigSync",
|
|
2842
2862
|
operationType: "mutation",
|
|
2843
|
-
positionalArgs: [{ name: "
|
|
2863
|
+
positionalArgs: [{ name: "configId", graphqlArg: "configId" }],
|
|
2844
2864
|
successMessage: "Triggered sync"
|
|
2845
2865
|
},
|
|
2846
2866
|
// =========================================================================
|
|
@@ -3757,11 +3777,11 @@ function createSchemaEngine(sdl) {
|
|
|
3757
3777
|
var __filename = fileURLToPath(import.meta.url);
|
|
3758
3778
|
var __dirname = dirname4(__filename);
|
|
3759
3779
|
function loadSchemaSDL() {
|
|
3760
|
-
const bundledPath =
|
|
3780
|
+
const bundledPath = resolve5(__dirname, "schema.graphql");
|
|
3761
3781
|
try {
|
|
3762
3782
|
return readFileSync(bundledPath, "utf-8");
|
|
3763
3783
|
} catch {
|
|
3764
|
-
const monorepoPath =
|
|
3784
|
+
const monorepoPath = resolve5(
|
|
3765
3785
|
__dirname,
|
|
3766
3786
|
"../../../graphql-core/schema.graphql"
|
|
3767
3787
|
);
|
|
@@ -3917,11 +3937,11 @@ function registerDynamicCommands(program2, globalOpts) {
|
|
|
3917
3937
|
);
|
|
3918
3938
|
Object.assign(variables, coerced);
|
|
3919
3939
|
if (flags.dir && entry.acceptsInput) {
|
|
3920
|
-
const dirPath =
|
|
3940
|
+
const dirPath = resolve5(String(flags.dir));
|
|
3921
3941
|
const files = readdirSync(dirPath).filter((f) => /\.(json|ts|js|mjs)$/.test(f)).sort();
|
|
3922
3942
|
if (files.length === 0) {
|
|
3923
3943
|
console.error(
|
|
3924
|
-
|
|
3944
|
+
chalk9.yellow(`\u26A0 No .json/.ts/.js files found in ${dirPath}`)
|
|
3925
3945
|
);
|
|
3926
3946
|
return;
|
|
3927
3947
|
}
|
|
@@ -3929,7 +3949,7 @@ function registerDynamicCommands(program2, globalOpts) {
|
|
|
3929
3949
|
let updated = 0;
|
|
3930
3950
|
let failed = 0;
|
|
3931
3951
|
for (const file of files) {
|
|
3932
|
-
const filePath =
|
|
3952
|
+
const filePath = resolve5(dirPath, file);
|
|
3933
3953
|
const fileData = await parseInputData({ file: filePath });
|
|
3934
3954
|
const argName = entry.inputArgName ?? "input";
|
|
3935
3955
|
const fileVars = { ...variables, [argName]: fileData };
|
|
@@ -3966,19 +3986,19 @@ function registerDynamicCommands(program2, globalOpts) {
|
|
|
3966
3986
|
} catch (updateErr) {
|
|
3967
3987
|
failed++;
|
|
3968
3988
|
const msg2 = updateErr instanceof Error ? updateErr.message : String(updateErr);
|
|
3969
|
-
console.error(
|
|
3989
|
+
console.error(chalk9.red(`\u2717 ${label}:`), msg2);
|
|
3970
3990
|
continue;
|
|
3971
3991
|
}
|
|
3972
3992
|
}
|
|
3973
3993
|
failed++;
|
|
3974
3994
|
const msg = err instanceof Error ? err.message : String(err);
|
|
3975
|
-
console.error(
|
|
3995
|
+
console.error(chalk9.red(`\u2717 ${label}:`), msg);
|
|
3976
3996
|
}
|
|
3977
3997
|
}
|
|
3978
3998
|
if (!(opts.json || opts.jsonl || opts.quiet)) {
|
|
3979
3999
|
console.log("");
|
|
3980
4000
|
console.log(
|
|
3981
|
-
|
|
4001
|
+
chalk9.bold(
|
|
3982
4002
|
`Done: ${created} created${updated ? `, ${updated} updated` : ""}${failed ? `, ${failed} failed` : ""}`
|
|
3983
4003
|
)
|
|
3984
4004
|
);
|
|
@@ -4154,7 +4174,7 @@ function registerDynamicCommands(program2, globalOpts) {
|
|
|
4154
4174
|
}
|
|
4155
4175
|
} else if (!(opts.json || opts.jsonl || opts.quiet)) {
|
|
4156
4176
|
console.error(
|
|
4157
|
-
|
|
4177
|
+
chalk9.yellow(
|
|
4158
4178
|
"\u26A0 Could not auto-publish: no version found in response"
|
|
4159
4179
|
)
|
|
4160
4180
|
);
|
|
@@ -4178,7 +4198,7 @@ function autoColumns(items) {
|
|
|
4178
4198
|
// src/cli.ts
|
|
4179
4199
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
4180
4200
|
var __dirname2 = dirname5(__filename2);
|
|
4181
|
-
config({ path:
|
|
4201
|
+
config({ path: resolve6(__dirname2, "../.env.local") });
|
|
4182
4202
|
var require2 = createRequire(import.meta.url);
|
|
4183
4203
|
var { version } = require2("../package.json");
|
|
4184
4204
|
var program = new Command();
|
|
@@ -4200,7 +4220,9 @@ registerWhoamiCommand(program, getGlobalOpts);
|
|
|
4200
4220
|
registerProfilesCommand(program, getGlobalOpts);
|
|
4201
4221
|
registerMediaCommands(program, getGlobalOpts);
|
|
4202
4222
|
registerSearchCommands(program, getGlobalOpts);
|
|
4203
|
-
|
|
4223
|
+
registerPushCommand(program, getGlobalOpts);
|
|
4224
|
+
registerRemoveCommand(program, getGlobalOpts);
|
|
4225
|
+
registerCreateConfigCommand(program, getGlobalOpts);
|
|
4204
4226
|
registerInitCommands(program, getGlobalOpts);
|
|
4205
4227
|
registerDynamicCommands(program, getGlobalOpts);
|
|
4206
4228
|
program.parse();
|