@gadmin2n/cli 0.0.105 → 0.0.107
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/CHANGELOG.md +17 -0
- package/actions/new.action.js +140 -94
- package/actions/update.action.d.ts +1 -0
- package/actions/update.action.js +564 -630
- package/commands/command.input.d.ts +1 -6
- package/commands/command.input.js +1 -7
- package/commands/command.loader.js +0 -2
- package/commands/new.command.js +8 -3
- package/commands/update.command.js +27 -37
- package/lib/template-merge/base-store.d.ts +16 -0
- package/lib/template-merge/base-store.js +127 -0
- package/lib/template-merge/binary-detect.d.ts +7 -0
- package/lib/template-merge/binary-detect.js +36 -0
- package/lib/template-merge/classify.d.ts +10 -0
- package/lib/template-merge/classify.js +61 -0
- package/lib/template-merge/config-validate.d.ts +5 -0
- package/lib/template-merge/config-validate.js +33 -0
- package/lib/template-merge/excludes.d.ts +7 -0
- package/lib/template-merge/excludes.js +109 -0
- package/lib/template-merge/index.d.ts +9 -8
- package/lib/template-merge/index.js +10 -8
- package/lib/template-merge/materialize.d.ts +18 -0
- package/lib/template-merge/materialize.js +129 -0
- package/lib/template-merge/merge3way.d.ts +15 -0
- package/lib/template-merge/merge3way.js +54 -0
- package/lib/template-merge/residual-scan.d.ts +10 -0
- package/lib/template-merge/residual-scan.js +31 -0
- package/lib/template-merge/types.d.ts +27 -0
- package/lib/template-merge/types.js +5 -0
- package/lib/ui/messages.d.ts +0 -2
- package/lib/ui/messages.js +0 -2
- package/package.json +2 -2
- package/commands/build.command.d.ts +0 -5
- package/commands/build.command.js +0 -50
- package/lib/template-merge/config-loader.d.ts +0 -15
- package/lib/template-merge/config-loader.js +0 -38
- package/lib/template-merge/env-merger.d.ts +0 -5
- package/lib/template-merge/env-merger.js +0 -57
- package/lib/template-merge/glob.d.ts +0 -5
- package/lib/template-merge/glob.js +0 -78
- package/lib/template-merge/json-merger.d.ts +0 -5
- package/lib/template-merge/json-merger.js +0 -269
- package/lib/template-merge/merger.d.ts +0 -30
- package/lib/template-merge/merger.js +0 -2
- package/lib/template-merge/prisma-merger.d.ts +0 -5
- package/lib/template-merge/prisma-merger.js +0 -112
- package/lib/template-merge/registry.d.ts +0 -25
- package/lib/template-merge/registry.js +0 -42
- package/lib/template-merge/ts-module-merger.d.ts +0 -16
- package/lib/template-merge/ts-module-merger.js +0 -193
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface MaterializedBase {
|
|
2
|
+
/** Absolute path to the directory containing the template's files. */
|
|
3
|
+
dir: string;
|
|
4
|
+
/** Idempotent cleanup of any temp dirs created. */
|
|
5
|
+
cleanup: () => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Materialize a base reference for 3-way merge.
|
|
9
|
+
*
|
|
10
|
+
* Sources, in priority order:
|
|
11
|
+
* 1. `GADMIN2_LOCAL_REGISTRY_DIR/<version>/<templateName>/` — used by tests
|
|
12
|
+
* and local development. Files are copied into a fresh tmp dir.
|
|
13
|
+
* 2. `npm pack @gadmin2n/schematics@<version>` — production. Tarball is
|
|
14
|
+
* extracted into a fresh tmp dir; the inner template subdir is returned.
|
|
15
|
+
*
|
|
16
|
+
* Returned `cleanup()` removes any tmp dir we created.
|
|
17
|
+
*/
|
|
18
|
+
export declare function materializeBase(schematicsVersion: string, templateName: string): MaterializedBase;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.materializeBase = void 0;
|
|
4
|
+
// cli/lib/template-merge/materialize.ts
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const os = require("os");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const SCHEMATICS_PKG = '@gadmin2n/schematics';
|
|
10
|
+
/**
|
|
11
|
+
* Materialize a base reference for 3-way merge.
|
|
12
|
+
*
|
|
13
|
+
* Sources, in priority order:
|
|
14
|
+
* 1. `GADMIN2_LOCAL_REGISTRY_DIR/<version>/<templateName>/` — used by tests
|
|
15
|
+
* and local development. Files are copied into a fresh tmp dir.
|
|
16
|
+
* 2. `npm pack @gadmin2n/schematics@<version>` — production. Tarball is
|
|
17
|
+
* extracted into a fresh tmp dir; the inner template subdir is returned.
|
|
18
|
+
*
|
|
19
|
+
* Returned `cleanup()` removes any tmp dir we created.
|
|
20
|
+
*/
|
|
21
|
+
function materializeBase(schematicsVersion, templateName) {
|
|
22
|
+
const localRegistry = process.env.GADMIN2_LOCAL_REGISTRY_DIR;
|
|
23
|
+
if (localRegistry) {
|
|
24
|
+
return materializeFromLocalRegistry(localRegistry, schematicsVersion, templateName);
|
|
25
|
+
}
|
|
26
|
+
return materializeFromNpm(schematicsVersion, templateName);
|
|
27
|
+
}
|
|
28
|
+
exports.materializeBase = materializeBase;
|
|
29
|
+
function materializeFromLocalRegistry(registryDir, version, templateName) {
|
|
30
|
+
const src = path.join(registryDir, version, templateName);
|
|
31
|
+
if (!fs.existsSync(src)) {
|
|
32
|
+
throw new Error(`local registry: version "${version}" not found at ${src}`);
|
|
33
|
+
}
|
|
34
|
+
const dst = fs.mkdtempSync(path.join(os.tmpdir(), 'gadmin2-base-'));
|
|
35
|
+
copyTreeRecursive(src, dst);
|
|
36
|
+
let cleaned = false;
|
|
37
|
+
const cleanup = () => {
|
|
38
|
+
if (cleaned)
|
|
39
|
+
return;
|
|
40
|
+
cleaned = true;
|
|
41
|
+
fs.rmSync(dst, { recursive: true, force: true });
|
|
42
|
+
};
|
|
43
|
+
process.on('exit', cleanup);
|
|
44
|
+
return { dir: dst, cleanup };
|
|
45
|
+
}
|
|
46
|
+
function materializeFromNpm(version, templateName) {
|
|
47
|
+
var _a;
|
|
48
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'gadmin2-base-'));
|
|
49
|
+
let cleaned = false;
|
|
50
|
+
const cleanup = () => {
|
|
51
|
+
if (cleaned)
|
|
52
|
+
return;
|
|
53
|
+
cleaned = true;
|
|
54
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
55
|
+
};
|
|
56
|
+
process.on('exit', cleanup);
|
|
57
|
+
try {
|
|
58
|
+
// npm pack writes the .tgz in the cwd; we capture its filename via --json.
|
|
59
|
+
let out;
|
|
60
|
+
try {
|
|
61
|
+
out = (0, child_process_1.execFileSync)('npm', ['pack', `${SCHEMATICS_PKG}@${version}`, '--json', '--silent'], { cwd: tmp, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
// ENOENT — npm not in PATH (preflight should catch this earlier)
|
|
65
|
+
if (err && err.code === 'ENOENT') {
|
|
66
|
+
throw new Error('npm not in PATH — required to materialize the base template');
|
|
67
|
+
}
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
const parsed = JSON.parse(out);
|
|
71
|
+
const tarballName = (_a = parsed === null || parsed === void 0 ? void 0 : parsed[0]) === null || _a === void 0 ? void 0 : _a.filename;
|
|
72
|
+
if (!tarballName) {
|
|
73
|
+
throw new Error(`npm pack did not return a filename. Raw output: ${out}`);
|
|
74
|
+
}
|
|
75
|
+
// npm pack `filename` may include a leading `<scope>/` for scoped packages
|
|
76
|
+
// on some npm versions, but the actual file lives flat in cwd.
|
|
77
|
+
const flatName = path.basename(tarballName);
|
|
78
|
+
try {
|
|
79
|
+
(0, child_process_1.execFileSync)('tar', ['-xf', flatName], { cwd: tmp, stdio: 'pipe' });
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
// ENOENT — tar not in PATH (preflight should catch this earlier)
|
|
83
|
+
if (err && err.code === 'ENOENT') {
|
|
84
|
+
throw new Error('tar not in PATH — required to extract the base template tarball');
|
|
85
|
+
}
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
const candidates = templateNameCandidates(templateName).map((n) => path.join(tmp, 'package/dist/lib/application/files', n));
|
|
89
|
+
for (const c of candidates) {
|
|
90
|
+
if (fs.existsSync(c)) {
|
|
91
|
+
return { dir: c, cleanup };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw new Error(`materialized tarball does not contain template "${templateName}". ` +
|
|
95
|
+
`Tried: ${candidates.join(', ')}`);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
cleanup();
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function templateNameCandidates(templateName) {
|
|
103
|
+
const out = [templateName];
|
|
104
|
+
if (templateName.startsWith('gadmin2n-')) {
|
|
105
|
+
out.push(templateName.replace('gadmin2n-', 'gadmin2-'));
|
|
106
|
+
}
|
|
107
|
+
else if (templateName.startsWith('gadmin2-')) {
|
|
108
|
+
out.push(templateName.replace('gadmin2-', 'gadmin2n-'));
|
|
109
|
+
}
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
function copyTreeRecursive(src, dst) {
|
|
113
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
114
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
115
|
+
const s = path.join(src, entry.name);
|
|
116
|
+
const d = path.join(dst, entry.name);
|
|
117
|
+
if (entry.isDirectory()) {
|
|
118
|
+
copyTreeRecursive(s, d);
|
|
119
|
+
}
|
|
120
|
+
else if (entry.isFile()) {
|
|
121
|
+
fs.copyFileSync(s, d);
|
|
122
|
+
try {
|
|
123
|
+
fs.chmodSync(d, fs.statSync(s).mode);
|
|
124
|
+
}
|
|
125
|
+
catch ( /* best effort */_a) { /* best effort */ }
|
|
126
|
+
}
|
|
127
|
+
// symlinks / sockets: skip
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface Merge3Result {
|
|
2
|
+
merged: string;
|
|
3
|
+
hasConflicts: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* 三方合并:依赖系统 git 的 `git merge-file`。
|
|
7
|
+
* 合并方向:base → ours / theirs,结果写入 ours 端。
|
|
8
|
+
* 冲突标记格式由 -L 参数控制:<<<<<<< INSTANCE / ======= / >>>>>>> TEMPLATE
|
|
9
|
+
*
|
|
10
|
+
* git merge-file 退出码:
|
|
11
|
+
* - 0 干净合并
|
|
12
|
+
* - N 1..127 冲突数(仍输出含标记的合并内容)
|
|
13
|
+
* - 128+ git 内部错误 / spawn 失败 —— 抛出
|
|
14
|
+
*/
|
|
15
|
+
export declare function merge3Way(baseContent: string, oursContent: string, theirsContent: string): Merge3Result;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.merge3Way = void 0;
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const os = require("os");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
/**
|
|
9
|
+
* 三方合并:依赖系统 git 的 `git merge-file`。
|
|
10
|
+
* 合并方向:base → ours / theirs,结果写入 ours 端。
|
|
11
|
+
* 冲突标记格式由 -L 参数控制:<<<<<<< INSTANCE / ======= / >>>>>>> TEMPLATE
|
|
12
|
+
*
|
|
13
|
+
* git merge-file 退出码:
|
|
14
|
+
* - 0 干净合并
|
|
15
|
+
* - N 1..127 冲突数(仍输出含标记的合并内容)
|
|
16
|
+
* - 128+ git 内部错误 / spawn 失败 —— 抛出
|
|
17
|
+
*/
|
|
18
|
+
function merge3Way(baseContent, oursContent, theirsContent) {
|
|
19
|
+
var _a, _b, _c, _d;
|
|
20
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gadmin-3way-'));
|
|
21
|
+
try {
|
|
22
|
+
const basePath = path.join(tmpDir, 'base');
|
|
23
|
+
const oursPath = path.join(tmpDir, 'ours');
|
|
24
|
+
const theirsPath = path.join(tmpDir, 'theirs');
|
|
25
|
+
fs.writeFileSync(basePath, baseContent, 'utf-8');
|
|
26
|
+
fs.writeFileSync(oursPath, oursContent, 'utf-8');
|
|
27
|
+
fs.writeFileSync(theirsPath, theirsContent, 'utf-8');
|
|
28
|
+
try {
|
|
29
|
+
(0, child_process_1.execFileSync)('git', ['merge-file', '-L', 'INSTANCE', '-L', 'BASE', '-L', 'TEMPLATE',
|
|
30
|
+
oursPath, basePath, theirsPath], { stdio: 'pipe' });
|
|
31
|
+
return { merged: fs.readFileSync(oursPath, 'utf-8'), hasConflicts: false };
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
// ENOENT — git not in PATH (preflight should catch this earlier)
|
|
35
|
+
if (err && err.code === 'ENOENT') {
|
|
36
|
+
throw new Error('git not in PATH — required for 3-way merge');
|
|
37
|
+
}
|
|
38
|
+
// git merge-file: status N where 1..127 = conflict count.
|
|
39
|
+
// 128+ = git internal error / spawn failure — never a conflict count.
|
|
40
|
+
if (typeof (err === null || err === void 0 ? void 0 : err.status) === 'number' && err.status > 0 && err.status < 128) {
|
|
41
|
+
return {
|
|
42
|
+
merged: fs.readFileSync(oursPath, 'utf-8'),
|
|
43
|
+
hasConflicts: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const stderrMsg = (_c = (_b = (_a = err === null || err === void 0 ? void 0 : err.stderr) === null || _a === void 0 ? void 0 : _a.toString) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : '';
|
|
47
|
+
throw new Error(`git merge-file failed (status ${(_d = err === null || err === void 0 ? void 0 : err.status) !== null && _d !== void 0 ? _d : '?'}): ${stderrMsg.trim() || (err === null || err === void 0 ? void 0 : err.message) || String(err)}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.merge3Way = merge3Way;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scanResidualMarkers = void 0;
|
|
4
|
+
// cli/lib/template-merge/residual-scan.ts
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const binary_detect_1 = require("./binary-detect");
|
|
8
|
+
const MARKER_RE = /^(<<<<<<< INSTANCE|=======|>>>>>>> TEMPLATE)\r?$/;
|
|
9
|
+
/**
|
|
10
|
+
* 扫描 rootDir 下指定文件中是否含有冲突标记(按整行匹配,避免误报字符串字面量)。
|
|
11
|
+
* 二进制文件跳过。
|
|
12
|
+
*/
|
|
13
|
+
function scanResidualMarkers(rootDir, files) {
|
|
14
|
+
const out = [];
|
|
15
|
+
for (const rel of files) {
|
|
16
|
+
const abs = path.join(rootDir, rel);
|
|
17
|
+
if (!fs.existsSync(abs))
|
|
18
|
+
continue;
|
|
19
|
+
if ((0, binary_detect_1.isFileBinary)(abs))
|
|
20
|
+
continue;
|
|
21
|
+
const content = fs.readFileSync(abs, 'utf-8');
|
|
22
|
+
const lines = content.split('\n');
|
|
23
|
+
for (let i = 0; i < lines.length; i++) {
|
|
24
|
+
if (MARKER_RE.test(lines[i])) {
|
|
25
|
+
out.push({ file: rel, line: i + 1, text: lines[i] });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
exports.scanResidualMarkers = scanResidualMarkers;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** 单个文件在三方合并中的分类结果。 */
|
|
2
|
+
export declare type ClassifyResult = 'add' | 'keep' | 'noop' | 'delete' | 'update' | 'addAddConflict' | 'modifyDeleteConflict' | 'deleteModifyConflict';
|
|
3
|
+
export interface ClassifiedPlan {
|
|
4
|
+
add: string[];
|
|
5
|
+
keep: string[];
|
|
6
|
+
noop: string[];
|
|
7
|
+
delete: string[];
|
|
8
|
+
update: string[];
|
|
9
|
+
addAddConflict: string[];
|
|
10
|
+
modifyDeleteConflict: string[];
|
|
11
|
+
deleteModifyConflict: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare type ConflictKind = 'content' | 'add/add' | 'modify/delete' | 'delete/modify' | 'binary';
|
|
14
|
+
export interface ConflictRecord {
|
|
15
|
+
path: string;
|
|
16
|
+
kind: ConflictKind;
|
|
17
|
+
detail?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface MergeOptions {
|
|
20
|
+
ours?: boolean;
|
|
21
|
+
theirs?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface BaseMeta {
|
|
24
|
+
schematicsVersion: string;
|
|
25
|
+
schemaVersion: number;
|
|
26
|
+
}
|
|
27
|
+
export declare const CURRENT_META_SCHEMA_VERSION = 1;
|
package/lib/ui/messages.d.ts
CHANGED
|
@@ -19,8 +19,6 @@ export declare const MESSAGES: {
|
|
|
19
19
|
LIBRARY_INSTALLATION_FAILED_NO_LIBRARY: string;
|
|
20
20
|
LIBRARY_INSTALLATION_STARTS: string;
|
|
21
21
|
TEMPLATE_QUESTION: string;
|
|
22
|
-
WITH_WEB_QUESTION: string;
|
|
23
22
|
TRANSFER_PROTOCOL_QUESTION: string;
|
|
24
|
-
SERVER_FRAMEWORK_QUESTION: string;
|
|
25
23
|
UI_FRAMEWORK_QUESTION: string;
|
|
26
24
|
};
|
package/lib/ui/messages.js
CHANGED
|
@@ -27,8 +27,6 @@ exports.MESSAGES = {
|
|
|
27
27
|
LIBRARY_INSTALLATION_FAILED_NO_LIBRARY: 'No library found.',
|
|
28
28
|
LIBRARY_INSTALLATION_STARTS: 'Starting library setup...',
|
|
29
29
|
TEMPLATE_QUESTION: 'Which template would you like to use?',
|
|
30
|
-
WITH_WEB_QUESTION: 'Need generate frontend web pages?',
|
|
31
30
|
TRANSFER_PROTOCOL_QUESTION: 'Transfer protocol to use (Restful or GraphQL)?',
|
|
32
|
-
SERVER_FRAMEWORK_QUESTION: 'Server framework to use (Nest or Iris)?',
|
|
33
31
|
UI_FRAMEWORK_QUESTION: 'UI framework to use (Antd or Tea)?',
|
|
34
32
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gadmin2n/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.107",
|
|
4
4
|
"description": "Gadmin - modern, fast, powerful node.js web framework (@cli)",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@angular-devkit/core": "13.3.2",
|
|
48
48
|
"@angular-devkit/schematics": "13.3.2",
|
|
49
49
|
"@angular-devkit/schematics-cli": "13.3.2",
|
|
50
|
-
"@gadmin2n/schematics": "^0.0.
|
|
50
|
+
"@gadmin2n/schematics": "^0.0.88",
|
|
51
51
|
"abc": "^0.6.1",
|
|
52
52
|
"chalk": "3.0.0",
|
|
53
53
|
"chokidar": "3.5.3",
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.BuildCommand = void 0;
|
|
13
|
-
const abstract_command_1 = require("./abstract.command");
|
|
14
|
-
class BuildCommand extends abstract_command_1.AbstractCommand {
|
|
15
|
-
load(program) {
|
|
16
|
-
program
|
|
17
|
-
.command('build [app]')
|
|
18
|
-
.option('-c, --config [path]', 'Path to gadmin-cli configuration file.')
|
|
19
|
-
.option('-p, --path [path]', 'Path to tsconfig file.')
|
|
20
|
-
.option('-w, --watch', 'Run in watch mode (live-reload).')
|
|
21
|
-
.option('--watchAssets', 'Watch non-ts (e.g., .graphql) files mode.')
|
|
22
|
-
.option('--webpack', 'Use webpack for compilation.')
|
|
23
|
-
.option('--webpackPath [path]', 'Path to webpack configuration.')
|
|
24
|
-
.option('--tsc', 'Use tsc for compilation.')
|
|
25
|
-
.description('Build Gadmin application.')
|
|
26
|
-
.action((app, command) => __awaiter(this, void 0, void 0, function* () {
|
|
27
|
-
const options = [];
|
|
28
|
-
options.push({
|
|
29
|
-
name: 'config',
|
|
30
|
-
value: command.config,
|
|
31
|
-
});
|
|
32
|
-
const isWebpackEnabled = command.tsc ? false : command.webpack;
|
|
33
|
-
options.push({ name: 'webpack', value: isWebpackEnabled });
|
|
34
|
-
options.push({ name: 'watch', value: !!command.watch });
|
|
35
|
-
options.push({ name: 'watchAssets', value: !!command.watchAssets });
|
|
36
|
-
options.push({
|
|
37
|
-
name: 'path',
|
|
38
|
-
value: command.path,
|
|
39
|
-
});
|
|
40
|
-
options.push({
|
|
41
|
-
name: 'webpackPath',
|
|
42
|
-
value: command.webpackPath,
|
|
43
|
-
});
|
|
44
|
-
const inputs = [];
|
|
45
|
-
inputs.push({ name: 'app', value: app });
|
|
46
|
-
yield this.action.handle(inputs, options);
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
exports.BuildCommand = BuildCommand;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export interface TemplateUpdateConfig {
|
|
2
|
-
/** Glob → merger name. Insertion order is preserved (use plain object/array, not Map). */
|
|
3
|
-
mergers?: Record<string, string>;
|
|
4
|
-
/** Dot-namespaced key → value, e.g. 'json.scripts': 'preserve-instance' */
|
|
5
|
-
policies?: Record<string, string>;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Load the templateUpdate section from gadmin-cli.json.
|
|
9
|
-
* Searches in this order:
|
|
10
|
-
* 1. <instanceDir>/server/gadmin-cli.json
|
|
11
|
-
* 2. <instanceDir>/gadmin-cli.json
|
|
12
|
-
* Returns null if no config file found, no `templateUpdate` key, or on parse error.
|
|
13
|
-
* On parse error, also console.warn with the error and the file path.
|
|
14
|
-
*/
|
|
15
|
-
export declare function loadTemplateUpdateConfig(instanceDir: string): TemplateUpdateConfig | null;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadTemplateUpdateConfig = void 0;
|
|
4
|
-
const fs = require("fs");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
/**
|
|
7
|
-
* Load the templateUpdate section from gadmin-cli.json.
|
|
8
|
-
* Searches in this order:
|
|
9
|
-
* 1. <instanceDir>/server/gadmin-cli.json
|
|
10
|
-
* 2. <instanceDir>/gadmin-cli.json
|
|
11
|
-
* Returns null if no config file found, no `templateUpdate` key, or on parse error.
|
|
12
|
-
* On parse error, also console.warn with the error and the file path.
|
|
13
|
-
*/
|
|
14
|
-
function loadTemplateUpdateConfig(instanceDir) {
|
|
15
|
-
const candidates = [
|
|
16
|
-
path.join(instanceDir, 'server', 'gadmin-cli.json'),
|
|
17
|
-
path.join(instanceDir, 'gadmin-cli.json'),
|
|
18
|
-
];
|
|
19
|
-
for (const configPath of candidates) {
|
|
20
|
-
if (!fs.existsSync(configPath))
|
|
21
|
-
continue;
|
|
22
|
-
try {
|
|
23
|
-
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
24
|
-
const parsed = JSON.parse(raw);
|
|
25
|
-
const section = parsed === null || parsed === void 0 ? void 0 : parsed.templateUpdate;
|
|
26
|
-
if (!section || typeof section !== 'object') {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
return section;
|
|
30
|
-
}
|
|
31
|
-
catch (err) {
|
|
32
|
-
console.warn(`Failed to parse templateUpdate config at ${configPath}: ${(err === null || err === void 0 ? void 0 : err.message) || err}`);
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
exports.loadTemplateUpdateConfig = loadTemplateUpdateConfig;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EnvMerger = void 0;
|
|
4
|
-
const KEY_RE = /^([A-Za-z_][A-Za-z0-9_]*)=/;
|
|
5
|
-
class EnvMerger {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.name = 'env';
|
|
8
|
-
}
|
|
9
|
-
merge(ctx) {
|
|
10
|
-
try {
|
|
11
|
-
const instLines = ctx.instanceContent.split('\n');
|
|
12
|
-
const instKeys = new Set();
|
|
13
|
-
for (const line of instLines) {
|
|
14
|
-
const m = line.match(KEY_RE);
|
|
15
|
-
if (m)
|
|
16
|
-
instKeys.add(m[1]);
|
|
17
|
-
}
|
|
18
|
-
const tmplLines = ctx.templateContent.split('\n');
|
|
19
|
-
const toAdd = [];
|
|
20
|
-
const addedKeys = [];
|
|
21
|
-
for (const line of tmplLines) {
|
|
22
|
-
const trimmed = line.trim();
|
|
23
|
-
if (trimmed === '' || trimmed.startsWith('#'))
|
|
24
|
-
continue;
|
|
25
|
-
const m = line.match(KEY_RE);
|
|
26
|
-
if (!m)
|
|
27
|
-
continue;
|
|
28
|
-
const key = m[1];
|
|
29
|
-
if (instKeys.has(key))
|
|
30
|
-
continue;
|
|
31
|
-
toAdd.push(line);
|
|
32
|
-
addedKeys.push(key);
|
|
33
|
-
}
|
|
34
|
-
if (toAdd.length === 0) {
|
|
35
|
-
return {
|
|
36
|
-
ok: true,
|
|
37
|
-
merged: ctx.instanceContent,
|
|
38
|
-
notes: ['no changes'],
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
let merged = ctx.instanceContent;
|
|
42
|
-
if (!merged.endsWith('\n'))
|
|
43
|
-
merged += '\n';
|
|
44
|
-
merged += '\n# --- added from template ---\n';
|
|
45
|
-
merged += toAdd.join('\n');
|
|
46
|
-
if (!merged.endsWith('\n'))
|
|
47
|
-
merged += '\n';
|
|
48
|
-
const notes = addedKeys.map((k) => `added ${k}`);
|
|
49
|
-
return { ok: true, merged, notes };
|
|
50
|
-
}
|
|
51
|
-
catch (e) {
|
|
52
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
53
|
-
return { ok: false, reason: `env merge error: ${msg}` };
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
exports.EnvMerger = EnvMerger;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.globMatch = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Convert a glob pattern to a RegExp.
|
|
6
|
-
* Supports: * (any chars except /), ** (any path segments), ? (single char)
|
|
7
|
-
*/
|
|
8
|
-
function globToRegex(pattern) {
|
|
9
|
-
let regexStr = '^';
|
|
10
|
-
let i = 0;
|
|
11
|
-
while (i < pattern.length) {
|
|
12
|
-
const c = pattern[i];
|
|
13
|
-
if (c === '*') {
|
|
14
|
-
if (pattern[i + 1] === '*') {
|
|
15
|
-
if (pattern[i + 2] === '/') {
|
|
16
|
-
regexStr += '(?:.+/)?';
|
|
17
|
-
i += 3;
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
regexStr += '.*';
|
|
21
|
-
i += 2;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
regexStr += '[^/]*';
|
|
26
|
-
i++;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
else if (c === '?') {
|
|
30
|
-
regexStr += '[^/]';
|
|
31
|
-
i++;
|
|
32
|
-
}
|
|
33
|
-
else if (c === '.' ||
|
|
34
|
-
c === '(' ||
|
|
35
|
-
c === ')' ||
|
|
36
|
-
c === '[' ||
|
|
37
|
-
c === ']' ||
|
|
38
|
-
c === '{' ||
|
|
39
|
-
c === '}' ||
|
|
40
|
-
c === '+' ||
|
|
41
|
-
c === '^' ||
|
|
42
|
-
c === '$' ||
|
|
43
|
-
c === '|' ||
|
|
44
|
-
c === '\\') {
|
|
45
|
-
regexStr += '\\' + c;
|
|
46
|
-
i++;
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
regexStr += c;
|
|
50
|
-
i++;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
regexStr += '$';
|
|
54
|
-
return new RegExp(regexStr);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Match a file path against a glob pattern.
|
|
58
|
-
* Equivalent to `matchesPattern` in actions/update.action.ts.
|
|
59
|
-
*/
|
|
60
|
-
function globMatch(filePath, pattern) {
|
|
61
|
-
if (filePath === pattern)
|
|
62
|
-
return true;
|
|
63
|
-
if (filePath.startsWith(pattern + '/'))
|
|
64
|
-
return true;
|
|
65
|
-
const parts = filePath.split('/');
|
|
66
|
-
if (!pattern.includes('/') &&
|
|
67
|
-
!pattern.includes('*') &&
|
|
68
|
-
!pattern.includes('?')) {
|
|
69
|
-
if (parts.includes(pattern))
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
if (pattern.includes('*') || pattern.includes('?')) {
|
|
73
|
-
const regex = globToRegex(pattern);
|
|
74
|
-
return regex.test(filePath);
|
|
75
|
-
}
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
exports.globMatch = globMatch;
|