@constructive-io/cli 8.0.3 → 8.1.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/commands/server.js +10 -10
- package/commands.js +0 -2
- package/esm/commands/server.js +10 -10
- package/esm/commands.js +0 -2
- package/esm/utils/display.js +0 -4
- package/package.json +12 -13
- package/utils/display.d.ts +1 -1
- package/utils/display.js +0 -4
- package/commands/jobs.d.ts +0 -3
- package/commands/jobs.js +0 -167
- package/esm/commands/jobs.js +0 -165
package/commands/server.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const graphql_env_1 = require("@constructive-io/graphql-env");
|
|
4
|
-
const logger_1 = require("@pgpmjs/logger");
|
|
5
4
|
const graphql_server_1 = require("@constructive-io/graphql-server");
|
|
5
|
+
const logger_1 = require("@pgpmjs/logger");
|
|
6
6
|
const pg_cache_1 = require("pg-cache");
|
|
7
7
|
const log = new logger_1.Logger('server');
|
|
8
8
|
const serverUsageText = `
|
|
@@ -19,7 +19,7 @@ Options:
|
|
|
19
19
|
--simpleInflection Use simple inflection (default: true)
|
|
20
20
|
--oppositeBaseNames Use opposite base names (default: false)
|
|
21
21
|
--postgis Enable PostGIS extension (default: true)
|
|
22
|
-
--
|
|
22
|
+
--scopedRouting Enable scoped routing (default: true)
|
|
23
23
|
--cwd <directory> Working directory (default: current directory)
|
|
24
24
|
|
|
25
25
|
Examples:
|
|
@@ -54,8 +54,8 @@ const questions = [
|
|
|
54
54
|
useDefault: true
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
|
-
name: '
|
|
58
|
-
message: 'Enable
|
|
57
|
+
name: 'scopedRouting',
|
|
58
|
+
message: 'Enable scoped routing?',
|
|
59
59
|
type: 'confirm',
|
|
60
60
|
required: false,
|
|
61
61
|
default: true,
|
|
@@ -65,7 +65,7 @@ const questions = [
|
|
|
65
65
|
name: 'origin',
|
|
66
66
|
message: 'CORS origin (exact URL or *)',
|
|
67
67
|
type: 'text',
|
|
68
|
-
required: false
|
|
68
|
+
required: false
|
|
69
69
|
// no default to avoid accidentally opening up CORS; pass explicitly or via env
|
|
70
70
|
},
|
|
71
71
|
{
|
|
@@ -106,7 +106,7 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
106
106
|
selectedDb = database;
|
|
107
107
|
log.info(`📌 Using database: "${selectedDb}"`);
|
|
108
108
|
}
|
|
109
|
-
const { oppositeBaseNames, port, postgis, simpleInflection,
|
|
109
|
+
const { oppositeBaseNames, port, postgis, simpleInflection, scopedRouting, origin } = await prompter.prompt(argv, questions);
|
|
110
110
|
// Warn when passing CORS override via CLI, especially in production
|
|
111
111
|
if (origin && origin.trim().length) {
|
|
112
112
|
const env = (process.env.NODE_ENV || 'development').toLowerCase();
|
|
@@ -122,7 +122,7 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
122
122
|
let selectedSchemas = [];
|
|
123
123
|
let authRole;
|
|
124
124
|
let roleName;
|
|
125
|
-
if (!
|
|
125
|
+
if (!scopedRouting) {
|
|
126
126
|
const db = await (0, pg_cache_1.getPgPool)({ database: selectedDb });
|
|
127
127
|
const result = await db.query(`
|
|
128
128
|
SELECT nspname
|
|
@@ -172,8 +172,8 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
172
172
|
postgis
|
|
173
173
|
},
|
|
174
174
|
api: {
|
|
175
|
-
|
|
176
|
-
...(
|
|
175
|
+
enableScopedRouting: scopedRouting,
|
|
176
|
+
...(scopedRouting === false && { exposedSchemas: selectedSchemas, authRole, roleName })
|
|
177
177
|
},
|
|
178
178
|
server: {
|
|
179
179
|
port,
|
|
@@ -186,7 +186,7 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
186
186
|
}
|
|
187
187
|
// Debug: Log API routing configuration
|
|
188
188
|
const apiOpts = options.api || {};
|
|
189
|
-
log.debug(`📡 API Routing: isPublic=${apiOpts.isPublic},
|
|
189
|
+
log.debug(`📡 API Routing: isPublic=${apiOpts.isPublic}, enableScopedRouting=${apiOpts.enableScopedRouting}`);
|
|
190
190
|
if (apiOpts.isPublic === false) {
|
|
191
191
|
log.debug(` Header-based routing enabled (X-Api-Name, X-Database-Id, X-Meta-Schema)`);
|
|
192
192
|
}
|
package/commands.js
CHANGED
|
@@ -11,7 +11,6 @@ const codegen_1 = __importDefault(require("./commands/codegen"));
|
|
|
11
11
|
const context_1 = __importDefault(require("./commands/context"));
|
|
12
12
|
const execute_1 = __importDefault(require("./commands/execute"));
|
|
13
13
|
const explorer_1 = __importDefault(require("./commands/explorer"));
|
|
14
|
-
const jobs_1 = __importDefault(require("./commands/jobs"));
|
|
15
14
|
const server_1 = __importDefault(require("./commands/server"));
|
|
16
15
|
const utils_2 = require("./utils");
|
|
17
16
|
const createCommandMap = () => {
|
|
@@ -19,7 +18,6 @@ const createCommandMap = () => {
|
|
|
19
18
|
server: server_1.default,
|
|
20
19
|
explorer: explorer_1.default,
|
|
21
20
|
codegen: codegen_1.default,
|
|
22
|
-
jobs: jobs_1.default,
|
|
23
21
|
context: context_1.default,
|
|
24
22
|
auth: auth_1.default,
|
|
25
23
|
execute: execute_1.default,
|
package/esm/commands/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getEnvOptions } from '@constructive-io/graphql-env';
|
|
2
|
-
import { Logger } from '@pgpmjs/logger';
|
|
3
2
|
import { GraphQLServer as server } from '@constructive-io/graphql-server';
|
|
3
|
+
import { Logger } from '@pgpmjs/logger';
|
|
4
4
|
import { getPgPool } from 'pg-cache';
|
|
5
5
|
const log = new Logger('server');
|
|
6
6
|
const serverUsageText = `
|
|
@@ -17,7 +17,7 @@ Options:
|
|
|
17
17
|
--simpleInflection Use simple inflection (default: true)
|
|
18
18
|
--oppositeBaseNames Use opposite base names (default: false)
|
|
19
19
|
--postgis Enable PostGIS extension (default: true)
|
|
20
|
-
--
|
|
20
|
+
--scopedRouting Enable scoped routing (default: true)
|
|
21
21
|
--cwd <directory> Working directory (default: current directory)
|
|
22
22
|
|
|
23
23
|
Examples:
|
|
@@ -52,8 +52,8 @@ const questions = [
|
|
|
52
52
|
useDefault: true
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
|
-
name: '
|
|
56
|
-
message: 'Enable
|
|
55
|
+
name: 'scopedRouting',
|
|
56
|
+
message: 'Enable scoped routing?',
|
|
57
57
|
type: 'confirm',
|
|
58
58
|
required: false,
|
|
59
59
|
default: true,
|
|
@@ -63,7 +63,7 @@ const questions = [
|
|
|
63
63
|
name: 'origin',
|
|
64
64
|
message: 'CORS origin (exact URL or *)',
|
|
65
65
|
type: 'text',
|
|
66
|
-
required: false
|
|
66
|
+
required: false
|
|
67
67
|
// no default to avoid accidentally opening up CORS; pass explicitly or via env
|
|
68
68
|
},
|
|
69
69
|
{
|
|
@@ -104,7 +104,7 @@ export default async (argv, prompter, _options) => {
|
|
|
104
104
|
selectedDb = database;
|
|
105
105
|
log.info(`📌 Using database: "${selectedDb}"`);
|
|
106
106
|
}
|
|
107
|
-
const { oppositeBaseNames, port, postgis, simpleInflection,
|
|
107
|
+
const { oppositeBaseNames, port, postgis, simpleInflection, scopedRouting, origin } = await prompter.prompt(argv, questions);
|
|
108
108
|
// Warn when passing CORS override via CLI, especially in production
|
|
109
109
|
if (origin && origin.trim().length) {
|
|
110
110
|
const env = (process.env.NODE_ENV || 'development').toLowerCase();
|
|
@@ -120,7 +120,7 @@ export default async (argv, prompter, _options) => {
|
|
|
120
120
|
let selectedSchemas = [];
|
|
121
121
|
let authRole;
|
|
122
122
|
let roleName;
|
|
123
|
-
if (!
|
|
123
|
+
if (!scopedRouting) {
|
|
124
124
|
const db = await getPgPool({ database: selectedDb });
|
|
125
125
|
const result = await db.query(`
|
|
126
126
|
SELECT nspname
|
|
@@ -170,8 +170,8 @@ export default async (argv, prompter, _options) => {
|
|
|
170
170
|
postgis
|
|
171
171
|
},
|
|
172
172
|
api: {
|
|
173
|
-
|
|
174
|
-
...(
|
|
173
|
+
enableScopedRouting: scopedRouting,
|
|
174
|
+
...(scopedRouting === false && { exposedSchemas: selectedSchemas, authRole, roleName })
|
|
175
175
|
},
|
|
176
176
|
server: {
|
|
177
177
|
port,
|
|
@@ -184,7 +184,7 @@ export default async (argv, prompter, _options) => {
|
|
|
184
184
|
}
|
|
185
185
|
// Debug: Log API routing configuration
|
|
186
186
|
const apiOpts = options.api || {};
|
|
187
|
-
log.debug(`📡 API Routing: isPublic=${apiOpts.isPublic},
|
|
187
|
+
log.debug(`📡 API Routing: isPublic=${apiOpts.isPublic}, enableScopedRouting=${apiOpts.enableScopedRouting}`);
|
|
188
188
|
if (apiOpts.isPublic === false) {
|
|
189
189
|
log.debug(` Header-based routing enabled (X-Api-Name, X-Database-Id, X-Meta-Schema)`);
|
|
190
190
|
}
|
package/esm/commands.js
CHANGED
|
@@ -5,7 +5,6 @@ import codegen from './commands/codegen';
|
|
|
5
5
|
import context from './commands/context';
|
|
6
6
|
import execute from './commands/execute';
|
|
7
7
|
import explorer from './commands/explorer';
|
|
8
|
-
import jobs from './commands/jobs';
|
|
9
8
|
import server from './commands/server';
|
|
10
9
|
import { usageText } from './utils';
|
|
11
10
|
const createCommandMap = () => {
|
|
@@ -13,7 +12,6 @@ const createCommandMap = () => {
|
|
|
13
12
|
server,
|
|
14
13
|
explorer,
|
|
15
14
|
codegen,
|
|
16
|
-
jobs,
|
|
17
15
|
context,
|
|
18
16
|
auth,
|
|
19
17
|
execute,
|
package/esm/utils/display.js
CHANGED
|
@@ -11,9 +11,6 @@ export const usageText = `
|
|
|
11
11
|
Code Generation:
|
|
12
12
|
codegen Generate TypeScript types and SDK from GraphQL schema
|
|
13
13
|
|
|
14
|
-
Jobs:
|
|
15
|
-
jobs up Start combined server (jobs runtime)
|
|
16
|
-
|
|
17
14
|
Execution Engine:
|
|
18
15
|
context Manage contexts (create, list, use, current, delete)
|
|
19
16
|
auth Manage authentication (set-token, status, logout)
|
|
@@ -34,7 +31,6 @@ export const usageText = `
|
|
|
34
31
|
cnc explorer Launch GraphiQL explorer
|
|
35
32
|
cnc codegen --schema schema.graphql Generate types from schema
|
|
36
33
|
cnc codegen --schema-enabled --output ./schemas Export schema SDL
|
|
37
|
-
cnc jobs up Start combined server (jobs runtime)
|
|
38
34
|
|
|
39
35
|
# Execution Engine
|
|
40
36
|
cnc context create my-api --endpoint https://api.example.com/graphql
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructive-io/cli",
|
|
3
|
-
"version": "8.0
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "Constructive CLI",
|
|
6
6
|
"main": "index.js",
|
|
@@ -45,24 +45,23 @@
|
|
|
45
45
|
"ts-node": "^10.9.2"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@constructive-io/graphql-codegen": "^5.0
|
|
49
|
-
"@constructive-io/graphql-env": "^3.
|
|
50
|
-
"@constructive-io/graphql-explorer": "^5.0.
|
|
51
|
-
"@constructive-io/graphql-server": "^5.0
|
|
52
|
-
"@constructive-io/graphql-types": "^3.
|
|
53
|
-
"@constructive-io/knative-job-service": "^3.0.3",
|
|
48
|
+
"@constructive-io/graphql-codegen": "^5.1.0",
|
|
49
|
+
"@constructive-io/graphql-env": "^3.17.0",
|
|
50
|
+
"@constructive-io/graphql-explorer": "^5.0.5",
|
|
51
|
+
"@constructive-io/graphql-server": "^5.1.0",
|
|
52
|
+
"@constructive-io/graphql-types": "^3.16.0",
|
|
54
53
|
"@inquirerer/utils": "^3.3.9",
|
|
55
|
-
"@pgpmjs/core": "^7.
|
|
54
|
+
"@pgpmjs/core": "^7.3.0",
|
|
56
55
|
"@pgpmjs/logger": "^2.14.0",
|
|
57
|
-
"@pgpmjs/server-utils": "^3.15.
|
|
58
|
-
"@pgpmjs/types": "^2.
|
|
56
|
+
"@pgpmjs/server-utils": "^3.15.4",
|
|
57
|
+
"@pgpmjs/types": "^2.36.0",
|
|
59
58
|
"appstash": "^0.7.0",
|
|
60
59
|
"find-and-require-package-json": "^0.9.1",
|
|
61
60
|
"inquirerer": "^4.9.1",
|
|
62
61
|
"js-yaml": "^4.1.0",
|
|
63
|
-
"pg-cache": "^3.15.
|
|
62
|
+
"pg-cache": "^3.15.3",
|
|
64
63
|
"pg-env": "^1.18.1",
|
|
65
|
-
"pgpm": "^5.0
|
|
64
|
+
"pgpm": "^5.1.0",
|
|
66
65
|
"shelljs": "^0.10.0",
|
|
67
66
|
"yanse": "^0.2.1"
|
|
68
67
|
},
|
|
@@ -77,5 +76,5 @@
|
|
|
77
76
|
"postgres",
|
|
78
77
|
"graphile"
|
|
79
78
|
],
|
|
80
|
-
"gitHead": "
|
|
79
|
+
"gitHead": "39db6d576bce7bc1de8123849f237b1695779d88"
|
|
81
80
|
}
|
package/utils/display.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const usageText = "\n Usage: cnc <command> [options]\n constructive <command> [options]\n\n Constructive CLI - API Server and Development Tools\n\n GraphQL Server:\n server Start a GraphQL server\n explorer Launch GraphiQL explorer interface\n\n Code Generation:\n codegen Generate TypeScript types and SDK from GraphQL schema\n\n
|
|
1
|
+
export declare const usageText = "\n Usage: cnc <command> [options]\n constructive <command> [options]\n\n Constructive CLI - API Server and Development Tools\n\n GraphQL Server:\n server Start a GraphQL server\n explorer Launch GraphiQL explorer interface\n\n Code Generation:\n codegen Generate TypeScript types and SDK from GraphQL schema\n\n Execution Engine:\n context Manage contexts (create, list, use, current, delete)\n auth Manage authentication (set-token, status, logout)\n execute Execute GraphQL queries against configured endpoints\n\n Global Options:\n -h, --help Display this help information\n -v, --version Display version information\n --cwd <directory> Working directory (default: current directory)\n\n Individual Command Help:\n cnc <command> --help Display detailed help for specific command\n cnc <command> -h Display detailed help for specific command\n\n Examples:\n cnc server Start GraphQL server\n cnc server --port 8080 Start server on custom port\n cnc explorer Launch GraphiQL explorer\n cnc codegen --schema schema.graphql Generate types from schema\n cnc codegen --schema-enabled --output ./schemas Export schema SDL\n\n # Execution Engine\n cnc context create my-api --endpoint https://api.example.com/graphql\n cnc auth set-token\n cnc execute --query 'query { __typename }'\n\n Database Operations:\n For database migrations, packages, and deployment, use pgpm:\n https://pgpm.io\n ";
|
package/utils/display.js
CHANGED
|
@@ -14,9 +14,6 @@ exports.usageText = `
|
|
|
14
14
|
Code Generation:
|
|
15
15
|
codegen Generate TypeScript types and SDK from GraphQL schema
|
|
16
16
|
|
|
17
|
-
Jobs:
|
|
18
|
-
jobs up Start combined server (jobs runtime)
|
|
19
|
-
|
|
20
17
|
Execution Engine:
|
|
21
18
|
context Manage contexts (create, list, use, current, delete)
|
|
22
19
|
auth Manage authentication (set-token, status, logout)
|
|
@@ -37,7 +34,6 @@ exports.usageText = `
|
|
|
37
34
|
cnc explorer Launch GraphiQL explorer
|
|
38
35
|
cnc codegen --schema schema.graphql Generate types from schema
|
|
39
36
|
cnc codegen --schema-enabled --output ./schemas Export schema SDL
|
|
40
|
-
cnc jobs up Start combined server (jobs runtime)
|
|
41
37
|
|
|
42
38
|
# Execution Engine
|
|
43
39
|
cnc context create my-api --endpoint https://api.example.com/graphql
|
package/commands/jobs.d.ts
DELETED
package/commands/jobs.js
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const fs_1 = require("fs");
|
|
4
|
-
const path_1 = require("path");
|
|
5
|
-
const knative_job_service_1 = require("@constructive-io/knative-job-service");
|
|
6
|
-
const inquirerer_1 = require("inquirerer");
|
|
7
|
-
const jobsUsageText = `
|
|
8
|
-
Constructive Jobs:
|
|
9
|
-
|
|
10
|
-
cnc jobs <subcommand> [OPTIONS]
|
|
11
|
-
|
|
12
|
-
Start or manage Constructive jobs services.
|
|
13
|
-
|
|
14
|
-
Subcommands:
|
|
15
|
-
up Start jobs runtime (jobs + functions)
|
|
16
|
-
|
|
17
|
-
Options:
|
|
18
|
-
--help, -h Show this help message
|
|
19
|
-
--cwd <directory> Working directory (default: current directory)
|
|
20
|
-
--with-jobs-server Enable jobs server (default: disabled; flag-only)
|
|
21
|
-
--functions <list> Comma-separated functions, optionally with ports (e.g. "fn=8080")
|
|
22
|
-
|
|
23
|
-
Examples:
|
|
24
|
-
cnc jobs up
|
|
25
|
-
cnc jobs up --cwd /path/to/constructive
|
|
26
|
-
cnc jobs up --with-jobs-server --functions send-email,send-verification-link=8082
|
|
27
|
-
`;
|
|
28
|
-
const questions = [
|
|
29
|
-
{
|
|
30
|
-
name: 'withJobsServer',
|
|
31
|
-
alias: 'with-jobs-server',
|
|
32
|
-
message: 'Enable jobs server?',
|
|
33
|
-
type: 'confirm',
|
|
34
|
-
required: false,
|
|
35
|
-
default: false,
|
|
36
|
-
useDefault: true
|
|
37
|
-
}
|
|
38
|
-
];
|
|
39
|
-
const ensureCwd = (cwd) => {
|
|
40
|
-
const resolved = (0, path_1.resolve)(cwd);
|
|
41
|
-
if (!(0, fs_1.existsSync)(resolved)) {
|
|
42
|
-
throw new Error(`Working directory does not exist: ${resolved}`);
|
|
43
|
-
}
|
|
44
|
-
process.chdir(resolved);
|
|
45
|
-
return resolved;
|
|
46
|
-
};
|
|
47
|
-
const parseFunctionsArg = (value) => {
|
|
48
|
-
if (value === undefined)
|
|
49
|
-
return undefined;
|
|
50
|
-
const values = Array.isArray(value) ? value : [value];
|
|
51
|
-
const tokens = [];
|
|
52
|
-
for (const value of values) {
|
|
53
|
-
if (value === true) {
|
|
54
|
-
tokens.push('all');
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
if (value === false || value === undefined || value === null)
|
|
58
|
-
continue;
|
|
59
|
-
const raw = String(value);
|
|
60
|
-
raw
|
|
61
|
-
.split(',')
|
|
62
|
-
.map((part) => part.trim())
|
|
63
|
-
.filter(Boolean)
|
|
64
|
-
.forEach((part) => tokens.push(part));
|
|
65
|
-
}
|
|
66
|
-
if (!tokens.length) {
|
|
67
|
-
return { mode: 'list', names: [], ports: {} };
|
|
68
|
-
}
|
|
69
|
-
const hasAll = tokens.some((token) => {
|
|
70
|
-
const normalized = token.trim().toLowerCase();
|
|
71
|
-
return normalized === 'all' || normalized === '*';
|
|
72
|
-
});
|
|
73
|
-
if (hasAll) {
|
|
74
|
-
if (tokens.length > 1) {
|
|
75
|
-
throw new Error('Use "all" without other function names.');
|
|
76
|
-
}
|
|
77
|
-
return { mode: 'all', names: [], ports: {} };
|
|
78
|
-
}
|
|
79
|
-
const names = [];
|
|
80
|
-
const ports = {};
|
|
81
|
-
for (const token of tokens) {
|
|
82
|
-
const trimmed = token.trim();
|
|
83
|
-
if (!trimmed)
|
|
84
|
-
continue;
|
|
85
|
-
const separatorIndex = trimmed.search(/[:=]/);
|
|
86
|
-
if (separatorIndex === -1) {
|
|
87
|
-
names.push(trimmed);
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
const name = trimmed.slice(0, separatorIndex).trim();
|
|
91
|
-
const portText = trimmed.slice(separatorIndex + 1).trim();
|
|
92
|
-
if (!name) {
|
|
93
|
-
throw new Error(`Missing function name in "${token}".`);
|
|
94
|
-
}
|
|
95
|
-
if (!portText) {
|
|
96
|
-
throw new Error(`Missing port for function "${name}".`);
|
|
97
|
-
}
|
|
98
|
-
const port = Number(portText);
|
|
99
|
-
if (!Number.isFinite(port) || port <= 0) {
|
|
100
|
-
throw new Error(`Invalid port "${portText}" for function "${name}".`);
|
|
101
|
-
}
|
|
102
|
-
names.push(name);
|
|
103
|
-
ports[name] = port;
|
|
104
|
-
}
|
|
105
|
-
const uniqueNames = [];
|
|
106
|
-
const seen = new Set();
|
|
107
|
-
for (const name of names) {
|
|
108
|
-
if (seen.has(name))
|
|
109
|
-
continue;
|
|
110
|
-
seen.add(name);
|
|
111
|
-
uniqueNames.push(name);
|
|
112
|
-
}
|
|
113
|
-
return { mode: 'list', names: uniqueNames, ports };
|
|
114
|
-
};
|
|
115
|
-
const buildKnativeJobsSvcOptions = (args) => {
|
|
116
|
-
const parsedFunctions = parseFunctionsArg(args.functions);
|
|
117
|
-
let functions;
|
|
118
|
-
if (parsedFunctions) {
|
|
119
|
-
if (parsedFunctions.mode === 'all') {
|
|
120
|
-
functions = { enabled: true };
|
|
121
|
-
}
|
|
122
|
-
else if (parsedFunctions.names.length) {
|
|
123
|
-
const services = parsedFunctions.names.map((name) => ({
|
|
124
|
-
name: name,
|
|
125
|
-
port: parsedFunctions.ports[name]
|
|
126
|
-
}));
|
|
127
|
-
functions = { enabled: true, services };
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
functions = undefined;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
jobs: { enabled: args.withJobsServer === true },
|
|
135
|
-
functions
|
|
136
|
-
};
|
|
137
|
-
};
|
|
138
|
-
exports.default = async (argv, prompter, _options) => {
|
|
139
|
-
if (argv.help || argv.h) {
|
|
140
|
-
console.log(jobsUsageText);
|
|
141
|
-
process.exit(0);
|
|
142
|
-
}
|
|
143
|
-
const { first: subcommand, newArgv } = (0, inquirerer_1.extractFirst)(argv);
|
|
144
|
-
const args = newArgv;
|
|
145
|
-
if (!subcommand) {
|
|
146
|
-
console.log(jobsUsageText);
|
|
147
|
-
await (0, inquirerer_1.cliExitWithError)('No subcommand provided. Use "up".');
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
switch (subcommand) {
|
|
151
|
-
case 'up': {
|
|
152
|
-
try {
|
|
153
|
-
ensureCwd(args.cwd || process.cwd());
|
|
154
|
-
const promptAnswers = await prompter.prompt(args, questions);
|
|
155
|
-
const server = new knative_job_service_1.KnativeJobsSvc(buildKnativeJobsSvcOptions(promptAnswers));
|
|
156
|
-
await server.start();
|
|
157
|
-
}
|
|
158
|
-
catch (error) {
|
|
159
|
-
await (0, inquirerer_1.cliExitWithError)(`Failed to start jobs runtime: ${error.message}`);
|
|
160
|
-
}
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
default:
|
|
164
|
-
console.log(jobsUsageText);
|
|
165
|
-
await (0, inquirerer_1.cliExitWithError)(`Unknown subcommand: ${subcommand}. Use "up".`);
|
|
166
|
-
}
|
|
167
|
-
};
|
package/esm/commands/jobs.js
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'fs';
|
|
2
|
-
import { resolve } from 'path';
|
|
3
|
-
import { KnativeJobsSvc } from '@constructive-io/knative-job-service';
|
|
4
|
-
import { cliExitWithError, extractFirst } from 'inquirerer';
|
|
5
|
-
const jobsUsageText = `
|
|
6
|
-
Constructive Jobs:
|
|
7
|
-
|
|
8
|
-
cnc jobs <subcommand> [OPTIONS]
|
|
9
|
-
|
|
10
|
-
Start or manage Constructive jobs services.
|
|
11
|
-
|
|
12
|
-
Subcommands:
|
|
13
|
-
up Start jobs runtime (jobs + functions)
|
|
14
|
-
|
|
15
|
-
Options:
|
|
16
|
-
--help, -h Show this help message
|
|
17
|
-
--cwd <directory> Working directory (default: current directory)
|
|
18
|
-
--with-jobs-server Enable jobs server (default: disabled; flag-only)
|
|
19
|
-
--functions <list> Comma-separated functions, optionally with ports (e.g. "fn=8080")
|
|
20
|
-
|
|
21
|
-
Examples:
|
|
22
|
-
cnc jobs up
|
|
23
|
-
cnc jobs up --cwd /path/to/constructive
|
|
24
|
-
cnc jobs up --with-jobs-server --functions send-email,send-verification-link=8082
|
|
25
|
-
`;
|
|
26
|
-
const questions = [
|
|
27
|
-
{
|
|
28
|
-
name: 'withJobsServer',
|
|
29
|
-
alias: 'with-jobs-server',
|
|
30
|
-
message: 'Enable jobs server?',
|
|
31
|
-
type: 'confirm',
|
|
32
|
-
required: false,
|
|
33
|
-
default: false,
|
|
34
|
-
useDefault: true
|
|
35
|
-
}
|
|
36
|
-
];
|
|
37
|
-
const ensureCwd = (cwd) => {
|
|
38
|
-
const resolved = resolve(cwd);
|
|
39
|
-
if (!existsSync(resolved)) {
|
|
40
|
-
throw new Error(`Working directory does not exist: ${resolved}`);
|
|
41
|
-
}
|
|
42
|
-
process.chdir(resolved);
|
|
43
|
-
return resolved;
|
|
44
|
-
};
|
|
45
|
-
const parseFunctionsArg = (value) => {
|
|
46
|
-
if (value === undefined)
|
|
47
|
-
return undefined;
|
|
48
|
-
const values = Array.isArray(value) ? value : [value];
|
|
49
|
-
const tokens = [];
|
|
50
|
-
for (const value of values) {
|
|
51
|
-
if (value === true) {
|
|
52
|
-
tokens.push('all');
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
if (value === false || value === undefined || value === null)
|
|
56
|
-
continue;
|
|
57
|
-
const raw = String(value);
|
|
58
|
-
raw
|
|
59
|
-
.split(',')
|
|
60
|
-
.map((part) => part.trim())
|
|
61
|
-
.filter(Boolean)
|
|
62
|
-
.forEach((part) => tokens.push(part));
|
|
63
|
-
}
|
|
64
|
-
if (!tokens.length) {
|
|
65
|
-
return { mode: 'list', names: [], ports: {} };
|
|
66
|
-
}
|
|
67
|
-
const hasAll = tokens.some((token) => {
|
|
68
|
-
const normalized = token.trim().toLowerCase();
|
|
69
|
-
return normalized === 'all' || normalized === '*';
|
|
70
|
-
});
|
|
71
|
-
if (hasAll) {
|
|
72
|
-
if (tokens.length > 1) {
|
|
73
|
-
throw new Error('Use "all" without other function names.');
|
|
74
|
-
}
|
|
75
|
-
return { mode: 'all', names: [], ports: {} };
|
|
76
|
-
}
|
|
77
|
-
const names = [];
|
|
78
|
-
const ports = {};
|
|
79
|
-
for (const token of tokens) {
|
|
80
|
-
const trimmed = token.trim();
|
|
81
|
-
if (!trimmed)
|
|
82
|
-
continue;
|
|
83
|
-
const separatorIndex = trimmed.search(/[:=]/);
|
|
84
|
-
if (separatorIndex === -1) {
|
|
85
|
-
names.push(trimmed);
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
const name = trimmed.slice(0, separatorIndex).trim();
|
|
89
|
-
const portText = trimmed.slice(separatorIndex + 1).trim();
|
|
90
|
-
if (!name) {
|
|
91
|
-
throw new Error(`Missing function name in "${token}".`);
|
|
92
|
-
}
|
|
93
|
-
if (!portText) {
|
|
94
|
-
throw new Error(`Missing port for function "${name}".`);
|
|
95
|
-
}
|
|
96
|
-
const port = Number(portText);
|
|
97
|
-
if (!Number.isFinite(port) || port <= 0) {
|
|
98
|
-
throw new Error(`Invalid port "${portText}" for function "${name}".`);
|
|
99
|
-
}
|
|
100
|
-
names.push(name);
|
|
101
|
-
ports[name] = port;
|
|
102
|
-
}
|
|
103
|
-
const uniqueNames = [];
|
|
104
|
-
const seen = new Set();
|
|
105
|
-
for (const name of names) {
|
|
106
|
-
if (seen.has(name))
|
|
107
|
-
continue;
|
|
108
|
-
seen.add(name);
|
|
109
|
-
uniqueNames.push(name);
|
|
110
|
-
}
|
|
111
|
-
return { mode: 'list', names: uniqueNames, ports };
|
|
112
|
-
};
|
|
113
|
-
const buildKnativeJobsSvcOptions = (args) => {
|
|
114
|
-
const parsedFunctions = parseFunctionsArg(args.functions);
|
|
115
|
-
let functions;
|
|
116
|
-
if (parsedFunctions) {
|
|
117
|
-
if (parsedFunctions.mode === 'all') {
|
|
118
|
-
functions = { enabled: true };
|
|
119
|
-
}
|
|
120
|
-
else if (parsedFunctions.names.length) {
|
|
121
|
-
const services = parsedFunctions.names.map((name) => ({
|
|
122
|
-
name: name,
|
|
123
|
-
port: parsedFunctions.ports[name]
|
|
124
|
-
}));
|
|
125
|
-
functions = { enabled: true, services };
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
functions = undefined;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return {
|
|
132
|
-
jobs: { enabled: args.withJobsServer === true },
|
|
133
|
-
functions
|
|
134
|
-
};
|
|
135
|
-
};
|
|
136
|
-
export default async (argv, prompter, _options) => {
|
|
137
|
-
if (argv.help || argv.h) {
|
|
138
|
-
console.log(jobsUsageText);
|
|
139
|
-
process.exit(0);
|
|
140
|
-
}
|
|
141
|
-
const { first: subcommand, newArgv } = extractFirst(argv);
|
|
142
|
-
const args = newArgv;
|
|
143
|
-
if (!subcommand) {
|
|
144
|
-
console.log(jobsUsageText);
|
|
145
|
-
await cliExitWithError('No subcommand provided. Use "up".');
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
switch (subcommand) {
|
|
149
|
-
case 'up': {
|
|
150
|
-
try {
|
|
151
|
-
ensureCwd(args.cwd || process.cwd());
|
|
152
|
-
const promptAnswers = await prompter.prompt(args, questions);
|
|
153
|
-
const server = new KnativeJobsSvc(buildKnativeJobsSvcOptions(promptAnswers));
|
|
154
|
-
await server.start();
|
|
155
|
-
}
|
|
156
|
-
catch (error) {
|
|
157
|
-
await cliExitWithError(`Failed to start jobs runtime: ${error.message}`);
|
|
158
|
-
}
|
|
159
|
-
break;
|
|
160
|
-
}
|
|
161
|
-
default:
|
|
162
|
-
console.log(jobsUsageText);
|
|
163
|
-
await cliExitWithError(`Unknown subcommand: ${subcommand}. Use "up".`);
|
|
164
|
-
}
|
|
165
|
-
};
|