vona-cli-set-api 1.1.154 → 1.1.155

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.
@@ -1,4 +1,5 @@
1
1
  import { metadataCustomSnippet } from '@cabloy/cli';
2
+ import { mergeMetaIndex } from 'vona-cli-set-api/mergeMetaIndex';
2
3
  import { catchError } from '@cabloy/utils';
3
4
  import fs from 'node:fs';
4
5
 
@@ -9,7 +10,7 @@ declare module '@cabloy/cli' {
9
10
  }
10
11
 
11
12
  const __snippet_import1 = "import { $tableColumns } from 'vona-module-a-ormutils';";
12
- const __snippet_update = "...$tableColumns('<%=argv.moduleResourceName%>', 'name'),";
13
+ const __snippet_table = '<%=argv.moduleResourceName%>';
13
14
 
14
15
  export default metadataCustomSnippet({
15
16
  file: 'src/bean/meta.index.ts',
@@ -35,14 +36,7 @@ export default metadataCustomSnippet({
35
36
  `import { Meta } from 'vona-module-a-meta';\n${code}`,
36
37
  );
37
38
  }
38
- // update
39
- const code = await cli.template.renderContent({ content: __snippet_update });
40
- if (ast.includes('indexes: {}')) {
41
- ast = ast.replace('indexes: {', `indexes: {\n ${code}\n `);
42
- } else {
43
- ast = ast.replace('indexes: {', `indexes: {\n ${code}`);
44
- }
45
- // ok
46
- return ast;
39
+ const table = await cli.template.renderContent({ content: __snippet_table });
40
+ return mergeMetaIndex(ast, table, 'name');
47
41
  },
48
42
  });
@@ -1,4 +1,5 @@
1
1
  import { metadataCustomSnippet } from '@cabloy/cli';
2
+ import { mergeMetaIndex } from 'vona-cli-set-api/mergeMetaIndex';
2
3
  import { catchError } from '@cabloy/utils';
3
4
  import fs from 'node:fs';
4
5
 
@@ -9,7 +10,7 @@ declare module '@cabloy/cli' {
9
10
  }
10
11
 
11
12
  const __snippet_import1 = "import { $tableColumns } from 'vona-module-a-ormutils';";
12
- const __snippet_update = "...$tableColumns('<%=argv.moduleResourceName%>', 'name'),";
13
+ const __snippet_table = '<%=argv.moduleResourceName%>';
13
14
 
14
15
  export default metadataCustomSnippet({
15
16
  file: 'src/bean/meta.index.ts',
@@ -35,14 +36,7 @@ export default metadataCustomSnippet({
35
36
  `import { Meta } from 'vona-module-a-meta';\n${code}`,
36
37
  );
37
38
  }
38
- // update
39
- const code = await cli.template.renderContent({ content: __snippet_update });
40
- if (ast.includes('indexes: {}')) {
41
- ast = ast.replace('indexes: {', `indexes: {\n ${code}\n `);
42
- } else {
43
- ast = ast.replace('indexes: {', `indexes: {\n ${code}`);
44
- }
45
- // ok
46
- return ast;
39
+ const table = await cli.template.renderContent({ content: __snippet_table });
40
+ return mergeMetaIndex(ast, table, 'name');
47
41
  },
48
42
  });
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './lib/beans.ts';
2
2
  export * from './lib/commands.ts';
3
3
  export * from './lib/utils.ts';
4
+ export { mergeMetaIndex } from './lib/mergeMetaIndex.ts';
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ import { catchError, combineApiPathControllerAndActionRaw, replaceTemplate } fro
25
25
  import { getOnionScenesMeta, getOnionMetasMeta, relativeNameToCapitalize } from '@cabloy/module-info';
26
26
  import { toUpperCaseFirstChar, stringToCapitalize, replaceTemplate as replaceTemplate$1 } from '@cabloy/word-utils';
27
27
  import fs from 'node:fs';
28
+ import gogocode from 'gogocode';
28
29
  import { beanFullNameFromOnionName } from 'vona-core';
29
30
 
30
31
  function getEnvMeta(configMeta) {
@@ -2018,6 +2019,120 @@ class CliToolsDeps extends BeanCliBase {
2018
2019
  }
2019
2020
  }
2020
2021
 
2022
+ function propertyName(node) {
2023
+ if (node.computed) return;
2024
+ if (node.key?.type === 'Identifier') return node.key.name;
2025
+ if (node.key?.type === 'StringLiteral') return node.key.value;
2026
+ }
2027
+ function literalValue(node) {
2028
+ return node?.type === 'StringLiteral' ? node.value : undefined;
2029
+ }
2030
+ function indexObject(source) {
2031
+ const file = gogocode(source, {
2032
+ parseOptions: {
2033
+ sourceType: 'module',
2034
+ plugins: ['typescript', 'decorators-legacy']
2035
+ }
2036
+ }).node;
2037
+ const objects = [];
2038
+ for (const statement of file.program.body) {
2039
+ const declaration = statement.declaration ?? statement;
2040
+ for (const decorator of declaration.decorators ?? []) {
2041
+ const call = decorator.expression;
2042
+ if (call.type !== 'CallExpression' || call.callee.name !== 'Meta') continue;
2043
+ const options = call.arguments[0];
2044
+ if (options?.type !== 'ObjectExpression') continue;
2045
+ for (const property of options.properties) {
2046
+ if (property.type === 'ObjectProperty' && propertyName(property) === 'indexes') {
2047
+ if (property.value.type !== 'ObjectExpression') {
2048
+ throw new Error('meta.index indexes must be an object literal');
2049
+ }
2050
+ objects.push(property.value);
2051
+ }
2052
+ }
2053
+ }
2054
+ }
2055
+ if (objects.length !== 1) throw new Error('expected exactly one @Meta indexes object');
2056
+ return objects[0];
2057
+ }
2058
+ function quote(value) {
2059
+ return `'${value.replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`;
2060
+ }
2061
+ function mergeMetaIndex(source, tableName, field) {
2062
+ const indexes = indexObject(source);
2063
+ const declarations = [];
2064
+ const fields = [];
2065
+ for (const property of indexes.properties) {
2066
+ if (property.type === 'ObjectProperty') {
2067
+ const key = propertyName(property);
2068
+ if (!key || key === tableName) {
2069
+ throw new Error(`unsupported index property for ${tableName}`);
2070
+ }
2071
+ continue;
2072
+ }
2073
+ if (property.type !== 'SpreadElement') {
2074
+ throw new Error(`unsupported index declaration for ${tableName}`);
2075
+ }
2076
+ const call = property.argument;
2077
+ if (call.type !== 'CallExpression' || call.callee.name !== '$tableColumns') {
2078
+ throw new Error(`unsupported index spread for ${tableName}`);
2079
+ }
2080
+ const name = literalValue(call.arguments[0]);
2081
+ if (!name) throw new Error(`index table name must be a string literal: ${tableName}`);
2082
+ if (name !== tableName) continue;
2083
+ const value = call.arguments[1];
2084
+ let values;
2085
+ if (value?.type === 'StringLiteral') values = [value];else if (value?.type === 'ArrayExpression') values = value.elements;else throw new Error(`unsupported index fields for ${tableName}`);
2086
+ for (const item of values) {
2087
+ const text = literalValue(item);
2088
+ if (text === undefined) throw new Error(`unsupported index fields for ${tableName}`);
2089
+ for (const spec of text.split(',')) {
2090
+ if (!fields.includes(spec)) fields.push(spec);
2091
+ }
2092
+ }
2093
+ declarations.push(property);
2094
+ }
2095
+ if (!fields.includes(field)) fields.push(field);
2096
+ if (declarations.length === 1) {
2097
+ const value = declarations[0].argument.arguments[1];
2098
+ if (value.type === 'StringLiteral' && fields.length === 1 && value.value === field) return source;
2099
+ if (value.type === 'ArrayExpression') {
2100
+ const values = value.elements.map(literalValue);
2101
+ if (values.length === fields.length && values.every((item, index) => item === fields[index])) {
2102
+ return source;
2103
+ }
2104
+ }
2105
+ }
2106
+ const columns = fields.length === 1 ? quote(fields[0]) : `[${fields.map(quote).join(', ')}]`;
2107
+ const declaration = `...$tableColumns(${quote(tableName)}, ${columns})`;
2108
+ if (!declarations.length) {
2109
+ const content = source.slice(indexes.start + 1, indexes.end - 1);
2110
+ if (content.trim() && !content.trimEnd().endsWith(',')) {
2111
+ throw new Error(`indexes object must use trailing commas before adding ${tableName}`);
2112
+ }
2113
+ return `${source.slice(0, indexes.start + 1)}\n ${declaration},${source.slice(indexes.start + 1)}`;
2114
+ }
2115
+ const patches = declarations.map((item, index) => {
2116
+ if (!index) return {
2117
+ start: item.start,
2118
+ end: item.end,
2119
+ text: declaration
2120
+ };
2121
+ let end = item.end;
2122
+ while (/\s/.test(source[end]) && end < indexes.end) end++;
2123
+ if (source[end] === ',') end++;
2124
+ return {
2125
+ start: item.start,
2126
+ end,
2127
+ text: ''
2128
+ };
2129
+ });
2130
+ for (const patch of patches.reverse()) {
2131
+ source = `${source.slice(0, patch.start)}${patch.text}${source.slice(patch.end)}`;
2132
+ }
2133
+ return source;
2134
+ }
2135
+
2021
2136
  class CliToolsMasterDetail extends BeanCliBase {
2022
2137
  async execute() {
2023
2138
  await super.execute();
@@ -2153,13 +2268,11 @@ class CliToolsMasterDetail extends BeanCliBase {
2153
2268
  const {
2154
2269
  argv
2155
2270
  } = this.context;
2156
- await this._patchFileByMarker({
2157
- fileName: this._detailPaths().metaIndex,
2158
- existsNeedle: `'${argv.fk}'`,
2159
- marker: ' indexes: {\n',
2160
- line: this._detailMetaIndexLine(),
2161
- shapeName: 'detail meta.index'
2162
- });
2271
+ const fileName = this._detailPaths().metaIndex;
2272
+ const content = this._readFile(fileName);
2273
+ const table = this.helper.combineModuleNameAndResource(argv.detailModuleInfo.relativeName, argv.detailResourceName);
2274
+ const updated = mergeMetaIndex(content, table, argv.fk);
2275
+ if (updated !== content) await this._saveFile(fileName, updated);
2163
2276
  }
2164
2277
  _detailMetaVersionLine() {
2165
2278
  const {
@@ -2167,12 +2280,6 @@ class CliToolsMasterDetail extends BeanCliBase {
2167
2280
  } = this.context;
2168
2281
  return ` table.tableIdentity(entity${argv.detailResourceNameCapitalize}.${argv.fk}).comment(entity${argv.detailResourceNameCapitalize}.$comment.${argv.fk});\n`;
2169
2282
  }
2170
- _detailMetaIndexLine() {
2171
- const {
2172
- argv
2173
- } = this.context;
2174
- return ` ...$tableColumns('${this.helper.combineModuleNameAndResource(argv.detailModuleInfo.relativeName, argv.detailResourceName)}', '${argv.fk}'),\n`;
2175
- }
2176
2283
  async _patchFileByMarker({
2177
2284
  fileName,
2178
2285
  existsNeedle,
@@ -3994,4 +4101,4 @@ const commands = {
3994
4101
  }
3995
4102
  };
3996
4103
 
3997
- export { beans, commands, copyTemplateFile, copyTemplateIfNeed, generateConfigDefine, getAbsolutePathOfModule, getEnvMeta, getImportEsm, getNodeEnv, getOutDir, getOutReleasesDir, loadJSONFile, pathToHref, requireModule, saveJSONFile };
4104
+ export { beans, commands, copyTemplateFile, copyTemplateIfNeed, generateConfigDefine, getAbsolutePathOfModule, getEnvMeta, getImportEsm, getNodeEnv, getOutDir, getOutReleasesDir, loadJSONFile, mergeMetaIndex, pathToHref, requireModule, saveJSONFile };
@@ -44,7 +44,6 @@ export declare class CliToolsMasterDetail extends BeanCliBase {
44
44
  private _patchDetailMetaVersion;
45
45
  private _patchDetailMetaIndex;
46
46
  private _detailMetaVersionLine;
47
- private _detailMetaIndexLine;
48
47
  private _patchFileByMarker;
49
48
  private _patchFileContent;
50
49
  private _renderMasterDetailDtos;
@@ -0,0 +1 @@
1
+ export declare function mergeMetaIndex(source: string, tableName: string, field: string): string;
@@ -1,8 +1,9 @@
1
1
  import { metadataCustomSnippet } from '@cabloy/cli';
2
+ import { mergeMetaIndex } from 'vona-cli-set-api/mergeMetaIndex';
2
3
  import { catchError } from '@cabloy/utils';
3
4
  import fs from 'node:fs';
4
5
  const __snippet_import1 = "import { $tableColumns } from 'vona-module-a-ormutils';";
5
- const __snippet_update = "...$tableColumns('<%=argv.moduleResourceName%>', 'name'),";
6
+ const __snippet_table = '<%=argv.moduleResourceName%>';
6
7
  export default metadataCustomSnippet({
7
8
  file: 'src/bean/meta.index.ts',
8
9
  language: 'plain',
@@ -21,15 +22,7 @@ export default metadataCustomSnippet({
21
22
  const code = await cli.template.renderContent({ content: __snippet_import1 });
22
23
  ast = ast.replace("import { Meta } from 'vona-module-a-meta';", `import { Meta } from 'vona-module-a-meta';\n${code}`);
23
24
  }
24
- // update
25
- const code = await cli.template.renderContent({ content: __snippet_update });
26
- if (ast.includes('indexes: {}')) {
27
- ast = ast.replace('indexes: {', `indexes: {\n ${code}\n `);
28
- }
29
- else {
30
- ast = ast.replace('indexes: {', `indexes: {\n ${code}`);
31
- }
32
- // ok
33
- return ast;
25
+ const table = await cli.template.renderContent({ content: __snippet_table });
26
+ return mergeMetaIndex(ast, table, 'name');
34
27
  },
35
28
  });
@@ -1,8 +1,9 @@
1
1
  import { metadataCustomSnippet } from '@cabloy/cli';
2
+ import { mergeMetaIndex } from 'vona-cli-set-api/mergeMetaIndex';
2
3
  import { catchError } from '@cabloy/utils';
3
4
  import fs from 'node:fs';
4
5
  const __snippet_import1 = "import { $tableColumns } from 'vona-module-a-ormutils';";
5
- const __snippet_update = "...$tableColumns('<%=argv.moduleResourceName%>', 'name'),";
6
+ const __snippet_table = '<%=argv.moduleResourceName%>';
6
7
  export default metadataCustomSnippet({
7
8
  file: 'src/bean/meta.index.ts',
8
9
  language: 'plain',
@@ -21,15 +22,7 @@ export default metadataCustomSnippet({
21
22
  const code = await cli.template.renderContent({ content: __snippet_import1 });
22
23
  ast = ast.replace("import { Meta } from 'vona-module-a-meta';", `import { Meta } from 'vona-module-a-meta';\n${code}`);
23
24
  }
24
- // update
25
- const code = await cli.template.renderContent({ content: __snippet_update });
26
- if (ast.includes('indexes: {}')) {
27
- ast = ast.replace('indexes: {', `indexes: {\n ${code}\n `);
28
- }
29
- else {
30
- ast = ast.replace('indexes: {', `indexes: {\n ${code}`);
31
- }
32
- // ok
33
- return ast;
25
+ const table = await cli.template.renderContent({ content: __snippet_table });
26
+ return mergeMetaIndex(ast, table, 'name');
34
27
  },
35
28
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vona-cli-set-api",
3
- "version": "1.1.154",
4
- "gitHead": "94435329d69fc19d0d15e4e10c3b1111e99ab1cf",
3
+ "version": "1.1.155",
4
+ "gitHead": "8d575dd958be6aa16daa249bdbdb024d20d0789d",
5
5
  "description": "vona cli-set-api",
6
6
  "keywords": [
7
7
  "framework",
@@ -25,6 +25,10 @@
25
25
  ],
26
26
  "default": "./dist/index.js"
27
27
  },
28
+ "./mergeMetaIndex": {
29
+ "types": "./dist/lib/mergeMetaIndex.d.ts",
30
+ "default": "./dist/index.js"
31
+ },
28
32
  "./package.json": "./package.json"
29
33
  },
30
34
  "publishConfig": {