@constructive-io/cli 0.0.3 → 5.1.1

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.
Files changed (130) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +346 -153
  3. package/commands/{analyze.d.ts → codegen.d.ts} +2 -2
  4. package/commands/codegen.js +131 -0
  5. package/commands/explorer.js +94 -0
  6. package/commands/get-graphql-schema.js +73 -0
  7. package/commands/server.js +187 -0
  8. package/commands.d.ts +0 -1
  9. package/commands.js +42 -61
  10. package/esm/commands/codegen.js +126 -0
  11. package/esm/commands/explorer.js +92 -0
  12. package/esm/commands/get-graphql-schema.js +71 -0
  13. package/esm/commands/server.js +185 -0
  14. package/esm/commands.js +41 -59
  15. package/esm/index.js +16 -36
  16. package/esm/utils/display.js +26 -23
  17. package/esm/utils/index.js +3 -6
  18. package/index.d.ts +0 -22
  19. package/index.js +16 -72
  20. package/package.json +50 -25
  21. package/utils/display.d.ts +1 -1
  22. package/utils/display.js +26 -23
  23. package/utils/index.d.ts +3 -6
  24. package/utils/index.js +7 -20
  25. package/commands/add.d.ts +0 -7
  26. package/commands/add.js +0 -86
  27. package/commands/admin-users/add.d.ts +0 -4
  28. package/commands/admin-users/add.js +0 -89
  29. package/commands/admin-users/bootstrap.d.ts +0 -4
  30. package/commands/admin-users/bootstrap.js +0 -50
  31. package/commands/admin-users/remove.d.ts +0 -4
  32. package/commands/admin-users/remove.js +0 -82
  33. package/commands/admin-users.d.ts +0 -4
  34. package/commands/admin-users.js +0 -68
  35. package/commands/analyze.js +0 -21
  36. package/commands/clear.d.ts +0 -3
  37. package/commands/clear.js +0 -59
  38. package/commands/deploy.d.ts +0 -4
  39. package/commands/deploy.js +0 -146
  40. package/commands/docker.d.ts +0 -3
  41. package/commands/docker.js +0 -194
  42. package/commands/env.d.ts +0 -4
  43. package/commands/env.js +0 -124
  44. package/commands/export.js +0 -129
  45. package/commands/extension.js +0 -48
  46. package/commands/init/index.d.ts +0 -7
  47. package/commands/init/index.js +0 -47
  48. package/commands/init/module.d.ts +0 -4
  49. package/commands/init/module.js +0 -71
  50. package/commands/init/workspace.d.ts +0 -4
  51. package/commands/init/workspace.js +0 -52
  52. package/commands/install.d.ts +0 -4
  53. package/commands/install.js +0 -37
  54. package/commands/kill.js +0 -107
  55. package/commands/migrate/deps.d.ts +0 -4
  56. package/commands/migrate/deps.js +0 -186
  57. package/commands/migrate/init.d.ts +0 -4
  58. package/commands/migrate/init.js +0 -65
  59. package/commands/migrate/list.d.ts +0 -4
  60. package/commands/migrate/list.js +0 -85
  61. package/commands/migrate/status.d.ts +0 -4
  62. package/commands/migrate/status.js +0 -94
  63. package/commands/migrate.d.ts +0 -4
  64. package/commands/migrate.js +0 -69
  65. package/commands/package.d.ts +0 -3
  66. package/commands/package.js +0 -65
  67. package/commands/plan.d.ts +0 -3
  68. package/commands/plan.js +0 -62
  69. package/commands/remove.d.ts +0 -3
  70. package/commands/remove.js +0 -42
  71. package/commands/rename.d.ts +0 -4
  72. package/commands/rename.js +0 -35
  73. package/commands/revert.d.ts +0 -3
  74. package/commands/revert.js +0 -107
  75. package/commands/tag.d.ts +0 -6
  76. package/commands/tag.js +0 -168
  77. package/commands/verify.d.ts +0 -3
  78. package/commands/verify.js +0 -85
  79. package/dist/README.md +0 -412
  80. package/dist/package.json +0 -64
  81. package/esm/commands/add.js +0 -51
  82. package/esm/commands/admin-users/add.js +0 -87
  83. package/esm/commands/admin-users/bootstrap.js +0 -48
  84. package/esm/commands/admin-users/remove.js +0 -80
  85. package/esm/commands/admin-users.js +0 -63
  86. package/esm/commands/analyze.js +0 -16
  87. package/esm/commands/clear.js +0 -54
  88. package/esm/commands/deploy.js +0 -144
  89. package/esm/commands/docker.js +0 -192
  90. package/esm/commands/env.js +0 -122
  91. package/esm/commands/export.js +0 -127
  92. package/esm/commands/extension.js +0 -46
  93. package/esm/commands/init/index.js +0 -42
  94. package/esm/commands/init/module.js +0 -68
  95. package/esm/commands/init/workspace.js +0 -46
  96. package/esm/commands/install.js +0 -35
  97. package/esm/commands/kill.js +0 -105
  98. package/esm/commands/migrate/deps.js +0 -184
  99. package/esm/commands/migrate/init.js +0 -63
  100. package/esm/commands/migrate/list.js +0 -83
  101. package/esm/commands/migrate/status.js +0 -92
  102. package/esm/commands/migrate.js +0 -64
  103. package/esm/commands/package.js +0 -63
  104. package/esm/commands/plan.js +0 -60
  105. package/esm/commands/remove.js +0 -40
  106. package/esm/commands/rename.js +0 -30
  107. package/esm/commands/revert.js +0 -105
  108. package/esm/commands/tag.js +0 -133
  109. package/esm/commands/verify.js +0 -83
  110. package/esm/package.js +0 -26
  111. package/esm/utils/argv.js +0 -92
  112. package/esm/utils/cli-error.js +0 -48
  113. package/esm/utils/database.js +0 -78
  114. package/esm/utils/deployed-changes.js +0 -68
  115. package/esm/utils/module-utils.js +0 -51
  116. package/package.d.ts +0 -1
  117. package/package.js +0 -29
  118. package/utils/argv.d.ts +0 -46
  119. package/utils/argv.js +0 -100
  120. package/utils/cli-error.d.ts +0 -8
  121. package/utils/cli-error.js +0 -52
  122. package/utils/database.d.ts +0 -21
  123. package/utils/database.js +0 -83
  124. package/utils/deployed-changes.d.ts +0 -4
  125. package/utils/deployed-changes.js +0 -72
  126. package/utils/module-utils.d.ts +0 -8
  127. package/utils/module-utils.js +0 -54
  128. /package/commands/{export.d.ts → explorer.d.ts} +0 -0
  129. /package/commands/{extension.d.ts → get-graphql-schema.d.ts} +0 -0
  130. /package/commands/{kill.d.ts → server.d.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import { Inquirerer } from 'inquirerer';
1
+ import { CLIOptions, Inquirerer } from 'inquirerer';
2
2
  import { ParsedArgs } from 'minimist';
3
- declare const _default: (argv: Partial<ParsedArgs>, _prompter: Inquirerer) => Promise<void>;
3
+ declare const _default: (argv: Partial<ParsedArgs>, _prompter: Inquirerer, _options: CLIOptions) => Promise<void>;
4
4
  export default _default;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = require("fs");
7
+ const path_1 = require("path");
8
+ const js_yaml_1 = __importDefault(require("js-yaml"));
9
+ const graphql_codegen_1 = require("@constructive-io/graphql-codegen");
10
+ const graphql_server_1 = require("@constructive-io/graphql-server");
11
+ const usage = `
12
+ Constructive GraphQL Codegen:
13
+
14
+ cnc codegen [OPTIONS]
15
+
16
+ Options:
17
+ --help, -h Show this help message
18
+ --config <path> Config file (json|yaml)
19
+ --schema <path> Schema SDL file path
20
+ --endpoint <url> GraphQL endpoint to fetch schema via introspection
21
+ --headerHost <host> Optional Host header to send with endpoint requests
22
+ --auth <token> Optional Authorization header value (e.g., "Bearer 123")
23
+ --header "Name: Value" Optional HTTP header; repeat to add multiple headers
24
+ --out <dir> Output root directory (default: graphql/codegen/dist)
25
+ --format <gql|ts> Document format (default: gql)
26
+ --convention <style> Filename convention (dashed|underscore|camelcase|camelUpper)
27
+ --emitTypes <bool> Emit types (default: true)
28
+ --emitOperations <bool> Emit operations (default: true)
29
+ --emitSdk <bool> Emit sdk (default: true)
30
+ --allowQuery <name> Only generate for this root field (repeatable)
31
+ --excludeQuery <name> Exclude this root field (repeatable)
32
+ --excludePattern <regex> Exclude fields matching regex (repeatable)
33
+ `;
34
+ function parseBool(v, d) {
35
+ if (v === undefined)
36
+ return d;
37
+ if (typeof v === 'boolean')
38
+ return v;
39
+ const s = String(v).toLowerCase();
40
+ if (s === 'true')
41
+ return true;
42
+ if (s === 'false')
43
+ return false;
44
+ return d;
45
+ }
46
+ async function loadConfig(path) {
47
+ const content = await fs_1.promises.readFile(path, 'utf8');
48
+ if (/\.ya?ml$/i.test(path))
49
+ return js_yaml_1.default.load(content);
50
+ if (/\.json$/i.test(path))
51
+ return JSON.parse(content);
52
+ return {};
53
+ }
54
+ exports.default = async (argv, _prompter, _options) => {
55
+ if (argv.help || argv.h) {
56
+ console.log(usage);
57
+ process.exit(0);
58
+ }
59
+ const cwd = argv.cwd || process.cwd();
60
+ const configPath = argv.config || '';
61
+ let fileOpts = {};
62
+ if (configPath)
63
+ fileOpts = await loadConfig(configPath);
64
+ const overrides = {};
65
+ if (argv.schema)
66
+ overrides.input = { ...(overrides.input || {}), schema: String(argv.schema) };
67
+ if (argv.endpoint)
68
+ overrides.input = { ...(overrides.input || {}), endpoint: String(argv.endpoint) };
69
+ const headerHost = argv.headerHost ?? '';
70
+ const auth = argv.auth ?? '';
71
+ const headerArg = argv.header;
72
+ const headerList = Array.isArray(headerArg) ? headerArg : headerArg ? [headerArg] : [];
73
+ const headers = {};
74
+ if (auth)
75
+ headers['Authorization'] = auth;
76
+ for (const h of headerList) {
77
+ const idx = typeof h === 'string' ? h.indexOf(':') : -1;
78
+ if (idx <= 0)
79
+ continue;
80
+ const name = h.slice(0, idx).trim();
81
+ const value = h.slice(idx + 1).trim();
82
+ if (!name)
83
+ continue;
84
+ headers[name] = value;
85
+ }
86
+ if (Object.keys(headers).length)
87
+ overrides.input = { ...(overrides.input || {}), headers };
88
+ if (argv.out)
89
+ overrides.output = { ...(overrides.output || {}), root: String(argv.out) };
90
+ if (argv.format)
91
+ overrides.documents = { ...(overrides.documents || {}), format: String(argv.format) };
92
+ if (argv.convention)
93
+ overrides.documents = { ...(overrides.documents || {}), convention: String(argv.convention) };
94
+ const allowQueryArg = argv.allowQuery;
95
+ const excludeQueryArg = argv.excludeQuery;
96
+ const excludePatternArg = argv.excludePattern;
97
+ const allowQueries = Array.isArray(allowQueryArg) ? allowQueryArg : allowQueryArg ? [String(allowQueryArg)] : [];
98
+ const excludeQueries = Array.isArray(excludeQueryArg) ? excludeQueryArg : excludeQueryArg ? [String(excludeQueryArg)] : [];
99
+ const excludePatterns = Array.isArray(excludePatternArg) ? excludePatternArg : excludePatternArg ? [String(excludePatternArg)] : [];
100
+ if (allowQueries.length || excludeQueries.length || excludePatterns.length) {
101
+ overrides.documents = { ...(overrides.documents || {}), allowQueries, excludeQueries, excludePatterns };
102
+ }
103
+ const emitTypes = parseBool(argv.emitTypes, true);
104
+ const emitOperations = parseBool(argv.emitOperations, true);
105
+ const emitSdk = parseBool(argv.emitSdk, true);
106
+ overrides.features = { emitTypes, emitOperations, emitSdk };
107
+ const merged = (0, graphql_codegen_1.mergeGraphQLCodegenOptions)(graphql_codegen_1.defaultGraphQLCodegenOptions, fileOpts);
108
+ const finalOptions = (0, graphql_codegen_1.mergeGraphQLCodegenOptions)(merged, overrides);
109
+ if (finalOptions.input.endpoint && headerHost) {
110
+ const opts = {};
111
+ if (headerHost)
112
+ opts.headerHost = headerHost;
113
+ if (auth)
114
+ opts.auth = auth;
115
+ if (Object.keys(headers).length)
116
+ opts.headers = headers;
117
+ const sdl = await graphql_server_1.fetchEndpointSchemaSDL(String(finalOptions.input.endpoint), opts);
118
+ const tmpSchemaPath = (0, path_1.join)(cwd, '.constructive-codegen-schema.graphql');
119
+ await fs_1.promises.writeFile(tmpSchemaPath, sdl, 'utf8');
120
+ finalOptions.input.schema = tmpSchemaPath;
121
+ finalOptions.input.endpoint = '';
122
+ }
123
+ const hasSchema = !!finalOptions.input.schema && String(finalOptions.input.schema).trim() !== '';
124
+ const hasEndpoint = !!finalOptions.input.endpoint && String(finalOptions.input.endpoint).trim() !== '';
125
+ if (!hasSchema && !hasEndpoint) {
126
+ console.error('Missing --schema or --endpoint or config.input');
127
+ process.exit(1);
128
+ }
129
+ const result = await (0, graphql_codegen_1.runCodegen)(finalOptions, cwd);
130
+ console.log(`Generated at ${(0, path_1.join)(result.root)}`);
131
+ };
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const graphql_env_1 = require("@constructive-io/graphql-env");
4
+ const graphql_explorer_1 = require("@constructive-io/graphql-explorer");
5
+ const logger_1 = require("@pgpmjs/logger");
6
+ const log = new logger_1.Logger('explorer');
7
+ const explorerUsageText = `
8
+ Constructive GraphQL Explorer:
9
+
10
+ cnc explorer [OPTIONS]
11
+
12
+ Launch GraphiQL explorer interface.
13
+
14
+ Options:
15
+ --help, -h Show this help message
16
+ --port <number> Server port (default: 5555)
17
+ --origin <url> CORS origin URL (default: http://localhost:3000)
18
+ --simpleInflection Use simple inflection (default: true)
19
+ --oppositeBaseNames Use opposite base names (default: false)
20
+ --postgis Enable PostGIS extension (default: true)
21
+ --cwd <directory> Working directory (default: current directory)
22
+
23
+ Examples:
24
+ cnc explorer Launch explorer with defaults
25
+ cnc explorer --origin http://localhost:4000 Launch explorer with custom origin
26
+ `;
27
+ const questions = [
28
+ {
29
+ name: 'simpleInflection',
30
+ message: 'Use simple inflection?',
31
+ type: 'confirm',
32
+ required: false,
33
+ default: true,
34
+ useDefault: true
35
+ },
36
+ {
37
+ name: 'oppositeBaseNames',
38
+ message: 'Use opposite base names?',
39
+ type: 'confirm',
40
+ required: false,
41
+ default: false,
42
+ useDefault: true
43
+ },
44
+ {
45
+ name: 'postgis',
46
+ message: 'Enable PostGIS extension?',
47
+ type: 'confirm',
48
+ required: false,
49
+ default: true,
50
+ useDefault: true
51
+ },
52
+ {
53
+ name: 'port',
54
+ message: 'Development server port',
55
+ type: 'number',
56
+ required: false,
57
+ default: 5555,
58
+ useDefault: true
59
+ },
60
+ {
61
+ name: 'origin',
62
+ message: 'CORS origin URL',
63
+ type: 'text',
64
+ required: false,
65
+ default: 'http://localhost:3000',
66
+ useDefault: true
67
+ }
68
+ ];
69
+ exports.default = async (argv, prompter, _options) => {
70
+ // Show usage if explicitly requested
71
+ if (argv.help || argv.h) {
72
+ console.log(explorerUsageText);
73
+ process.exit(0);
74
+ }
75
+ log.info('🔧 Constructive GraphQL Explorer Configuration:\n');
76
+ const { oppositeBaseNames, origin, port, postgis, simpleInflection } = await prompter.prompt(argv, questions);
77
+ const options = (0, graphql_env_1.getEnvOptions)({
78
+ features: {
79
+ oppositeBaseNames,
80
+ simpleInflection,
81
+ postgis
82
+ },
83
+ server: {
84
+ origin,
85
+ port
86
+ }
87
+ });
88
+ log.success('✅ Selected Configuration:');
89
+ for (const [key, value] of Object.entries(options)) {
90
+ log.debug(`${key}: ${JSON.stringify(value)}`);
91
+ }
92
+ log.success('🚀 Launching Explorer...\n');
93
+ (0, graphql_explorer_1.GraphQLExplorer)(options);
94
+ };
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs_1 = require("fs");
4
+ const graphql_server_1 = require("@constructive-io/graphql-server");
5
+ const usage = `
6
+ Constructive Get GraphQL Schema:
7
+
8
+ cnc get-graphql-schema [OPTIONS]
9
+
10
+ Options:
11
+ --help, -h Show this help message
12
+ --database <name> Database name (default: constructive)
13
+ --schemas <list> Comma-separated schemas to include
14
+ --endpoint <url> GraphQL endpoint to fetch schema via introspection
15
+ --headerHost <host> Optional Host header to send with endpoint requests
16
+ --auth <token> Optional Authorization header value (e.g., "Bearer 123")
17
+ --header "Name: Value" Optional HTTP header; repeat to add multiple headers
18
+ --out <path> Output file path (default: print to stdout)
19
+ `;
20
+ const defaultSchemas = [
21
+ 'collections_public',
22
+ 'dashboard_public'
23
+ ];
24
+ exports.default = async (argv, prompter, _options) => {
25
+ if (argv.help || argv.h) {
26
+ console.log(usage);
27
+ process.exit(0);
28
+ }
29
+ const endpoint = argv.endpoint ?? '';
30
+ const headerHost = argv.headerHost ?? '';
31
+ const auth = argv.auth ?? '';
32
+ const database = argv.database ?? 'constructive';
33
+ const schemasArg = argv.schemas ?? defaultSchemas.join(',');
34
+ const out = argv.out ?? '';
35
+ const headerArg = argv.header;
36
+ const headerList = Array.isArray(headerArg) ? headerArg : headerArg ? [headerArg] : [];
37
+ const headers = {};
38
+ for (const h of headerList) {
39
+ const idx = typeof h === 'string' ? h.indexOf(':') : -1;
40
+ if (idx <= 0)
41
+ continue;
42
+ const name = h.slice(0, idx).trim();
43
+ const value = h.slice(idx + 1).trim();
44
+ if (!name)
45
+ continue;
46
+ headers[name] = value;
47
+ }
48
+ const schemas = schemasArg.split(',').map(s => s.trim()).filter(Boolean);
49
+ let sdl;
50
+ if (endpoint) {
51
+ const opts = {};
52
+ if (headerHost)
53
+ opts.headerHost = headerHost;
54
+ if (auth)
55
+ opts.auth = auth;
56
+ if (Object.keys(headers).length)
57
+ opts.headers = headers;
58
+ sdl = await graphql_server_1.fetchEndpointSchemaSDL(endpoint, opts);
59
+ }
60
+ else {
61
+ // The server package already depends on postgraphile and graphql,
62
+ // and exporting a reusable programmatic builder from there
63
+ // avoids adding new dependencies to cli and prevents duplication.
64
+ sdl = await (0, graphql_server_1.buildSchemaSDL)({ database, schemas });
65
+ }
66
+ if (out) {
67
+ await fs_1.promises.writeFile(out, sdl, 'utf8');
68
+ console.log(`Wrote schema SDL to ${out}`);
69
+ }
70
+ else {
71
+ process.stdout.write(sdl + '\n');
72
+ }
73
+ };
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const graphql_env_1 = require("@constructive-io/graphql-env");
4
+ const logger_1 = require("@pgpmjs/logger");
5
+ const graphql_server_1 = require("@constructive-io/graphql-server");
6
+ const pg_cache_1 = require("pg-cache");
7
+ const log = new logger_1.Logger('server');
8
+ const serverUsageText = `
9
+ Constructive GraphQL Server:
10
+
11
+ cnc server [OPTIONS]
12
+
13
+ Start Constructive GraphQL development server.
14
+
15
+ Options:
16
+ --help, -h Show this help message
17
+ --port <number> Server port (default: 5555)
18
+ --simpleInflection Use simple inflection (default: true)
19
+ --oppositeBaseNames Use opposite base names (default: false)
20
+ --postgis Enable PostGIS extension (default: true)
21
+ --metaApi Enable Meta API (default: true)
22
+ --cwd <directory> Working directory (default: current directory)
23
+
24
+ Examples:
25
+ cnc server Start server with defaults
26
+ cnc server --port 8080 Start server on custom port
27
+ cnc server --no-postgis Start server without PostGIS
28
+ `;
29
+ const questions = [
30
+ {
31
+ name: 'simpleInflection',
32
+ message: 'Use simple inflection?',
33
+ type: 'confirm',
34
+ required: false,
35
+ default: true,
36
+ useDefault: true
37
+ },
38
+ {
39
+ name: 'oppositeBaseNames',
40
+ message: 'Use opposite base names?',
41
+ type: 'confirm',
42
+ required: false,
43
+ default: false,
44
+ useDefault: true
45
+ },
46
+ {
47
+ name: 'postgis',
48
+ message: 'Enable PostGIS extension?',
49
+ type: 'confirm',
50
+ required: false,
51
+ default: true,
52
+ useDefault: true
53
+ },
54
+ {
55
+ name: 'metaApi',
56
+ message: 'Enable Meta API?',
57
+ type: 'confirm',
58
+ required: false,
59
+ default: true,
60
+ useDefault: true
61
+ },
62
+ {
63
+ name: 'origin',
64
+ message: 'CORS origin (exact URL or *)',
65
+ type: 'text',
66
+ required: false,
67
+ // no default to avoid accidentally opening up CORS; pass explicitly or via env
68
+ },
69
+ {
70
+ name: 'port',
71
+ message: 'Development server port',
72
+ type: 'number',
73
+ required: false,
74
+ default: 5555,
75
+ useDefault: true
76
+ }
77
+ ];
78
+ exports.default = async (argv, prompter, _options) => {
79
+ // Show usage if explicitly requested
80
+ if (argv.help || argv.h) {
81
+ console.log(serverUsageText);
82
+ process.exit(0);
83
+ }
84
+ log.info('🔧 Constructive GraphQL Server Configuration:\n');
85
+ let selectedDb = process.env.PGDATABASE;
86
+ if (!selectedDb) {
87
+ const db = await (0, pg_cache_1.getPgPool)({ database: 'postgres' });
88
+ const result = await db.query(`
89
+ SELECT datname FROM pg_database
90
+ WHERE datistemplate = false AND datname NOT IN ('postgres')
91
+ AND datname !~ '^pg_'
92
+ ORDER BY datname;
93
+ `);
94
+ const dbChoices = result.rows.map(row => row.datname);
95
+ const { database } = await prompter.prompt(argv, [
96
+ {
97
+ type: 'autocomplete',
98
+ name: 'database',
99
+ message: 'Select the database to use',
100
+ options: dbChoices,
101
+ required: true
102
+ }
103
+ ]);
104
+ selectedDb = database;
105
+ log.info(`📌 Using database: "${selectedDb}"`);
106
+ }
107
+ const { oppositeBaseNames, port, postgis, simpleInflection, metaApi, origin } = await prompter.prompt(argv, questions);
108
+ // Warn when passing CORS override via CLI, especially in production
109
+ if (origin && origin.trim().length) {
110
+ const env = (process.env.NODE_ENV || 'development').toLowerCase();
111
+ if (env === 'production') {
112
+ if (origin.trim() === '*') {
113
+ log.warn('CORS wildcard ("*") provided via --origin in production: this effectively disables CORS and is not recommended. Prefer per-API CORS via meta schema.');
114
+ }
115
+ else {
116
+ log.warn(`CORS override (origin=${origin.trim()}) provided via --origin in production. Prefer per-API CORS via meta schema.`);
117
+ }
118
+ }
119
+ }
120
+ let selectedSchemas = [];
121
+ let authRole;
122
+ let roleName;
123
+ if (!metaApi) {
124
+ const db = await (0, pg_cache_1.getPgPool)({ database: selectedDb });
125
+ const result = await db.query(`
126
+ SELECT nspname
127
+ FROM pg_namespace
128
+ WHERE nspname NOT IN ('pg_catalog', 'information_schema')
129
+ ORDER BY nspname;
130
+ `);
131
+ const schemaChoices = result.rows.map(row => ({
132
+ name: row.nspname,
133
+ value: row.nspname,
134
+ selected: true
135
+ }));
136
+ const { schemas } = await prompter.prompt(argv, [
137
+ {
138
+ type: 'checkbox',
139
+ name: 'schemas',
140
+ message: 'Select schemas to expose',
141
+ options: schemaChoices,
142
+ required: true
143
+ }
144
+ ]);
145
+ selectedSchemas = schemas.filter(s => s.selected).map(s => s.value);
146
+ const { authRole: selectedAuthRole, roleName: selectedRoleName } = await prompter.prompt(argv, [
147
+ {
148
+ type: 'autocomplete',
149
+ name: 'authRole',
150
+ message: 'Select the authentication role',
151
+ options: ['postgres', 'authenticated', 'anonymous'],
152
+ required: true
153
+ },
154
+ {
155
+ type: 'autocomplete',
156
+ name: 'roleName',
157
+ message: 'Enter the default role name:',
158
+ options: ['postgres', 'authenticated', 'anonymous'],
159
+ required: true
160
+ }
161
+ ]);
162
+ authRole = selectedAuthRole;
163
+ roleName = selectedRoleName;
164
+ }
165
+ const options = (0, graphql_env_1.getEnvOptions)({
166
+ pg: { database: selectedDb },
167
+ features: {
168
+ oppositeBaseNames,
169
+ simpleInflection,
170
+ postgis
171
+ },
172
+ api: {
173
+ enableMetaApi: metaApi,
174
+ ...(metaApi === false && { exposedSchemas: selectedSchemas, authRole, roleName })
175
+ },
176
+ server: {
177
+ port,
178
+ ...(origin ? { origin } : {})
179
+ }
180
+ });
181
+ log.success('✅ Selected Configuration:');
182
+ for (const [key, value] of Object.entries(options)) {
183
+ log.debug(`${key}: ${JSON.stringify(value)}`);
184
+ }
185
+ log.success('🚀 Launching Server...\n');
186
+ (0, graphql_server_1.GraphQLServer)(options);
187
+ };
package/commands.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { CLIOptions, Inquirerer } from 'inquirerer';
2
2
  import { ParsedArgs } from 'minimist';
3
- export declare const createConstructiveCommandMap: (skipPgTeardown?: boolean) => Record<string, Function>;
4
3
  export declare const commands: (argv: Partial<ParsedArgs>, prompter: Inquirerer, options: CLIOptions & {
5
4
  skipPgTeardown?: boolean;
6
5
  }) => Promise<Partial<ParsedArgs>>;
package/commands.js CHANGED
@@ -3,83 +3,63 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.commands = exports.createConstructiveCommandMap = void 0;
7
- const pg_cache_1 = require("pg-cache");
8
- const add_1 = __importDefault(require("./commands/add"));
9
- const admin_users_1 = __importDefault(require("./commands/admin-users"));
10
- const analyze_1 = __importDefault(require("./commands/analyze"));
11
- const clear_1 = __importDefault(require("./commands/clear"));
12
- const deploy_1 = __importDefault(require("./commands/deploy"));
13
- const docker_1 = __importDefault(require("./commands/docker"));
14
- const env_1 = __importDefault(require("./commands/env"));
15
- const export_1 = __importDefault(require("./commands/export"));
16
- const extension_1 = __importDefault(require("./commands/extension"));
17
- const init_1 = __importDefault(require("./commands/init"));
18
- const install_1 = __importDefault(require("./commands/install"));
19
- const kill_1 = __importDefault(require("./commands/kill"));
20
- const migrate_1 = __importDefault(require("./commands/migrate"));
21
- const package_1 = __importDefault(require("./commands/package"));
22
- const plan_1 = __importDefault(require("./commands/plan"));
23
- const remove_1 = __importDefault(require("./commands/remove"));
24
- const rename_1 = __importDefault(require("./commands/rename"));
25
- const revert_1 = __importDefault(require("./commands/revert"));
26
- const tag_1 = __importDefault(require("./commands/tag"));
27
- const verify_1 = __importDefault(require("./commands/verify"));
28
- const package_2 = require("./package");
6
+ exports.commands = void 0;
7
+ const find_and_require_package_json_1 = require("find-and-require-package-json");
8
+ const pgpm_1 = require("pgpm");
9
+ const codegen_1 = __importDefault(require("./commands/codegen"));
10
+ const explorer_1 = __importDefault(require("./commands/explorer"));
11
+ const get_graphql_schema_1 = __importDefault(require("./commands/get-graphql-schema"));
12
+ const server_1 = __importDefault(require("./commands/server"));
29
13
  const utils_1 = require("./utils");
30
- const cli_error_1 = require("./utils/cli-error");
31
- const withPgTeardown = (fn, skipTeardown = false) => async (...args) => {
32
- try {
33
- await fn(...args);
34
- }
35
- finally {
36
- if (!skipTeardown) {
37
- await (0, pg_cache_1.teardownPgPools)();
38
- }
39
- }
40
- };
41
- const createConstructiveCommandMap = (skipPgTeardown = false) => {
42
- const pgt = (fn) => withPgTeardown(fn, skipPgTeardown);
14
+ const createCommandMap = (skipPgTeardown = false) => {
15
+ const pgpmCommands = (0, pgpm_1.createPgpmCommandMap)(skipPgTeardown);
43
16
  return {
44
- add: add_1.default,
45
- 'admin-users': pgt(admin_users_1.default),
46
- clear: pgt(clear_1.default),
47
- deploy: pgt(deploy_1.default),
48
- docker: docker_1.default,
49
- env: env_1.default,
50
- verify: pgt(verify_1.default),
51
- revert: pgt(revert_1.default),
52
- remove: pgt(remove_1.default),
53
- init: pgt(init_1.default),
54
- extension: pgt(extension_1.default),
55
- plan: pgt(plan_1.default),
56
- export: pgt(export_1.default),
57
- package: pgt(package_1.default),
58
- tag: pgt(tag_1.default),
59
- kill: pgt(kill_1.default),
60
- install: pgt(install_1.default),
61
- migrate: pgt(migrate_1.default),
62
- analyze: pgt(analyze_1.default),
63
- rename: pgt(rename_1.default)
17
+ ...pgpmCommands,
18
+ server: server_1.default,
19
+ explorer: explorer_1.default,
20
+ 'get-graphql-schema': get_graphql_schema_1.default,
21
+ codegen: codegen_1.default
64
22
  };
65
23
  };
66
- exports.createConstructiveCommandMap = createConstructiveCommandMap;
67
24
  const commands = async (argv, prompter, options) => {
25
+ let { first: command, newArgv } = (0, utils_1.extractFirst)(argv);
26
+ // Run update check early so it shows on help/version paths too
27
+ try {
28
+ const pkg = (0, find_and_require_package_json_1.findAndRequirePackageJson)(__dirname);
29
+ await (0, pgpm_1.checkForUpdates)({
30
+ command: command || 'help',
31
+ pkgName: pkg.name,
32
+ pkgVersion: pkg.version,
33
+ toolName: 'constructive',
34
+ key: pkg.name,
35
+ updateCommand: `Run npm i -g ${pkg.name}@latest to upgrade.`
36
+ });
37
+ }
38
+ catch {
39
+ // ignore update check failures
40
+ }
68
41
  if (argv.version || argv.v) {
69
- const pkg = (0, package_2.readAndParsePackageJson)();
42
+ const pkg = (0, find_and_require_package_json_1.findAndRequirePackageJson)(__dirname);
70
43
  console.log(pkg.version);
71
44
  process.exit(0);
72
45
  }
73
- let { first: command, newArgv } = (0, utils_1.extractFirst)(argv);
46
+ // Show usage if explicitly requested but no command specified
74
47
  if ((argv.help || argv.h || command === 'help') && !command) {
75
48
  console.log(utils_1.usageText);
76
49
  process.exit(0);
77
50
  }
51
+ // Show usage for help command specifically
78
52
  if (command === 'help') {
79
53
  console.log(utils_1.usageText);
80
54
  process.exit(0);
81
55
  }
82
- const commandMap = (0, exports.createConstructiveCommandMap)(options?.skipPgTeardown);
56
+ // Command-specific help for init
57
+ if (command === 'init' && (argv.help || argv.h)) {
58
+ console.log((0, pgpm_1.createInitUsageText)('constructive', 'Constructive'));
59
+ process.exit(0);
60
+ }
61
+ const commandMap = createCommandMap(options?.skipPgTeardown);
62
+ // Prompt if no command provided
83
63
  if (!command) {
84
64
  const answer = await prompter.prompt(argv, [
85
65
  {
@@ -91,6 +71,7 @@ const commands = async (argv, prompter, options) => {
91
71
  ]);
92
72
  command = answer.command;
93
73
  }
74
+ // Prompt for working directory
94
75
  newArgv = await prompter.prompt(newArgv, [
95
76
  {
96
77
  type: 'text',
@@ -104,7 +85,7 @@ const commands = async (argv, prompter, options) => {
104
85
  const commandFn = commandMap[command];
105
86
  if (!commandFn) {
106
87
  console.log(utils_1.usageText);
107
- await (0, cli_error_1.cliExitWithError)(`Unknown command: ${command}`);
88
+ await (0, utils_1.cliExitWithError)(`Unknown command: ${command}`);
108
89
  }
109
90
  await commandFn(newArgv, prompter, options);
110
91
  prompter.close();