@cabloy/cli 3.0.66 → 3.0.68

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,291 +0,0 @@
1
- import fs from 'node:fs';
2
- import { createRequire } from 'node:module';
3
- import path from 'node:path';
4
- import { catchError } from '@cabloy/utils';
5
- import ejs from '@zhennann/ejs';
6
- import { globby } from 'globby';
7
- import gogocode from 'gogocode';
8
- import isTextOrBinary from 'istextorbinary';
9
- import { commandsConfig } from "../config.js";
10
- export class LocalTemplate {
11
- cli;
12
- constructor(cli) {
13
- this.cli = cli;
14
- }
15
- get options() {
16
- return this.cli.options;
17
- }
18
- get context() {
19
- return this.cli.options.context;
20
- }
21
- get console() {
22
- return this.cli.console;
23
- }
24
- get helper() {
25
- return this.cli.helper;
26
- }
27
- get moduleConfig() {
28
- return commandsConfig;
29
- }
30
- get fileMapping() {
31
- return this.moduleConfig.template.render.fileMapping;
32
- }
33
- get filesIgnore() {
34
- return this.moduleConfig.template.render.ignore;
35
- }
36
- resolveTemplatePath(setName, _path) {
37
- if (path.isAbsolute(_path))
38
- return _path;
39
- const sets = this.moduleConfig.sets;
40
- const require = createRequire(import.meta.url);
41
- const modulePath = require.resolve(`${sets[process.env.CabloyCliBrandName][setName]}/package.json`);
42
- return path.join(path.dirname(modulePath), 'cli/templates', _path);
43
- }
44
- async renderBoilerplateAndSnippets({ targetDir, setName, snippetsPath, boilerplatePath, }) {
45
- await this.helper.ensureDir(targetDir);
46
- // first
47
- if (snippetsPath) {
48
- const snippetsDir = this.resolveTemplatePath(setName, snippetsPath);
49
- await this.applySnippets(targetDir, snippetsDir);
50
- }
51
- // then
52
- if (boilerplatePath) {
53
- const templateDir = this.resolveTemplatePath(setName, boilerplatePath);
54
- await this.renderDir(targetDir, templateDir);
55
- }
56
- }
57
- async renderDir(targetDir, templateDir) {
58
- const { argv } = this.context;
59
- // files
60
- const files = await globby('**/*', {
61
- cwd: templateDir,
62
- dot: true,
63
- onlyFiles: false,
64
- });
65
- // loop
66
- for (const file of files) {
67
- const { dir: dirname, base: basename } = path.parse(file);
68
- if (this.filesIgnore.includes(basename))
69
- continue;
70
- const templateFile = path.join(templateDir, file);
71
- const fileName = this.parseFileBaseName(basename);
72
- const parentPath = path.join(targetDir, dirname);
73
- const targetFile = path.join(parentPath, this.replaceTemplate(fileName, argv));
74
- await this.renderFile({ targetFile, templateFile });
75
- if (fileName !== '.gitkeep') {
76
- await this.helper.removeGitkeep(parentPath);
77
- }
78
- }
79
- return files;
80
- }
81
- replaceTemplate(content, scope) {
82
- if (!content)
83
- return null;
84
- return content.toString().replace(/(\\)?\{\{ *([\w.]+) *\}\}/g, (block, skip, key) => {
85
- if (skip) {
86
- return block.substring(skip.length);
87
- }
88
- const value = this.getProperty(scope, key);
89
- return value !== undefined ? value : '';
90
- });
91
- }
92
- getProperty(obj, name, sep) {
93
- return this._getProperty(obj, name, sep, false);
94
- }
95
- _getProperty(obj, name, sep, forceObject) {
96
- if (!obj)
97
- return undefined;
98
- const names = name.split(sep || '.');
99
- // loop
100
- for (const name of names) {
101
- if (obj[name] === undefined || obj[name] === null) {
102
- if (forceObject) {
103
- obj[name] = {};
104
- }
105
- else {
106
- obj = obj[name];
107
- break;
108
- }
109
- }
110
- obj = obj[name];
111
- }
112
- return obj;
113
- }
114
- parseFileBaseName(basename) {
115
- let fileName = this.fileMapping[basename] || basename;
116
- if (fileName.lastIndexOf('_') === fileName.length - 1) {
117
- fileName = fileName.substring(0, fileName.length - 1);
118
- }
119
- return fileName;
120
- }
121
- async renderFile({ targetFile, templateFile }) {
122
- const stats = fs.lstatSync(templateFile);
123
- if (stats.isSymbolicLink()) {
124
- const target = fs.readlinkSync(templateFile);
125
- fs.symlinkSync(target, targetFile);
126
- await this.console.log(`${targetFile} link to ${target}`);
127
- }
128
- else if (stats.isDirectory()) {
129
- await this.helper.ensureDir(targetFile);
130
- }
131
- else if (stats.isFile()) {
132
- const content = fs.readFileSync(templateFile);
133
- await this.console.log(`write to ${targetFile}`);
134
- // check if content is a text file
135
- let result;
136
- let changed;
137
- if (!isTextOrBinary.isTextSync(templateFile, content)) {
138
- result = content;
139
- }
140
- else {
141
- const _content = content.toString('utf8');
142
- result = await this.renderContent({ content: _content });
143
- changed = _content !== result;
144
- }
145
- // save
146
- fs.writeFileSync(targetFile, result);
147
- // format
148
- if (changed && !this.context.argv.noformat) {
149
- await catchError(() => {
150
- return this.helper.formatFile({ fileName: targetFile, logPrefix: 'format: ' });
151
- });
152
- }
153
- }
154
- else {
155
- await this.console.log(`ignore ${templateFile}, only support file, dir, symlink`);
156
- }
157
- }
158
- async renderContent({ content }) {
159
- if (!content)
160
- return content;
161
- const data = this.getEjsData();
162
- const options = this.getEjsOptions();
163
- return await ejs.render(content, data, options);
164
- }
165
- getEjsOptions() {
166
- return {
167
- async: true,
168
- cache: false,
169
- compileDebug: true,
170
- outputFunctionName: 'echo',
171
- rmWhitespace: false,
172
- };
173
- }
174
- getEjsData() {
175
- return {
176
- cli: this.cli,
177
- ...this.context,
178
- };
179
- }
180
- getAstData(ast, snippet) {
181
- return {
182
- cli: this.cli,
183
- ast,
184
- snippet,
185
- ...this.context,
186
- };
187
- }
188
- getInitData(targetFile) {
189
- return {
190
- cli: this.cli,
191
- targetFile,
192
- ...this.context,
193
- };
194
- }
195
- async applySnippets(targetDir, snippetsDir) {
196
- // snippets
197
- let files = await globby('*.{cjs,ts}', {
198
- cwd: snippetsDir,
199
- onlyFiles: true,
200
- });
201
- // snippets sort
202
- files = files
203
- .filter(item => item[0] !== '-')
204
- .sort((a, b) => this._parseSnippetFilePrefix(a) - this._parseSnippetFilePrefix(b));
205
- // for
206
- for (const file of files) {
207
- const snippetTemplatePath = path.join(snippetsDir, file);
208
- await this._loadSnippetInstance(snippetTemplatePath, async (snippet) => {
209
- if (!snippet.file) {
210
- throw new Error(`should provider file path for: ${file}`);
211
- }
212
- let fileName;
213
- if (typeof snippet.file === 'function') {
214
- fileName = snippet.file(this.getEjsData());
215
- }
216
- else {
217
- fileName = await this.renderContent({ content: snippet.file });
218
- }
219
- if (!fileName) {
220
- // means ignore, so do nothing
221
- }
222
- else {
223
- const targetFile = path.join(targetDir, fileName);
224
- await this.applySnippet(targetFile, snippet);
225
- }
226
- });
227
- }
228
- }
229
- async _loadSnippetInstance(snippetTemplatePath, fn) {
230
- return await this.helper.importDynamic(snippetTemplatePath, instance => {
231
- return fn(instance.default);
232
- });
233
- }
234
- async applySnippet(targetFile, snippet) {
235
- await this.console.log(`apply changes to ${targetFile}`);
236
- // source code
237
- let sourceCode;
238
- if (fs.existsSync(targetFile)) {
239
- sourceCode = fs.readFileSync(targetFile);
240
- sourceCode = sourceCode.toString('utf8');
241
- }
242
- else {
243
- if (!snippet.init) {
244
- throw new Error(`should provider init content for: ${targetFile}`);
245
- }
246
- let content;
247
- if (typeof snippet.init === 'function') {
248
- content = await snippet.init(this.getInitData(targetFile));
249
- }
250
- else {
251
- content = snippet.init;
252
- }
253
- sourceCode = await this.renderContent({ content });
254
- }
255
- // language
256
- const language = snippet.language;
257
- // transform
258
- let outputCode;
259
- if (language === 'plain') {
260
- const ast = sourceCode;
261
- const outAst = await snippet.transform(this.getAstData(ast, snippet));
262
- outputCode = outAst;
263
- }
264
- else if (language === 'json') {
265
- const ast = JSON.parse(sourceCode);
266
- const outAst = await snippet.transform(this.getAstData(ast, snippet));
267
- outputCode = outAst === undefined ? outAst : JSON.stringify(outAst, null, 2);
268
- }
269
- else {
270
- const ast = gogocode(sourceCode, { parseOptions: snippet.parseOptions });
271
- const outAst = await snippet.transform(this.getAstData(ast, snippet));
272
- outputCode = outAst === undefined ? outAst : outAst.root().generate();
273
- }
274
- if (outputCode !== undefined) {
275
- // save
276
- fs.writeFileSync(targetFile, outputCode);
277
- // format
278
- if (!this.context.argv.noformat) {
279
- await catchError(() => {
280
- return this.helper.formatFile({ fileName: targetFile, logPrefix: 'format: ' });
281
- });
282
- }
283
- }
284
- }
285
- _parseSnippetFilePrefix(fileName) {
286
- const num = fileName.split('-')[0];
287
- if (!num || Number.isNaN(num))
288
- return 10000;
289
- return Number.parseInt(num);
290
- }
291
- }
package/dist/registry.js DELETED
@@ -1,14 +0,0 @@
1
- import NPMConfig from '@npmcli/config';
2
- import npmDefinitions from '@npmcli/config/lib/definitions/index.js';
3
- let __registry;
4
- export async function getRegistry() {
5
- if (!__registry) {
6
- const npmConfig = new NPMConfig(Object.assign({ npmPath: '' }, npmDefinitions));
7
- await npmConfig.load();
8
- __registry = npmConfig.get('registry') || 'https://registry.npmjs.org/';
9
- if (!__registry.endsWith('/')) {
10
- __registry = `${__registry}/`;
11
- }
12
- }
13
- return __registry;
14
- }
package/dist/start.js DELETED
@@ -1,93 +0,0 @@
1
- import CommonBin from '@zhennann/common-bin';
2
- import { BeanCli } from "./lib/bean.cli.js";
3
- import { CliCommand } from "./lib/cli.js";
4
- import { collectCommands } from "./lib/commands.js";
5
- import { checkForUpdates } from "./utils.js";
6
- const DISPATCH = Symbol.for('eb:Command#dispatch');
7
- const PARSE = Symbol.for('eb:Command#parse');
8
- export class CabloyCommand extends CommonBin {
9
- brandName;
10
- defaultSetName;
11
- constructor(brandName, rawArgv) {
12
- super(rawArgv);
13
- this.usage = `Usage: ${brandName} [command] [options]`;
14
- this.defaultSetName = brandName === 'zova' ? 'front' : 'api';
15
- this.brandName = brandName;
16
- process.env.CabloyCliBrandName = brandName;
17
- }
18
- async [DISPATCH]() {
19
- const parsed = await this[PARSE](this.rawArgv);
20
- if (parsed._.length === 0) {
21
- await super[DISPATCH]();
22
- return;
23
- }
24
- // checkForUpdates
25
- checkForUpdates(`${this.brandName}-cli`);
26
- // collectCommands
27
- await collectCommands();
28
- // cli
29
- await this._handleCli();
30
- }
31
- async _handleCli() {
32
- // get parsed argument without handling helper and version
33
- const parsed = await this[PARSE](this.rawArgv);
34
- // argv
35
- const argv = {
36
- projectPath: process.cwd(),
37
- };
38
- // indexBrandName
39
- const indexBrandName = this.rawArgv.indexOf(this.brandName);
40
- // cli
41
- const indexCommand = indexBrandName > -1 ? indexBrandName + 1 : 0;
42
- Object.assign(argv, this._prepareCliFullName(parsed._[indexCommand]));
43
- // cli meta
44
- const context = { brandName: this.brandName, argv };
45
- const beanCli = new BeanCli();
46
- const meta = await beanCli.meta({ context });
47
- // cli run
48
- const rawArgv = this.rawArgv.slice();
49
- if (indexBrandName > -1) {
50
- rawArgv.splice(0, indexBrandName + 2);
51
- }
52
- else {
53
- rawArgv.splice(0, 1);
54
- }
55
- const command = new CliCommand(rawArgv, { meta, argv });
56
- await command[DISPATCH]();
57
- // force exit
58
- process.exit(0);
59
- }
60
- _prepareCliFullName(cliName) {
61
- if (!cliName) {
62
- return { cliFullName: `${this.defaultSetName}:default:list` };
63
- // throw new Error('Please specify the cli name');
64
- }
65
- const parts = cliName.split(':');
66
- if (parts.length === 1) {
67
- // means show module's commands
68
- parts[1] = '';
69
- }
70
- if (parts.length === 2) {
71
- if (parts[1]) {
72
- // means show group's commands
73
- parts[2] = '';
74
- }
75
- else {
76
- // means show module's commands
77
- if (!parts[0])
78
- parts[0] = this.defaultSetName;
79
- return { cliFullName: `${this.defaultSetName}:default:list`, set: parts[0] };
80
- }
81
- }
82
- if (!parts[0])
83
- parts[0] = this.defaultSetName;
84
- if (!parts[1])
85
- parts[1] = 'default';
86
- if (!parts[2]) {
87
- // means show group's commands
88
- return { cliFullName: `${this.defaultSetName}:default:list`, set: parts[0], group: parts[1] };
89
- }
90
- // default
91
- return { cliFullName: parts.join(':') };
92
- }
93
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1,4 +0,0 @@
1
- export * from "./argv.js";
2
- export * from "./console.js";
3
- export * from "./helper.js";
4
- export * from "./template.js";
@@ -1,3 +0,0 @@
1
- export function metadataCustomSnippet(snippet) {
2
- return snippet;
3
- }
package/dist/utils.js DELETED
@@ -1,46 +0,0 @@
1
- import { createRequire } from 'node:module';
2
- import boxen from 'boxen';
3
- import chalk from 'chalk';
4
- import semver from 'semver';
5
- import urllib from 'urllib';
6
- import { getRegistry } from "./registry.js";
7
- const boxenOptions = { padding: 1, margin: 1, align: 'center', borderColor: 'yellow', borderStyle: 'round' };
8
- export async function checkForUpdates(packageName) {
9
- try {
10
- // version old
11
- const require = createRequire(import.meta.url);
12
- const pkg = require(`${packageName}/package.json`);
13
- const versionOld = pkg.version;
14
- // version new
15
- const info = await getPackageInfo(packageName);
16
- const versionNew = info.version;
17
- // check
18
- const lt = semver.lt(versionOld, versionNew);
19
- if (!lt)
20
- return;
21
- // log
22
- let message = `[${chalk.keyword('cyan')(packageName)}] new version available: ${chalk.keyword('yellow')(versionOld)} → ${chalk.keyword('orange')(versionNew)}`;
23
- message += `\nRun ${chalk.keyword('orange')(`> pnpm add -g ${packageName} <`)} to update!`;
24
- // eslint-disable-next-line
25
- console.log('\n' + boxen(message, boxenOptions));
26
- }
27
- catch (_err) {
28
- // donothing
29
- }
30
- }
31
- export async function getPackageInfo(packageName) {
32
- const registry = await getRegistry();
33
- const result = await urllib.request(`${registry}${packageName}/latest`, {
34
- dataType: 'json',
35
- followRedirect: true,
36
- maxRedirects: 5,
37
- });
38
- if (result.status !== 200) {
39
- const message = `npm info ${packageName} got error: ${result.status}, ${result.data.reason}`;
40
- throw new Error(message);
41
- }
42
- return result.data;
43
- }
44
- export function patchFlavor(flavor) {
45
- return Array.isArray(flavor) ? flavor[flavor.length - 1] : flavor;
46
- }