@nocobase/cli 2.1.0-alpha.4 → 2.1.0-alpha.40

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 (211) hide show
  1. package/LICENSE.txt +107 -0
  2. package/README.md +393 -19
  3. package/README.zh-CN.md +343 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +135 -0
  6. package/bin/session-env.js +39 -0
  7. package/dist/commands/api/resource/create.js +15 -0
  8. package/dist/commands/api/resource/destroy.js +15 -0
  9. package/dist/commands/api/resource/get.js +15 -0
  10. package/dist/commands/api/resource/index.js +20 -0
  11. package/dist/commands/api/resource/list.js +16 -0
  12. package/dist/commands/api/resource/query.js +15 -0
  13. package/dist/commands/api/resource/update.js +15 -0
  14. package/dist/commands/app/down.js +301 -0
  15. package/dist/commands/app/logs.js +114 -0
  16. package/dist/commands/app/restart.js +158 -0
  17. package/dist/commands/app/start.js +305 -0
  18. package/dist/commands/app/stop.js +115 -0
  19. package/dist/commands/app/upgrade.js +636 -0
  20. package/dist/commands/backup/create.js +147 -0
  21. package/dist/commands/backup/index.js +20 -0
  22. package/dist/commands/backup/restore.js +105 -0
  23. package/{src/cli.js → dist/commands/build.js} +4 -11
  24. package/dist/commands/config/delete.js +30 -0
  25. package/dist/commands/config/get.js +29 -0
  26. package/dist/commands/config/index.js +20 -0
  27. package/dist/commands/config/list.js +29 -0
  28. package/dist/commands/config/set.js +35 -0
  29. package/dist/commands/db/check.js +240 -0
  30. package/dist/commands/db/logs.js +85 -0
  31. package/dist/commands/db/ps.js +60 -0
  32. package/dist/commands/db/shared.js +96 -0
  33. package/dist/commands/db/start.js +71 -0
  34. package/dist/commands/db/stop.js +71 -0
  35. package/{templates/plugin/src/client/models/index.ts → dist/commands/dev.js} +4 -4
  36. package/{src/commands/locale/react-js-cron/index.js → dist/commands/down.js} +3 -8
  37. package/dist/commands/download.js +13 -0
  38. package/dist/commands/env/add.js +366 -0
  39. package/dist/commands/env/auth.js +130 -0
  40. package/dist/commands/env/current.js +21 -0
  41. package/dist/commands/env/info.js +157 -0
  42. package/dist/commands/env/list.js +44 -0
  43. package/dist/commands/env/remove.js +84 -0
  44. package/dist/commands/env/shared.js +158 -0
  45. package/dist/commands/env/status.js +90 -0
  46. package/dist/commands/env/update.js +74 -0
  47. package/dist/commands/env/use.js +38 -0
  48. package/dist/commands/examples/prompts-stages.js +150 -0
  49. package/dist/commands/examples/prompts-test.js +181 -0
  50. package/dist/commands/init.js +1092 -0
  51. package/dist/commands/install.js +2378 -0
  52. package/dist/commands/license/activate.js +360 -0
  53. package/dist/commands/license/env.js +94 -0
  54. package/dist/commands/license/generate-id.js +108 -0
  55. package/dist/commands/license/id.js +70 -0
  56. package/dist/commands/license/index.js +20 -0
  57. package/dist/commands/license/plugins/clean.js +115 -0
  58. package/dist/commands/license/plugins/index.js +20 -0
  59. package/dist/commands/license/plugins/list.js +64 -0
  60. package/dist/commands/license/plugins/shared.js +325 -0
  61. package/dist/commands/license/plugins/sync.js +285 -0
  62. package/dist/commands/license/shared.js +423 -0
  63. package/dist/commands/license/status.js +64 -0
  64. package/dist/commands/logs.js +12 -0
  65. package/dist/commands/plugin/disable.js +86 -0
  66. package/dist/commands/plugin/enable.js +86 -0
  67. package/dist/commands/plugin/list.js +82 -0
  68. package/dist/commands/pm/disable.js +12 -0
  69. package/dist/commands/pm/enable.js +12 -0
  70. package/dist/commands/pm/list.js +12 -0
  71. package/dist/commands/restart.js +12 -0
  72. package/dist/commands/scaffold/migration.js +38 -0
  73. package/dist/commands/scaffold/plugin.js +37 -0
  74. package/dist/commands/self/check.js +71 -0
  75. package/dist/commands/self/index.js +20 -0
  76. package/dist/commands/self/update.js +95 -0
  77. package/dist/commands/session/id.js +24 -0
  78. package/dist/commands/session/remove.js +57 -0
  79. package/dist/commands/session/setup.js +62 -0
  80. package/dist/commands/skills/check.js +69 -0
  81. package/dist/commands/skills/index.js +20 -0
  82. package/dist/commands/skills/install.js +80 -0
  83. package/dist/commands/skills/remove.js +80 -0
  84. package/dist/commands/skills/update.js +87 -0
  85. package/dist/commands/source/build.js +58 -0
  86. package/dist/commands/source/dev.js +182 -0
  87. package/dist/commands/source/download.js +880 -0
  88. package/dist/commands/source/publish.js +109 -0
  89. package/dist/commands/source/registry/logs.js +70 -0
  90. package/dist/commands/source/registry/start.js +57 -0
  91. package/dist/commands/source/registry/status.js +33 -0
  92. package/dist/commands/source/registry/stop.js +48 -0
  93. package/dist/commands/source/test.js +477 -0
  94. package/dist/commands/start.js +12 -0
  95. package/dist/commands/stop.js +12 -0
  96. package/dist/commands/test.js +12 -0
  97. package/dist/commands/upgrade.js +12 -0
  98. package/dist/commands/v1.js +210 -0
  99. package/dist/generated/command-registry.js +133 -0
  100. package/dist/help/runtime-help.js +23 -0
  101. package/dist/lib/api-client.js +329 -0
  102. package/dist/lib/app-health.js +126 -0
  103. package/dist/lib/app-managed-resources.js +316 -0
  104. package/dist/lib/app-runtime.js +180 -0
  105. package/dist/lib/auth-store.js +368 -0
  106. package/dist/lib/backup.js +171 -0
  107. package/dist/lib/bootstrap.js +403 -0
  108. package/dist/lib/build-config.js +18 -0
  109. package/dist/lib/builtin-db.js +86 -0
  110. package/dist/lib/cli-config.js +176 -0
  111. package/dist/lib/cli-home.js +47 -0
  112. package/dist/lib/cli-locale.js +129 -0
  113. package/dist/lib/command-discovery.js +39 -0
  114. package/dist/lib/db-connection-check.js +158 -0
  115. package/dist/lib/docker-env-file.js +52 -0
  116. package/dist/lib/docker-image.js +37 -0
  117. package/dist/lib/env-auth.js +873 -0
  118. package/dist/lib/env-config.js +94 -0
  119. package/dist/lib/env-guard.js +62 -0
  120. package/dist/lib/generated-command.js +186 -0
  121. package/dist/lib/http-request.js +49 -0
  122. package/dist/lib/inquirer-theme.js +17 -0
  123. package/dist/lib/inquirer.js +244 -0
  124. package/dist/lib/naming.js +70 -0
  125. package/dist/lib/object-utils.js +76 -0
  126. package/dist/lib/openapi.js +62 -0
  127. package/dist/lib/plugin-storage.js +64 -0
  128. package/dist/lib/post-processors.js +23 -0
  129. package/dist/lib/prompt-catalog-core.js +185 -0
  130. package/dist/lib/prompt-catalog-terminal.js +375 -0
  131. package/{src/index.js → dist/lib/prompt-catalog.js} +2 -6
  132. package/dist/lib/prompt-validators.js +240 -0
  133. package/dist/lib/prompt-web-ui.js +2103 -0
  134. package/dist/lib/resource-command.js +357 -0
  135. package/dist/lib/resource-request.js +104 -0
  136. package/dist/lib/run-npm.js +275 -0
  137. package/dist/lib/runtime-env-vars.js +32 -0
  138. package/dist/lib/runtime-generator.js +498 -0
  139. package/dist/lib/runtime-store.js +56 -0
  140. package/dist/lib/self-manager.js +301 -0
  141. package/dist/lib/session-id.js +17 -0
  142. package/dist/lib/session-integration.js +703 -0
  143. package/dist/lib/session-store.js +118 -0
  144. package/dist/lib/skills-manager.js +360 -0
  145. package/dist/lib/source-publish.js +306 -0
  146. package/dist/lib/source-registry.js +188 -0
  147. package/dist/lib/startup-update.js +285 -0
  148. package/dist/lib/ui.js +155 -0
  149. package/dist/locale/en-US.json +344 -0
  150. package/dist/locale/zh-CN.json +344 -0
  151. package/dist/post-processors/data-modeling.js +84 -0
  152. package/dist/post-processors/data-source-manager.js +138 -0
  153. package/dist/post-processors/index.js +19 -0
  154. package/nocobase-ctl.config.json +388 -0
  155. package/package.json +100 -26
  156. package/LICENSE +0 -661
  157. package/bin/index.js +0 -39
  158. package/nocobase.conf.tpl +0 -95
  159. package/src/commands/benchmark.js +0 -73
  160. package/src/commands/build.js +0 -49
  161. package/src/commands/clean.js +0 -30
  162. package/src/commands/client.js +0 -166
  163. package/src/commands/create-nginx-conf.js +0 -37
  164. package/src/commands/create-plugin.js +0 -33
  165. package/src/commands/dev.js +0 -200
  166. package/src/commands/doc.js +0 -76
  167. package/src/commands/e2e.js +0 -265
  168. package/src/commands/global.js +0 -43
  169. package/src/commands/index.js +0 -45
  170. package/src/commands/instance-id.js +0 -47
  171. package/src/commands/locale/cronstrue.js +0 -122
  172. package/src/commands/locale/react-js-cron/en-US.json +0 -75
  173. package/src/commands/locale/react-js-cron/zh-CN.json +0 -33
  174. package/src/commands/locale/react-js-cron/zh-TW.json +0 -33
  175. package/src/commands/locale.js +0 -81
  176. package/src/commands/p-test.js +0 -88
  177. package/src/commands/perf.js +0 -63
  178. package/src/commands/pkg.js +0 -321
  179. package/src/commands/pm2.js +0 -37
  180. package/src/commands/postinstall.js +0 -88
  181. package/src/commands/start.js +0 -148
  182. package/src/commands/tar.js +0 -36
  183. package/src/commands/test-coverage.js +0 -55
  184. package/src/commands/test.js +0 -107
  185. package/src/commands/umi.js +0 -33
  186. package/src/commands/update-deps.js +0 -72
  187. package/src/commands/upgrade.js +0 -47
  188. package/src/commands/view-license-key.js +0 -44
  189. package/src/license.js +0 -76
  190. package/src/logger.js +0 -75
  191. package/src/plugin-generator.js +0 -80
  192. package/src/util.js +0 -517
  193. package/templates/bundle-status.html +0 -338
  194. package/templates/create-app-package.json +0 -39
  195. package/templates/plugin/.npmignore.tpl +0 -2
  196. package/templates/plugin/README.md.tpl +0 -1
  197. package/templates/plugin/client.d.ts +0 -2
  198. package/templates/plugin/client.js +0 -1
  199. package/templates/plugin/package.json.tpl +0 -11
  200. package/templates/plugin/server.d.ts +0 -2
  201. package/templates/plugin/server.js +0 -1
  202. package/templates/plugin/src/client/client.d.ts +0 -249
  203. package/templates/plugin/src/client/index.tsx.tpl +0 -1
  204. package/templates/plugin/src/client/locale.ts +0 -21
  205. package/templates/plugin/src/client/plugin.tsx.tpl +0 -10
  206. package/templates/plugin/src/index.ts +0 -2
  207. package/templates/plugin/src/locale/en-US.json +0 -1
  208. package/templates/plugin/src/locale/zh-CN.json +0 -1
  209. package/templates/plugin/src/server/collections/.gitkeep +0 -0
  210. package/templates/plugin/src/server/index.ts.tpl +0 -1
  211. package/templates/plugin/src/server/plugin.ts.tpl +0 -19
@@ -0,0 +1,70 @@
1
+ import path from 'node:path';
2
+ export function toKebabCase(value) {
3
+ return value
4
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
5
+ .replace(/[^a-zA-Z0-9]+/g, '-')
6
+ .replace(/-+/g, '-')
7
+ .replace(/^-|-$/g, '')
8
+ .toLowerCase();
9
+ }
10
+ export function splitPathAction(pathTemplate) {
11
+ const normalizedPath = pathTemplate.replace(/^\/+/, '');
12
+ const separatorIndex = normalizedPath.lastIndexOf(':');
13
+ if (separatorIndex === -1) {
14
+ return {
15
+ resourcePath: normalizedPath,
16
+ action: 'call',
17
+ };
18
+ }
19
+ return {
20
+ resourcePath: normalizedPath.slice(0, separatorIndex),
21
+ action: normalizedPath.slice(separatorIndex + 1),
22
+ };
23
+ }
24
+ export function toLogicalResourceName(pathTemplate) {
25
+ const { resourcePath } = splitPathAction(pathTemplate);
26
+ return resourcePath
27
+ .split('/')
28
+ .filter(Boolean)
29
+ .filter((segment) => !segment.startsWith('{'))
30
+ .map((segment) => toKebabCase(segment))
31
+ .join('.');
32
+ }
33
+ export function toLogicalActionName(pathTemplate) {
34
+ return toKebabCase(splitPathAction(pathTemplate).action);
35
+ }
36
+ export function toResourceSegments(pathTemplate, options) {
37
+ const { resourcePath, action } = splitPathAction(pathTemplate);
38
+ const pathSegments = resourcePath
39
+ .split('/')
40
+ .filter(Boolean)
41
+ .flatMap((segment) => {
42
+ if (!segment.startsWith('{')) {
43
+ return [toKebabCase(segment)];
44
+ }
45
+ if (!options?.includeParams) {
46
+ return [];
47
+ }
48
+ return [`by-${toKebabCase(segment.slice(1, -1))}`];
49
+ });
50
+ return [...pathSegments, toKebabCase(action)].filter(Boolean);
51
+ }
52
+ export function toCommandSegments(moduleName, pathTemplate, options) {
53
+ const resourceSegments = toResourceSegments(pathTemplate, options);
54
+ const segments = [options?.omitModule ? '' : toKebabCase(moduleName), ...resourceSegments].filter(Boolean);
55
+ return segments.length ? segments : [toKebabCase(moduleName), 'call'];
56
+ }
57
+ export function toClassName(segments) {
58
+ return segments
59
+ .map((segment) => segment.replace(/(^\w|-\w)/g, (token) => token.replace('-', '').toUpperCase()))
60
+ .join('');
61
+ }
62
+ export function toOutputFile(outputRoot, segments) {
63
+ const folder = path.join(outputRoot, ...segments.slice(0, -1));
64
+ const filePath = path.join(folder, `${segments.at(-1)}.ts`);
65
+ return filePath;
66
+ }
67
+ export function toImportPath(fromFile, targetFile) {
68
+ const relative = path.relative(path.dirname(fromFile), targetFile).replace(/\\/g, '/');
69
+ return relative.startsWith('.') ? relative : `./${relative}`;
70
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ export function pickKeys(object, keys) {
10
+ const picked = {};
11
+ for (const key of keys) {
12
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
13
+ const typedKey = key;
14
+ picked[typedKey] = object[typedKey];
15
+ }
16
+ }
17
+ return picked;
18
+ }
19
+ export function omitKeys(object, keys) {
20
+ const omittedKeys = new Set(keys);
21
+ const result = {};
22
+ for (const key of Object.keys(object)) {
23
+ if (!omittedKeys.has(key)) {
24
+ const typedKey = key;
25
+ result[typedKey] = object[typedKey];
26
+ }
27
+ }
28
+ return result;
29
+ }
30
+ export function upperFirst(value) {
31
+ if (!value) {
32
+ return value;
33
+ }
34
+ return value[0].toUpperCase() + value.slice(1);
35
+ }
36
+ export function deepEqual(left, right) {
37
+ if (Object.is(left, right)) {
38
+ return true;
39
+ }
40
+ if (left == null || right == null) {
41
+ return false;
42
+ }
43
+ if (typeof left !== typeof right) {
44
+ return false;
45
+ }
46
+ if (typeof left !== 'object') {
47
+ return false;
48
+ }
49
+ if (Array.isArray(left) || Array.isArray(right)) {
50
+ if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) {
51
+ return false;
52
+ }
53
+ for (let index = 0; index < left.length; index += 1) {
54
+ if (!deepEqual(left[index], right[index])) {
55
+ return false;
56
+ }
57
+ }
58
+ return true;
59
+ }
60
+ const leftObject = left;
61
+ const rightObject = right;
62
+ const leftKeys = Object.keys(leftObject);
63
+ const rightKeys = Object.keys(rightObject);
64
+ if (leftKeys.length !== rightKeys.length) {
65
+ return false;
66
+ }
67
+ for (const key of leftKeys) {
68
+ if (!Object.prototype.hasOwnProperty.call(rightObject, key)) {
69
+ return false;
70
+ }
71
+ if (!deepEqual(leftObject[key], rightObject[key])) {
72
+ return false;
73
+ }
74
+ }
75
+ return true;
76
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ const HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete'];
10
+ function resolveLocalRef(document, ref) {
11
+ if (!ref.startsWith('#/')) {
12
+ return undefined;
13
+ }
14
+ return ref
15
+ .slice(2)
16
+ .split('/')
17
+ .reduce((current, segment) => current?.[segment], document);
18
+ }
19
+ function dereferenceNode(node, document, seen = new Set()) {
20
+ if (Array.isArray(node)) {
21
+ return node.map((item) => dereferenceNode(item, document, seen));
22
+ }
23
+ if (!node || typeof node !== 'object') {
24
+ return node;
25
+ }
26
+ const ref = node.$ref;
27
+ if (typeof ref === 'string') {
28
+ if (seen.has(ref)) {
29
+ return {};
30
+ }
31
+ const resolved = resolveLocalRef(document, ref);
32
+ if (!resolved) {
33
+ return node;
34
+ }
35
+ return dereferenceNode(resolved, document, new Set([...seen, ref]));
36
+ }
37
+ return Object.fromEntries(Object.entries(node).map(([key, value]) => [key, dereferenceNode(value, document, seen)]));
38
+ }
39
+ export function collectOperations(document) {
40
+ const operations = [];
41
+ for (const [pathTemplate, pathItem] of Object.entries(document.paths ?? {})) {
42
+ for (const method of HTTP_METHODS) {
43
+ const operation = pathItem?.[method];
44
+ if (!operation || '$ref' in operation) {
45
+ continue;
46
+ }
47
+ const parameters = [...(pathItem.parameters ?? []), ...(operation.parameters ?? [])]
48
+ .map((parameter) => dereferenceNode(parameter, document))
49
+ .filter((parameter) => Boolean(parameter && !('$ref' in parameter)));
50
+ operations.push({
51
+ method,
52
+ pathTemplate,
53
+ operation: {
54
+ ...operation,
55
+ parameters,
56
+ requestBody: operation.requestBody ? dereferenceNode(operation.requestBody, document) : undefined,
57
+ },
58
+ });
59
+ }
60
+ }
61
+ return operations;
62
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import path from 'node:path';
10
+ import { access, lstat, readlink, rm } from 'node:fs/promises';
11
+ async function pathExists(target) {
12
+ try {
13
+ await access(target);
14
+ return true;
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ export function resolvePluginStoragePath(storagePath) {
21
+ const root = String(storagePath ?? process.env.STORAGE_PATH ?? '').trim();
22
+ if (root) {
23
+ return path.join(path.isAbsolute(root) ? root : path.resolve(process.cwd(), root), 'plugins');
24
+ }
25
+ const configured = String(process.env.PLUGIN_STORAGE_PATH ?? '').trim();
26
+ if (configured) {
27
+ return path.isAbsolute(configured) ? configured : path.resolve(process.cwd(), configured);
28
+ }
29
+ return path.resolve(process.cwd(), 'storage', 'plugins');
30
+ }
31
+ export async function removeStoragePluginSymlink(pluginName, storagePath, nodeModulesPath = String(process.env.NODE_MODULES_PATH ?? '').trim()) {
32
+ if (!nodeModulesPath) {
33
+ return false;
34
+ }
35
+ const storagePluginsPath = resolvePluginStoragePath(storagePath);
36
+ const targetPath = path.resolve(storagePluginsPath, pluginName);
37
+ const linkPath = path.resolve(nodeModulesPath, pluginName);
38
+ if (!(await pathExists(linkPath))) {
39
+ return false;
40
+ }
41
+ let statResult;
42
+ try {
43
+ statResult = await lstat(linkPath);
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ if (!statResult.isSymbolicLink()) {
49
+ return false;
50
+ }
51
+ let resolvedLinkTarget = '';
52
+ try {
53
+ const linkTarget = await readlink(linkPath);
54
+ resolvedLinkTarget = path.resolve(path.dirname(linkPath), linkTarget);
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ if (resolvedLinkTarget !== targetPath) {
60
+ return false;
61
+ }
62
+ await rm(linkPath, { recursive: true, force: true });
63
+ return true;
64
+ }
@@ -0,0 +1,23 @@
1
+ function buildKey(resource, action) {
2
+ return `${resource}:${action}`;
3
+ }
4
+ class PostProcessorRegistry {
5
+ processors = new Map();
6
+ register(resource, action, processor) {
7
+ this.processors.set(buildKey(resource, action), processor);
8
+ }
9
+ resolve(resource, action) {
10
+ if (!resource || !action) {
11
+ return undefined;
12
+ }
13
+ return this.processors.get(buildKey(resource, action));
14
+ }
15
+ }
16
+ export const postProcessorRegistry = new PostProcessorRegistry();
17
+ export async function applyPostProcessor(result, context) {
18
+ const processor = postProcessorRegistry.resolve(context.operation.logicalResourceName, context.operation.actionName);
19
+ if (!processor) {
20
+ return result;
21
+ }
22
+ return processor(result, context);
23
+ }
@@ -0,0 +1,185 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import { createCliTranslate, resolveCliLocale, resolveLocalizedText, } from "./cli-locale.js";
10
+ export function selectOptionValues(options) {
11
+ return options.map((o) => (typeof o === 'string' ? o : o.value));
12
+ }
13
+ export function resolvePromptText(text, locale, fallback = '') {
14
+ return resolveLocalizedText(text, { locale, fallback });
15
+ }
16
+ export function enabledSelectOptionValues(options) {
17
+ return options
18
+ .filter((o) => typeof o === 'string' || o.disabled !== true)
19
+ .map((o) => (typeof o === 'string' ? o : o.value));
20
+ }
21
+ export function createPromptCatalogHooks(locale, overrides, defaults) {
22
+ return {
23
+ onCancel: overrides?.onCancel
24
+ ?? defaults?.onCancel
25
+ ?? (() => {
26
+ throw new Error(createCliTranslate(locale)('promptCatalog.common.cancelled'));
27
+ }),
28
+ onMissingNonInteractive: overrides?.onMissingNonInteractive
29
+ ?? defaults?.onMissingNonInteractive
30
+ ?? ((message) => {
31
+ throw new Error(message);
32
+ }),
33
+ };
34
+ }
35
+ export function hasIvKey(iv, key) {
36
+ return (Object.prototype.hasOwnProperty.call(iv, key) && iv[key] !== undefined && iv[key] !== null);
37
+ }
38
+ export function resolveTextInitial(def, valuesSoFar) {
39
+ const iv = def.initialValue;
40
+ if (typeof iv === 'function') {
41
+ return iv(valuesSoFar);
42
+ }
43
+ return iv;
44
+ }
45
+ export function mergedText(key, def, iv, useYesInitial, valuesSoFar = {}) {
46
+ if (hasIvKey(iv, key)) {
47
+ return String(iv[key]);
48
+ }
49
+ if (useYesInitial && def.yesInitialValue !== undefined) {
50
+ return def.yesInitialValue;
51
+ }
52
+ return resolveTextInitial(def, valuesSoFar) ?? '';
53
+ }
54
+ export function mergedBoolean(key, def, iv, useYesInitial) {
55
+ if (hasIvKey(iv, key)) {
56
+ return Boolean(iv[key]);
57
+ }
58
+ if (useYesInitial && def.yesInitialValue !== undefined) {
59
+ return def.yesInitialValue;
60
+ }
61
+ return def.initialValue ?? true;
62
+ }
63
+ export function mergedSelect(key, def, iv, useYesInitial) {
64
+ const enabledValueList = enabledSelectOptionValues(def.options);
65
+ if (hasIvKey(iv, key)) {
66
+ const s = String(iv[key]);
67
+ if (enabledValueList.includes(s)) {
68
+ return s;
69
+ }
70
+ return undefined;
71
+ }
72
+ if (useYesInitial && def.yesInitialValue !== undefined && enabledValueList.includes(def.yesInitialValue)) {
73
+ return def.yesInitialValue;
74
+ }
75
+ const d = def.initialValue;
76
+ if (d !== undefined && enabledValueList.includes(d)) {
77
+ return d;
78
+ }
79
+ return enabledValueList[0];
80
+ }
81
+ export function mergedInteger(key, def, iv, useYesInitial) {
82
+ if (hasIvKey(iv, key)) {
83
+ const v = iv[key];
84
+ return typeof v === 'number' ? v : Number.parseInt(String(v), 10);
85
+ }
86
+ if (useYesInitial && def.yesInitialValue !== undefined) {
87
+ return def.yesInitialValue;
88
+ }
89
+ return def.initialValue;
90
+ }
91
+ export function mergedPassword(key, def, iv, useYesInitial) {
92
+ if (hasIvKey(iv, key)) {
93
+ return String(iv[key] ?? '');
94
+ }
95
+ if (useYesInitial && def.yesInitialValue !== undefined) {
96
+ return def.yesInitialValue;
97
+ }
98
+ return def.initialValue;
99
+ }
100
+ export function isBlankText(value) {
101
+ return value.trim() === '';
102
+ }
103
+ export async function runPromptFieldValidate(def, value, values) {
104
+ if (def.type === 'intro' || def.type === 'outro' || def.type === 'run') {
105
+ return undefined;
106
+ }
107
+ if (!('validate' in def) || def.validate === undefined) {
108
+ return undefined;
109
+ }
110
+ const r = await def.validate(value, values);
111
+ if (r == null || r === '') {
112
+ return undefined;
113
+ }
114
+ return String(r);
115
+ }
116
+ export function isPromptBlockSkipped(def, values) {
117
+ if (def.type === 'run') {
118
+ return def.when !== undefined && !def.when(values);
119
+ }
120
+ return def.hidden !== undefined && def.hidden(values);
121
+ }
122
+ export function tryApplyPreset(key, def, preset, out, hooks, locale) {
123
+ const t = createCliTranslate(locale);
124
+ if (!hasIvKey(preset, key)) {
125
+ return false;
126
+ }
127
+ const raw = preset[key];
128
+ switch (def.type) {
129
+ case 'intro':
130
+ case 'outro':
131
+ case 'run':
132
+ return false;
133
+ case 'text': {
134
+ const s = String(raw ?? '');
135
+ if (def.required && isBlankText(s)) {
136
+ hooks.onMissingNonInteractive(t('promptCatalog.preset.required', { key }));
137
+ }
138
+ out[key] = s;
139
+ return true;
140
+ }
141
+ case 'boolean': {
142
+ out[key] = Boolean(raw);
143
+ return true;
144
+ }
145
+ case 'select': {
146
+ const valueList = selectOptionValues(def.options);
147
+ const s = String(raw ?? '');
148
+ if (!valueList.includes(s)) {
149
+ hooks.onMissingNonInteractive(t('promptCatalog.preset.invalidSelect', { key, value: s, options: valueList.join(', ') }));
150
+ }
151
+ out[key] = s;
152
+ return true;
153
+ }
154
+ case 'password': {
155
+ const s = String(raw ?? '');
156
+ if (def.required && isBlankText(s)) {
157
+ hooks.onMissingNonInteractive(t('promptCatalog.preset.required', { key }));
158
+ }
159
+ out[key] = s;
160
+ return true;
161
+ }
162
+ case 'integer': {
163
+ if (typeof raw === 'number' && Number.isFinite(raw)) {
164
+ out[key] = raw;
165
+ return true;
166
+ }
167
+ const s = String(raw ?? '').trim();
168
+ if (s === '') {
169
+ if (def.required) {
170
+ hooks.onMissingNonInteractive(t('promptCatalog.preset.required', { key }));
171
+ }
172
+ out[key] = def.initialValue ?? 0;
173
+ return true;
174
+ }
175
+ if (!/^-?\\d+$/.test(s)) {
176
+ hooks.onMissingNonInteractive(t('promptCatalog.preset.invalidInteger', { key }));
177
+ }
178
+ out[key] = Number.parseInt(s, 10);
179
+ return true;
180
+ }
181
+ }
182
+ }
183
+ export function resolvePromptCatalogLocale(locale) {
184
+ return resolveCliLocale(locale);
185
+ }