@meadmin/cli 1.3.7 → 1.3.8

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.
@@ -0,0 +1,116 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, lstatSync, readFileSync, readdirSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { mergeConfig, mergeEntity, mergePackage } from './merge.js';
5
+ import { excluded, skipExisting, sourceMode } from './rules.js';
6
+ import { isIntegrationSource, mergeSource } from './source.js';
7
+ import { generateUpdateSql } from './sql.js';
8
+ export const hash = (content) => createHash('sha256').update(content).digest('hex');
9
+ export function readLocal(root, path) {
10
+ let current = root;
11
+ for (const part of path.split('/')) {
12
+ current = join(current, part);
13
+ if (existsSync(current) && lstatSync(current).isSymbolicLink())
14
+ throw new Error(`拒绝操作符号链接:${path}`);
15
+ }
16
+ if (!existsSync(current))
17
+ return undefined;
18
+ if (!lstatSync(current).isFile())
19
+ throw new Error(`文件路径被目录占用:${path}`);
20
+ return readFileSync(current);
21
+ }
22
+ function templateFiles(root) {
23
+ const files = new Map(), names = new Set();
24
+ const visit = (directory, prefix = '') => {
25
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
26
+ const sourcePath = prefix + entry.name;
27
+ if (excluded(sourcePath))
28
+ continue;
29
+ if (entry.isSymbolicLink())
30
+ throw new Error(`模板含符号链接:${sourcePath}`);
31
+ if (entry.isDirectory())
32
+ visit(join(directory, entry.name), sourcePath + '/');
33
+ else if (entry.isFile()) {
34
+ const path = prefix + (entry.name === 'packageTemplate.json' ? 'package.json' : entry.name);
35
+ if (names.has(path.toLowerCase()))
36
+ throw new Error(`模板映射路径冲突:${path}`);
37
+ names.add(path.toLowerCase());
38
+ files.set(path, readFileSync(join(directory, entry.name)));
39
+ }
40
+ }
41
+ };
42
+ visit(root);
43
+ return files;
44
+ }
45
+ export function makePlan(root, oldTemplate, targetTemplate, targetVersion, rules, sourceRules = {}) {
46
+ const base = templateFiles(oldTemplate), target = templateFiles(targetTemplate);
47
+ const plan = { changes: [], skipped: [], manual: [], sqlTables: [] };
48
+ const add = (path, content, action, previous, conflict = false) => {
49
+ if (previous?.equals(content))
50
+ return;
51
+ plan.changes.push({ path, action: previous ? action : 'create', previous: previous ? hash(previous) : null, content, conflict });
52
+ };
53
+ for (const [path, content] of target) {
54
+ if (path.toLowerCase() === 'meadmin.sql')
55
+ continue;
56
+ if (path.toLowerCase() === 'update.sql' || /^meadmin-.*\.sql$/i.test(path)) {
57
+ plan.manual.push(`${path}: 模板含升级产物保留名称,未复制`);
58
+ continue;
59
+ }
60
+ const local = readLocal(root, path), old = base.get(path);
61
+ if (local && skipExisting(path, rules)) {
62
+ plan.skipped.push(`${path}: 存在时跳过`);
63
+ continue;
64
+ }
65
+ if (local?.equals(content) || (old?.equals(content) && local))
66
+ continue;
67
+ if (!local) {
68
+ add(path, content, 'create');
69
+ continue;
70
+ }
71
+ const conflict = !old || !old.equals(local);
72
+ const explicitMode = sourceMode(path, sourceRules);
73
+ const sourceFile = /\.[cm]?[jt]s$/.test(path);
74
+ const builtinMerge = path === 'package.json' || path.endsWith('/package.json') || /(^|\/)entities\//.test(path) || /(^|\/)src\/config\//.test(path);
75
+ // 显式 false 关闭自动识别;默认不扩大到有运行时初始化逻辑的入口。
76
+ const mode = sourceFile && !builtinMerge ? (explicitMode === undefined && isIntegrationSource(content.toString('utf8')) ? 'exports' : explicitMode) : undefined;
77
+ if (mode) {
78
+ const result = mergeSource(local.toString('utf8'), content.toString('utf8'), old?.toString('utf8'), mode, path);
79
+ plan.manual.push(...result.manual.map((message) => `${path}: ${message}`));
80
+ add(path, Buffer.from(result.content), 'merge', local, conflict);
81
+ continue;
82
+ }
83
+ const merge = path.endsWith('/package.json') || path === 'package.json' ? mergePackage : /(^|\/)entities\/.*\.ts$/.test(path) ? mergeEntity : /(^|\/)src\/config\//.test(path) && path.endsWith('.ts') ? mergeConfig : undefined;
84
+ if (merge) {
85
+ try {
86
+ const result = merge(local.toString('utf8'), content.toString('utf8'), old?.toString('utf8'));
87
+ plan.manual.push(...result.manual.map((message) => `${path}: ${message}`));
88
+ add(path, Buffer.from(result.content), 'merge', local, conflict);
89
+ }
90
+ catch (error) {
91
+ plan.manual.push(`${path}: 合并失败,需人工处理:${String(error)}`);
92
+ }
93
+ }
94
+ else if (/(^|\/)(vite\.config\.[^/]+|eslint\.config\.[^/]+|tsconfig[^/]*\.json|pnpm-workspace\.yaml)$/.test(path)) {
95
+ plan.manual.push(`${path}: 工程配置变化,保留本地,需人工对照目标模板`);
96
+ }
97
+ else
98
+ add(path, content, 'overwrite', local, conflict);
99
+ }
100
+ for (const path of base.keys())
101
+ if (!target.has(path) && !excluded(path))
102
+ plan.manual.push(`${path}: 目标模板已移除,本地不会删除`);
103
+ const sql = [...target].find(([path]) => path.toLowerCase() === 'meadmin.sql')?.[1];
104
+ if (sql) {
105
+ const generated = generateUpdateSql(sql.toString('utf8'), targetVersion);
106
+ const originalName = `meadmin-${targetVersion}.sql`;
107
+ add(originalName, sql, 'overwrite', readLocal(root, originalName));
108
+ add('update.sql', Buffer.from(generated.content), 'overwrite', readLocal(root, 'update.sql'));
109
+ plan.manual.push(...generated.manual.map((item) => 'SQL: ' + item));
110
+ plan.sqlTables = generated.tables;
111
+ }
112
+ else
113
+ plan.manual.push('目标模板缺少 meadmin.sql,未生成数据升级脚本');
114
+ return plan;
115
+ }
116
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhbm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91cGRhdGUvcGxhbm5lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDM0UsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNqQyxPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDcEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ2hFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDL0QsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBSTdDLE1BQU0sQ0FBQyxNQUFNLElBQUksR0FBRyxDQUFDLE9BQWUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDNUYsTUFBTSxVQUFVLFNBQVMsQ0FBQyxJQUFZLEVBQUUsSUFBWTtJQUNsRCxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUM7SUFDbkIsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDbkMsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDOUIsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLGNBQWMsRUFBRTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMs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
@@ -0,0 +1,12 @@
1
+ export type SourcePolicy = 'functions' | 'exports' | false;
2
+ export type UpdateRules = {
3
+ skipExisting: Record<string, boolean>;
4
+ mergeSource: Record<string, SourcePolicy>;
5
+ };
6
+ export declare const defaults: Record<string, boolean>;
7
+ export declare const sourceDefaults: Record<string, SourcePolicy>;
8
+ export declare function excluded(path: string): boolean;
9
+ export declare function skipExisting(path: string, user?: Record<string, boolean>): boolean;
10
+ export declare function sourceMode(path: string, user?: Record<string, SourcePolicy>): SourcePolicy | undefined;
11
+ export declare function validateConfig(value: unknown): UpdateRules;
12
+ export declare const validateRules: (value: unknown) => Record<string, boolean>;
@@ -0,0 +1,55 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { matchesGlob } from 'node:path';
3
+ const builtin = JSON.parse(readFileSync(new URL('../../template/update.defaults.json', import.meta.url), 'utf8'));
4
+ export const defaults = builtin.skipExisting;
5
+ export const sourceDefaults = builtin.mergeSource;
6
+ export function excluded(path) {
7
+ const normalized = path.toLowerCase();
8
+ return normalized.split('/').some((p) => ['.git', '.workbuddy', '.meadmin', 'node_modules', 'dist', 'logs', 'uploadfile'].includes(p)) || /(^|\/)(pnpm-lock\.yaml|package-lock\.json|yarn\.lock|.*\.tsbuildinfo)$/.test(normalized);
9
+ }
10
+ /** 精确路径优先;可证明的目录子集优先;无法区分的冲突规则拒绝猜测。 */
11
+ function resolveRule(path, rules) {
12
+ const entries = Object.entries(rules).filter(([pattern]) => matchesGlob(path, pattern));
13
+ const exact = entries.find(([pattern]) => !/[?*[{]/.test(pattern));
14
+ if (exact)
15
+ return exact[1];
16
+ const prefix = (pattern) => pattern.slice(0, pattern.search(/[?*[{]/));
17
+ const within = (specific, broad) => {
18
+ if (!broad.endsWith('/**') && !broad.endsWith('/**/*.ts'))
19
+ return false;
20
+ const broadPrefix = prefix(broad);
21
+ return !/[?*[{]/.test(broadPrefix) && prefix(specific).startsWith(broadPrefix) && prefix(specific).length > broadPrefix.length;
22
+ };
23
+ const candidates = entries.filter(([pattern]) => !entries.some(([other]) => other !== pattern && within(other, pattern)));
24
+ if (!candidates.length)
25
+ return undefined;
26
+ if (candidates.some(([, value]) => value !== candidates[0][1]))
27
+ throw new Error(`规则冲突:${path},请使用精确路径消除歧义`);
28
+ return candidates[0][1];
29
+ }
30
+ export function skipExisting(path, user = {}) {
31
+ return resolveRule(path, { ...defaults, ...user }) ?? false;
32
+ }
33
+ export function sourceMode(path, user = {}) {
34
+ return resolveRule(path, { ...sourceDefaults, ...user });
35
+ }
36
+ export function validateConfig(value) {
37
+ if (!value || typeof value !== 'object' || Array.isArray(value))
38
+ throw new Error('规则文件必须为JSON对象');
39
+ const config = value;
40
+ if (Object.keys(config).some((k) => !['skipExisting', 'mergeSource'].includes(k)))
41
+ throw new Error('规则仅支持 skipExisting、mergeSource');
42
+ const check = (name, allowed) => {
43
+ const rules = config[name] ?? {};
44
+ if (typeof rules !== 'object' || rules === null || Array.isArray(rules))
45
+ throw new Error(`${name} 必须为对象`);
46
+ for (const [path, mode] of Object.entries(rules)) {
47
+ if (!path || path.startsWith('/') || path.includes('\\') || path.includes(':') || path.split('/').some((part) => part === '..' || part === '.') || !allowed.includes(mode))
48
+ throw new Error(`${name}规则无效:${path}`);
49
+ }
50
+ return rules;
51
+ };
52
+ return { skipExisting: check('skipExisting', [true, false]), mergeSource: check('mergeSource', ['functions', 'exports', false]) };
53
+ }
54
+ export const validateRules = (value) => validateConfig(value).skipExisting;
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXBkYXRlL3J1bGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDdkMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUl4QyxNQUFNLE9BQU8sR0FBZ0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxHQUFHLENBQUMscUNBQXFDLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQy9ILE1BQU0sQ0FBQyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO0FBQzdDLE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDO0FBRWxELE1BQU0sVUFBVSxRQUFRLENBQUMsSUFBWTtJQUNuQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDdEMsT0FBTyxVQUFVLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxZQUFZLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSx3RUFBd0UsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7QUFDdE8sQ0FBQztBQUVELHVDQUF1QztBQUN2QyxTQUFTLFdBQVcsQ0FBSSxJQUFZLEVBQUUsS0FBd0I7SUFDNUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxXQUFXLENB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
@@ -0,0 +1,10 @@
1
+ export type SourceMergeMode = 'functions' | 'exports';
2
+ export type SourceMergeResult = {
3
+ content: string;
4
+ manual: string[];
5
+ changed: boolean;
6
+ };
7
+ /** 只识别静态集成入口;包含类、函数或执行语句的入口仍交由其他规则处理。 */
8
+ export declare function isIntegrationSource(text: string): boolean;
9
+ /** 按函数和静态注册项增量合并,所有坐标和文本均属于节点自身的 SourceFile。 */
10
+ export declare function mergeSource(localText: string, targetText: string, baseText: string | undefined, mode: SourceMergeMode, path?: string): SourceMergeResult;