@flarum/cli 2.0.0-beta.8 → 2.0.0
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/LICENSE +1 -1
- package/README.md +181 -49
- package/bin/run +2 -1
- package/bin/splitsh-lite-darwin +0 -0
- package/bin/splitsh-lite-linux +0 -0
- package/boilerplate/skeleton/extension/.gitattributes +16 -14
- package/boilerplate/skeleton/extension/.github/workflows/backend.yml +2 -6
- package/boilerplate/skeleton/extension/.github/workflows/frontend.yml +4 -6
- package/boilerplate/skeleton/extension/LICENSE.md +1 -1
- package/boilerplate/skeleton/extension/README.md +1 -1
- package/boilerplate/skeleton/extension/composer.json +6 -4
- package/boilerplate/skeleton/extension/extend.php +2 -2
- package/boilerplate/skeleton/extension/js/admin.ts +2 -0
- package/boilerplate/skeleton/extension/js/forum.ts +2 -0
- package/boilerplate/skeleton/extension/js/package.json +5 -1
- package/boilerplate/skeleton/extension/js/src/admin/index.ts +5 -0
- package/boilerplate/skeleton/extension/js/src/common/index.ts +5 -0
- package/boilerplate/skeleton/extension/js/src/forum/index.ts +5 -0
- package/boilerplate/skeleton/extension/js/tsconfig.json +10 -2
- package/boilerplate/skeleton/extension/locale/en.yml +1 -1
- package/boilerplate/skeleton/extension/tests/phpunit.integration.xml +1 -0
- package/lib/base-command.d.ts +3 -1
- package/lib/base-command.js +44 -31
- package/lib/boilersmith/io.d.ts +28 -8
- package/lib/boilersmith/io.js +4 -2
- package/lib/boilersmith/paths.d.ts +2 -2
- package/lib/boilersmith/paths.js +7 -7
- package/lib/boilersmith/scaffolding/audit-step-factory.js +11 -11
- package/lib/boilersmith/scaffolding/infra-step-factory.js +2 -2
- package/lib/boilersmith/scaffolding/init-step-factory.js +5 -5
- package/lib/boilersmith/scaffolding/module.d.ts +28 -8
- package/lib/boilersmith/scaffolding/module.js +59 -17
- package/lib/boilersmith/scaffolding/scaffolder.d.ts +4 -1
- package/lib/boilersmith/scaffolding/scaffolder.js +32 -32
- package/lib/boilersmith/scaffolding/template-param.d.ts +1 -1
- package/lib/boilersmith/scaffolding/template-param.js +2 -2
- package/lib/boilersmith/step-manager.d.ts +0 -1
- package/lib/boilersmith/step-manager.js +10 -20
- package/lib/boilersmith/steps/stub-base.js +3 -3
- package/lib/boilersmith/utils/clone-and-fill.js +1 -1
- package/lib/boilersmith/utils/commit-async.d.ts +2 -0
- package/lib/boilersmith/utils/commit-async.js +15 -0
- package/lib/boilersmith/utils/read-tpl.js +2 -2
- package/lib/commands/audit/infra.d.ts +1 -1
- package/lib/commands/audit/infra.js +30 -8
- package/lib/commands/infra.d.ts +2 -2
- package/lib/commands/infra.js +18 -12
- package/lib/commands/init.d.ts +1 -1
- package/lib/commands/init.js +4 -2
- package/lib/commands/make/backend/api-controller.js +1 -2
- package/lib/commands/make/backend/api-serializer-attributes.js +1 -2
- package/lib/commands/make/backend/command.js +1 -2
- package/lib/commands/make/backend/event-listener.js +1 -2
- package/lib/commands/make/backend/handler.js +2 -5
- package/lib/commands/make/backend/integration-test.js +2 -4
- package/lib/commands/make/backend/migration.js +1 -2
- package/lib/commands/make/backend/model.js +1 -2
- package/lib/commands/make/backend/policy.js +1 -2
- package/lib/commands/make/backend/route.js +1 -2
- package/lib/commands/make/backend/service-provider.js +1 -2
- package/lib/commands/make/frontend/model.js +2 -5
- package/lib/commands/monorepo/create.d.ts +15 -0
- package/lib/commands/monorepo/create.js +20 -0
- package/lib/commands/monorepo/split.d.ts +15 -0
- package/lib/commands/monorepo/split.js +19 -0
- package/lib/commands/update/js-imports.js +1 -2
- package/lib/help.js +1 -1
- package/lib/providers/php-provider.js +2 -2
- package/lib/steps/gen-ext-scaffolder.d.ts +2 -2
- package/lib/steps/gen-ext-scaffolder.js +187 -53
- package/lib/steps/js/base.js +2 -4
- package/lib/steps/js/model.js +4 -4
- package/lib/steps/misc/composer.js +2 -2
- package/lib/steps/misc/git.d.ts +1 -1
- package/lib/steps/misc/git.js +2 -2
- package/lib/steps/misc/npm.d.ts +11 -0
- package/lib/steps/misc/npm.js +19 -0
- package/lib/steps/misc/yarn.js +2 -2
- package/lib/steps/monorepo/create.d.ts +17 -0
- package/lib/steps/monorepo/create.js +186 -0
- package/lib/steps/monorepo/split.d.ts +14 -0
- package/lib/steps/monorepo/split.js +99 -0
- package/lib/steps/stubs/backend/api-controller.d.ts +1 -1
- package/lib/steps/stubs/backend/api-controller.js +3 -0
- package/lib/steps/stubs/backend/api-serializer.d.ts +1 -1
- package/lib/steps/stubs/backend/api-serializer.js +3 -0
- package/lib/steps/stubs/backend/command.d.ts +0 -5
- package/lib/steps/stubs/backend/command.js +1 -0
- package/lib/steps/stubs/backend/event-listener.d.ts +1 -1
- package/lib/steps/stubs/backend/event-listener.js +2 -0
- package/lib/steps/stubs/backend/handler-command.d.ts +1 -1
- package/lib/steps/stubs/backend/handler-command.js +1 -0
- package/lib/steps/stubs/backend/handler.d.ts +1 -1
- package/lib/steps/stubs/backend/handler.js +4 -0
- package/lib/steps/stubs/backend/integration-test.d.ts +1 -1
- package/lib/steps/stubs/backend/integration-test.js +2 -0
- package/lib/steps/stubs/backend/job.d.ts +1 -1
- package/lib/steps/stubs/backend/job.js +1 -0
- package/lib/steps/stubs/backend/migration.js +6 -3
- package/lib/steps/stubs/backend/model.d.ts +1 -1
- package/lib/steps/stubs/backend/model.js +1 -0
- package/lib/steps/stubs/backend/policy.d.ts +1 -1
- package/lib/steps/stubs/backend/policy.js +2 -0
- package/lib/steps/stubs/backend/repository.d.ts +1 -1
- package/lib/steps/stubs/backend/repository.js +2 -0
- package/lib/steps/stubs/backend/service-provider.d.ts +1 -1
- package/lib/steps/stubs/backend/service-provider.js +1 -0
- package/lib/steps/stubs/backend/validator.d.ts +1 -1
- package/lib/steps/stubs/backend/validator.js +1 -0
- package/lib/steps/stubs/flarum-base.js +1 -1
- package/lib/steps/stubs/frontend/component.d.ts +0 -5
- package/lib/steps/stubs/frontend/component.js +1 -0
- package/lib/steps/stubs/frontend/modal.d.ts +0 -5
- package/lib/steps/stubs/frontend/modal.js +1 -0
- package/lib/steps/stubs/frontend/model.d.ts +0 -5
- package/lib/steps/stubs/frontend/model.js +1 -0
- package/lib/steps/stubs/js-base.js +8 -5
- package/lib/steps/stubs/php-base.js +10 -8
- package/lib/steps/update/js-imports.js +8 -2
- package/lib/utils/composer.d.ts +1 -0
- package/lib/utils/migration.js +3 -1
- package/lib/utils/monorepo.d.ts +24 -0
- package/lib/utils/monorepo.js +24 -0
- package/lib/utils/validation.d.ts +2 -0
- package/lib/utils/validation.js +6 -0
- package/oclif.manifest.json +1 -1
- package/package.json +11 -5
- package/php-subsystem/composer.json +9 -9
- package/php-subsystem/composer.lock +64 -71
- package/php-subsystem/vendor/composer/installed.json +54 -61
- package/php-subsystem/vendor/nikic/php-parser/README.md +55 -59
- package/php-subsystem/vendor/nikic/php-parser/composer.json +39 -39
- package/php-subsystem/vendor/nikic/php-parser/grammar/README.md +17 -20
package/lib/base-command.js
CHANGED
|
@@ -4,16 +4,18 @@ exports.LocationType = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const core_1 = require("@oclif/core");
|
|
6
6
|
const cli_ux_1 = (0, tslib_1.__importDefault)(require("cli-ux"));
|
|
7
|
-
const
|
|
7
|
+
const path_1 = require("path");
|
|
8
8
|
const globby_1 = (0, tslib_1.__importDefault)(require("globby"));
|
|
9
|
-
const
|
|
10
|
-
const
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
11
|
const io_1 = require("boilersmith/io");
|
|
12
12
|
const step_manager_1 = require("boilersmith/step-manager");
|
|
13
13
|
const paths_1 = require("boilersmith/paths");
|
|
14
14
|
const php_provider_1 = require("./providers/php-provider");
|
|
15
15
|
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
|
|
16
16
|
const errors_1 = require("@oclif/errors");
|
|
17
|
+
const monorepo_1 = require("./utils/monorepo");
|
|
18
|
+
const mem_fs_1 = require("mem-fs");
|
|
17
19
|
var LocationType;
|
|
18
20
|
(function (LocationType) {
|
|
19
21
|
LocationType[LocationType["FLARUM_EXTENSION"] = 0] = "FLARUM_EXTENSION";
|
|
@@ -23,7 +25,7 @@ var LocationType;
|
|
|
23
25
|
class BaseCommand extends core_1.Command {
|
|
24
26
|
constructor() {
|
|
25
27
|
super(...arguments);
|
|
26
|
-
this.STUB_PATH = (0,
|
|
28
|
+
this.STUB_PATH = (0, path_1.resolve)(__dirname, '../boilerplate/stubs/');
|
|
27
29
|
this.dry = false;
|
|
28
30
|
this.requireExistingExtension = true;
|
|
29
31
|
}
|
|
@@ -51,10 +53,9 @@ class BaseCommand extends core_1.Command {
|
|
|
51
53
|
requestedDir: path,
|
|
52
54
|
package: extRoot,
|
|
53
55
|
});
|
|
54
|
-
const phpProvider = new php_provider_1.PhpSubsystemProvider((0,
|
|
55
|
-
const out = await this.steps(new step_manager_1.StepManager())
|
|
56
|
-
|
|
57
|
-
const errorMessages = out.messages.filter(m => m.type === 'error');
|
|
56
|
+
const phpProvider = new php_provider_1.PhpSubsystemProvider((0, path_1.resolve)(__dirname, '../php-subsystem/index.php'));
|
|
57
|
+
const out = await this.steps(new step_manager_1.StepManager(), extRoot).run(paths, this.genIO(), { php: phpProvider }, this.dry);
|
|
58
|
+
const errorMessages = out.messages.filter((m) => m.type === 'error');
|
|
58
59
|
this.log('\n\n');
|
|
59
60
|
if (out.succeeded && errorMessages.length === 0) {
|
|
60
61
|
this.log(chalk_1.default.bold(chalk_1.default.underline(chalk_1.default.green('Success! The following steps were completed:'))));
|
|
@@ -66,7 +67,7 @@ class BaseCommand extends core_1.Command {
|
|
|
66
67
|
}
|
|
67
68
|
this.log(chalk_1.default.bold(chalk_1.default.yellow('The steps that completed were:')));
|
|
68
69
|
}
|
|
69
|
-
else if (out.error
|
|
70
|
+
else if (out.error.startsWith('EEXIT:')) {
|
|
70
71
|
this.log(chalk_1.default.bold(chalk_1.default.underline(chalk_1.default.red('Exiting.'))));
|
|
71
72
|
if (out.stepsRan.length > 0) {
|
|
72
73
|
this.log(chalk_1.default.bold(chalk_1.default.yellow('Before the exit, the following steps were completed:')));
|
|
@@ -86,7 +87,7 @@ class BaseCommand extends core_1.Command {
|
|
|
86
87
|
for (const stepName of out.stepsRan)
|
|
87
88
|
this.log(`- ${chalk_1.default.dim(stepName)}`);
|
|
88
89
|
this.log('');
|
|
89
|
-
const nonErrorMessages = out.messages.filter(m => m.type !== 'error');
|
|
90
|
+
const nonErrorMessages = out.messages.filter((m) => m.type !== 'error');
|
|
90
91
|
if (nonErrorMessages.length > 0) {
|
|
91
92
|
this.log('');
|
|
92
93
|
this.log('The following messages were generated during execution:');
|
|
@@ -118,45 +119,53 @@ class BaseCommand extends core_1.Command {
|
|
|
118
119
|
return new io_1.PromptsIO({}, [], this.flags['no-interaction'], errors_1.exit);
|
|
119
120
|
}
|
|
120
121
|
monorepoPaths(options) {
|
|
122
|
+
var _a, _b;
|
|
121
123
|
try {
|
|
122
|
-
const monorepoConfig = (0,
|
|
123
|
-
const contents = JSON.parse(monorepoConfig.toString());
|
|
124
|
+
const monorepoConfig = (0, monorepo_1.getMonorepoConf)((0, mem_fs_1.create)(), new paths_1.NodePaths({ package: process.cwd() }));
|
|
124
125
|
return [
|
|
125
|
-
...(options.includeCore ? [
|
|
126
|
-
...(options.includeExtensions ?
|
|
127
|
-
...(options.includePhpPackages ?
|
|
128
|
-
...(options.includeJSPackages ?
|
|
126
|
+
...(options.includeCore && monorepoConfig.packages.core ? [(0, monorepo_1.corePath)(monorepoConfig.packages.core.name)] : []),
|
|
127
|
+
...(options.includeExtensions ? monorepoConfig.packages.extensions : []).map((ext) => (0, monorepo_1.extensionPath)(ext.name)),
|
|
128
|
+
...(options.includePhpPackages ? (_a = monorepoConfig.packages.composer) !== null && _a !== void 0 ? _a : [] : []).map((lib) => (0, monorepo_1.composerPath)(lib.name)),
|
|
129
|
+
...(options.includeJSPackages ? (_b = monorepoConfig.packages.npm) !== null && _b !== void 0 ? _b : [] : []).map((lib) => (0, monorepo_1.npmPath)(lib.name)),
|
|
129
130
|
];
|
|
130
131
|
}
|
|
131
|
-
catch (
|
|
132
|
+
catch (_c) {
|
|
132
133
|
this.error('Could not run monorepo command: `flarum-monorepo.json` file is missing or invalid.');
|
|
133
134
|
}
|
|
134
135
|
}
|
|
136
|
+
isFlarumMonorepo(path) {
|
|
137
|
+
return (0, fs_1.existsSync)((0, path_1.resolve)(path, 'flarum-monorepo.json'));
|
|
138
|
+
}
|
|
135
139
|
isFlarumCore(path) {
|
|
136
140
|
try {
|
|
137
|
-
const composerJsonPath = (0,
|
|
138
|
-
const val = JSON.parse((0,
|
|
141
|
+
const composerJsonPath = (0, path_1.resolve)(path, 'composer.json');
|
|
142
|
+
const val = JSON.parse((0, fs_1.readFileSync)(composerJsonPath, 'utf8'));
|
|
139
143
|
return val.name === 'flarum/core';
|
|
140
144
|
}
|
|
141
145
|
catch (_a) {
|
|
142
146
|
return false;
|
|
143
147
|
}
|
|
144
148
|
}
|
|
149
|
+
jsPackageManager(currDir) {
|
|
150
|
+
if (!(0, fs_1.existsSync)((0, path_1.resolve)(currDir, 'js')))
|
|
151
|
+
return null;
|
|
152
|
+
return (0, fs_1.existsSync)((0, path_1.resolve)(currDir, 'js/yarn.lock')) ? 'yarn' : 'npm';
|
|
153
|
+
}
|
|
145
154
|
async getFlarumExtensionRoot(currDir) {
|
|
146
|
-
let currPath = (0,
|
|
155
|
+
let currPath = (0, path_1.resolve)(currDir);
|
|
147
156
|
while (currPath !== '/') {
|
|
148
|
-
if ((0,
|
|
157
|
+
if ((0, fs_1.existsSync)((0, path_1.resolve)(currPath, 'flarum-monorepo.json'))) {
|
|
149
158
|
return { path: currPath, type: LocationType.FLARUM_MONOREPO };
|
|
150
159
|
}
|
|
151
|
-
if ((0,
|
|
160
|
+
if ((0, fs_1.existsSync)((0, path_1.resolve)(currPath, 'composer.json')) && (0, fs_1.existsSync)((0, path_1.resolve)(currPath, 'extend.php'))) {
|
|
152
161
|
return { path: currPath, type: LocationType.FLARUM_EXTENSION };
|
|
153
162
|
}
|
|
154
163
|
if (this.isFlarumCore(currPath)) {
|
|
155
164
|
return { path: currPath, type: LocationType.FLARUM_CORE };
|
|
156
165
|
}
|
|
157
|
-
currPath = (0,
|
|
166
|
+
currPath = (0, path_1.resolve)(currPath, '..');
|
|
158
167
|
}
|
|
159
|
-
this.error(`${(0,
|
|
168
|
+
this.error(`${(0, path_1.resolve)(currDir)} is not located in a valid Flarum package!
|
|
160
169
|
- Flarum extensions must contain (at a minimum) 'extend.php' and 'composer.json' files.
|
|
161
170
|
- Flarum core must contain a 'composer.json' file with the name 'flarum/core'.
|
|
162
171
|
- Flarum monorepos must have a valid 'flarum-monorepo.json' file`);
|
|
@@ -165,14 +174,14 @@ class BaseCommand extends core_1.Command {
|
|
|
165
174
|
const verify = await this.genIO().getParam({
|
|
166
175
|
name: 'verify',
|
|
167
176
|
type: 'confirm',
|
|
168
|
-
message: `Work in Flarum package located at ${(0,
|
|
177
|
+
message: `Work in Flarum package located at ${(0, path_1.resolve)(extRoot)}?`,
|
|
169
178
|
initial: true,
|
|
170
179
|
});
|
|
171
180
|
if (!verify)
|
|
172
181
|
this.exit();
|
|
173
182
|
}
|
|
174
183
|
async ensureComposerInstallRan(extRoot) {
|
|
175
|
-
if ((0,
|
|
184
|
+
if ((0, fs_1.existsSync)((0, path_1.resolve)(extRoot, 'vendor/flarum/core/composer.json')))
|
|
176
185
|
return;
|
|
177
186
|
this.log("This command requires `composer install` to have been ran in your extension's root directory.");
|
|
178
187
|
const composer = await this.genIO().getParam({
|
|
@@ -183,7 +192,7 @@ class BaseCommand extends core_1.Command {
|
|
|
183
192
|
});
|
|
184
193
|
if (composer) {
|
|
185
194
|
cli_ux_1.default.action.start('Installing composer packages');
|
|
186
|
-
(0,
|
|
195
|
+
(0, child_process_1.execSync)('composer install', { cwd: extRoot });
|
|
187
196
|
cli_ux_1.default.action.stop();
|
|
188
197
|
}
|
|
189
198
|
else {
|
|
@@ -197,7 +206,7 @@ class BaseCommand extends core_1.Command {
|
|
|
197
206
|
*/
|
|
198
207
|
async confirmOverrideFiles(dir, pattern, confirmationMessage) {
|
|
199
208
|
const paths = Array.isArray(pattern) ? pattern : [pattern];
|
|
200
|
-
const files = await (0, globby_1.default)(paths.map(p => (0,
|
|
209
|
+
const files = await (0, globby_1.default)(paths.map((p) => (0, path_1.resolve)(dir, p)));
|
|
201
210
|
const empty = files.length === 0 || (files.length === 1 && files[0] === '.git');
|
|
202
211
|
if (empty)
|
|
203
212
|
return false;
|
|
@@ -212,13 +221,17 @@ class BaseCommand extends core_1.Command {
|
|
|
212
221
|
return true;
|
|
213
222
|
}
|
|
214
223
|
async deleteFiles(dir, pattern) {
|
|
215
|
-
const pathsToDelete = await (0, globby_1.default)((0,
|
|
216
|
-
pathsToDelete.forEach(
|
|
224
|
+
const pathsToDelete = await (0, globby_1.default)((0, path_1.resolve)(dir, pattern));
|
|
225
|
+
pathsToDelete.forEach(fs_1.unlinkSync);
|
|
217
226
|
}
|
|
218
227
|
}
|
|
219
228
|
exports.default = BaseCommand;
|
|
220
229
|
BaseCommand.flags = {
|
|
221
|
-
'no-interaction': core_1.Flags.boolean({
|
|
230
|
+
'no-interaction': core_1.Flags.boolean({
|
|
231
|
+
char: 'n',
|
|
232
|
+
description: 'Do not ask any interactive questions, assume defaults. When impossible, error.',
|
|
233
|
+
default: false,
|
|
234
|
+
}),
|
|
222
235
|
help: core_1.Flags.help({ char: 'h' }),
|
|
223
236
|
};
|
|
224
237
|
BaseCommand.args = [
|
package/lib/boilersmith/io.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { PromptObject } from 'prompts';
|
|
1
|
+
import { PromptObject, PromptType } from 'prompts';
|
|
2
|
+
declare type BooleanPromptType = PromptType & ('confirm' | 'toggle');
|
|
3
|
+
declare type StringPromptType = PromptType & ('text' | 'password' | 'invisible' | 'autocomplete');
|
|
4
|
+
declare type DatePromptType = PromptType & 'date';
|
|
5
|
+
declare type ListPromptType = PromptType & 'list';
|
|
2
6
|
export declare type ParamDef<N extends string = string> = Omit<PromptObject<N>, 'name'> & {
|
|
3
7
|
name: N;
|
|
8
|
+
message: string;
|
|
4
9
|
};
|
|
5
10
|
export declare type Message = {
|
|
6
11
|
type: 'info' | 'warning' | 'error';
|
|
@@ -11,7 +16,19 @@ export interface IO {
|
|
|
11
16
|
/**
|
|
12
17
|
* Prompt the user for some input data.
|
|
13
18
|
*/
|
|
14
|
-
getParam
|
|
19
|
+
getParam(param: ParamDef & {
|
|
20
|
+
type: BooleanPromptType;
|
|
21
|
+
}, noCache?: boolean): Promise<boolean>;
|
|
22
|
+
getParam(param: ParamDef & {
|
|
23
|
+
type: StringPromptType;
|
|
24
|
+
}, noCache?: boolean): Promise<string>;
|
|
25
|
+
getParam(param: ParamDef & {
|
|
26
|
+
type: DatePromptType;
|
|
27
|
+
}, noCache?: boolean): Promise<Date>;
|
|
28
|
+
getParam(param: ParamDef & {
|
|
29
|
+
type: ListPromptType;
|
|
30
|
+
}, noCache?: boolean): Promise<string[]>;
|
|
31
|
+
getParam<T>(param: ParamDef, noCache?: boolean): Promise<T>;
|
|
15
32
|
/**
|
|
16
33
|
* Check if some data has already been prompted for.
|
|
17
34
|
*/
|
|
@@ -32,13 +49,16 @@ export interface IO {
|
|
|
32
49
|
declare type OnCancel = () => void;
|
|
33
50
|
export declare class PromptsIO implements IO {
|
|
34
51
|
supportsAnsiColor: boolean;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
protected cache: Map<string, unknown>;
|
|
53
|
+
protected messages: Message[];
|
|
54
|
+
protected noInteraction: boolean;
|
|
55
|
+
protected onCancel?: OnCancel;
|
|
56
|
+
protected prev?: {
|
|
57
|
+
val: any;
|
|
58
|
+
prompt: ParamDef;
|
|
59
|
+
};
|
|
40
60
|
constructor(initial?: Record<string, unknown>, messages?: Message[], noInteraction?: boolean, onCancel?: OnCancel);
|
|
41
|
-
getParam<T>(paramDef: ParamDef): Promise<T>;
|
|
61
|
+
getParam<T>(paramDef: ParamDef, noCache?: boolean): Promise<T>;
|
|
42
62
|
hasCached(name: string): boolean;
|
|
43
63
|
/**
|
|
44
64
|
* @internal
|
package/lib/boilersmith/io.js
CHANGED
|
@@ -15,7 +15,7 @@ class PromptsIO {
|
|
|
15
15
|
this.noInteraction = noInteraction;
|
|
16
16
|
this.onCancel = onCancel;
|
|
17
17
|
}
|
|
18
|
-
async getParam(paramDef) {
|
|
18
|
+
async getParam(paramDef, noCache = false) {
|
|
19
19
|
var _a, _b, _c;
|
|
20
20
|
const paramName = paramDef.name;
|
|
21
21
|
if (this.cache.has(paramName)) {
|
|
@@ -42,7 +42,9 @@ class PromptsIO {
|
|
|
42
42
|
}));
|
|
43
43
|
resValue = res[paramName];
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
if (!noCache) {
|
|
46
|
+
this.cache.set(paramName, resValue);
|
|
47
|
+
}
|
|
46
48
|
this.prev = {
|
|
47
49
|
val: resValue,
|
|
48
50
|
prompt: paramDef,
|
|
@@ -3,7 +3,7 @@ export interface Paths {
|
|
|
3
3
|
package(...path: string[]): string;
|
|
4
4
|
requestedDir(...path: string[]): string | null;
|
|
5
5
|
monorepo(...path: string[]): string | null;
|
|
6
|
-
onMonorepoSub(packagePath: string): Paths;
|
|
6
|
+
onMonorepoSub(packagePath: string, monorepoPath?: string): Paths;
|
|
7
7
|
}
|
|
8
8
|
declare type InternalPaths = {
|
|
9
9
|
package: string;
|
|
@@ -17,6 +17,6 @@ export declare class NodePaths implements Paths {
|
|
|
17
17
|
package(...path: string[]): string;
|
|
18
18
|
requestedDir(...path: string[]): string | null;
|
|
19
19
|
monorepo(...path: string[]): string | null;
|
|
20
|
-
onMonorepoSub(packagePath: string): NodePaths;
|
|
20
|
+
onMonorepoSub(packagePath: string, monorepoPath?: string): NodePaths;
|
|
21
21
|
}
|
|
22
22
|
export {};
|
package/lib/boilersmith/paths.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NodePaths = void 0;
|
|
4
|
-
const
|
|
4
|
+
const path_1 = require("path");
|
|
5
5
|
class NodePaths {
|
|
6
6
|
constructor(paths) {
|
|
7
7
|
this.paths = paths;
|
|
8
8
|
}
|
|
9
9
|
cwd(...path) {
|
|
10
|
-
return (0,
|
|
10
|
+
return (0, path_1.resolve)(process.cwd(), ...path);
|
|
11
11
|
}
|
|
12
12
|
package(...path) {
|
|
13
|
-
return (0,
|
|
13
|
+
return (0, path_1.resolve)(this.paths.package, ...path);
|
|
14
14
|
}
|
|
15
15
|
requestedDir(...path) {
|
|
16
16
|
if (!this.paths.requestedDir)
|
|
17
17
|
return null;
|
|
18
|
-
return (0,
|
|
18
|
+
return (0, path_1.resolve)(this.paths.requestedDir, ...path);
|
|
19
19
|
}
|
|
20
20
|
monorepo(...path) {
|
|
21
21
|
if (!this.paths.monorepo)
|
|
22
22
|
return null;
|
|
23
|
-
return (0,
|
|
23
|
+
return (0, path_1.resolve)(this.paths.monorepo, ...path);
|
|
24
24
|
}
|
|
25
|
-
onMonorepoSub(packagePath) {
|
|
26
|
-
return new NodePaths(Object.assign(Object.assign({}, this.paths), { monorepo: this.paths.package, package: packagePath }));
|
|
25
|
+
onMonorepoSub(packagePath, monorepoPath) {
|
|
26
|
+
return new NodePaths(Object.assign(Object.assign({}, this.paths), { monorepo: monorepoPath !== null && monorepoPath !== void 0 ? monorepoPath : this.paths.package, package: packagePath }));
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
exports.NodePaths = NodePaths;
|
|
@@ -8,7 +8,7 @@ const module_1 = require("./module");
|
|
|
8
8
|
const template_param_1 = require("./template-param");
|
|
9
9
|
const cond_format_1 = require("boilersmith/utils/cond-format");
|
|
10
10
|
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
|
|
11
|
-
const
|
|
11
|
+
const fs_1 = require("fs");
|
|
12
12
|
function auditStepFactory(dry, scaffoldDir, modules, templateParams, excludeScaffoldingFunc, moduleStatusCache) {
|
|
13
13
|
let modulesEnabled;
|
|
14
14
|
return {
|
|
@@ -17,28 +17,28 @@ function auditStepFactory(dry, scaffoldDir, modules, templateParams, excludeScaf
|
|
|
17
17
|
async run(_fs, paths, io, _providers) {
|
|
18
18
|
const paramVals = await (0, template_param_1.currParamValues)(templateParams, _fs, paths, io);
|
|
19
19
|
modulesEnabled = await (0, module_1.currModulesEnabled)(modules, _fs, paths, moduleStatusCache);
|
|
20
|
-
const actionableModules = modules.filter(m => m.updatable && modulesEnabled[m.name] && (!m.togglable || !m.dependsOn.some(dep => !modulesEnabled[dep])));
|
|
21
|
-
io.info((0, cond_format_1.condFormat)(io.supportsAnsiColor, m => chalk_1.default.yellow(chalk_1.default.bold(chalk_1.default.underline(m))), `Auditing infrastructure for ${actionableModules.length} enabled modules:`), true);
|
|
20
|
+
const actionableModules = modules.filter((m) => m.updatable && modulesEnabled[m.name] && (!m.togglable || !m.dependsOn.some((dep) => !modulesEnabled[dep])));
|
|
21
|
+
io.info((0, cond_format_1.condFormat)(io.supportsAnsiColor, (m) => chalk_1.default.yellow(chalk_1.default.bold(chalk_1.default.underline(m))), `Auditing infrastructure for ${actionableModules.length} enabled modules:`), true);
|
|
22
22
|
for (const m of modules) {
|
|
23
23
|
if (actionableModules.includes(m)) {
|
|
24
|
-
io.info((0, cond_format_1.condFormat)(io.supportsAnsiColor, m => chalk_1.default.dim(chalk_1.default.green(m)), `✓ ${m.name}: ${m.shortDescription}`), true);
|
|
24
|
+
io.info((0, cond_format_1.condFormat)(io.supportsAnsiColor, (m) => chalk_1.default.dim(chalk_1.default.green(m)), `✓ ${m.name}: ${m.shortDescription}`), true);
|
|
25
25
|
}
|
|
26
26
|
else if (m.updatable) {
|
|
27
|
-
io.info((0, cond_format_1.condFormat)(io.supportsAnsiColor, m => chalk_1.default.dim(chalk_1.default.red(m)),
|
|
27
|
+
io.info((0, cond_format_1.condFormat)(io.supportsAnsiColor, (m) => chalk_1.default.dim(chalk_1.default.red(m)), `✕ ${m.name}: ${m.shortDescription} (disabled)`), true);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
for (const m of actionableModules) {
|
|
31
31
|
const fs = dry ? (0, mem_fs_1.create)() : _fs;
|
|
32
|
-
const excludeScaffolding = excludeScaffoldingFunc ? excludeScaffoldingFunc(fs, paths) : [];
|
|
32
|
+
const excludeScaffolding = excludeScaffoldingFunc ? excludeScaffoldingFunc(fs, paths) : { files: [], configKeys: {} };
|
|
33
33
|
(0, module_1.applyModule)(m, modulesEnabled, paramVals, scaffoldDir, fs, paths, excludeScaffolding, true);
|
|
34
34
|
if (dry) {
|
|
35
35
|
const filesWithChanges = fs
|
|
36
36
|
.all()
|
|
37
|
-
.filter(f => f.state && f.state !== 'deleted')
|
|
38
|
-
.filter(f => { var _a; return !(0,
|
|
37
|
+
.filter((f) => f.state && f.state !== 'deleted')
|
|
38
|
+
.filter((f) => { var _a; return !(0, fs_1.existsSync)(f.path) || (0, fs_1.readFileSync)(f.path, 'utf8').toString() !== ((_a = f.contents) === null || _a === void 0 ? void 0 : _a.toString()); });
|
|
39
39
|
if (filesWithChanges.length > 0) {
|
|
40
40
|
io.error(`Module ${m.name} has ${filesWithChanges.length} changed files: ${filesWithChanges
|
|
41
|
-
.map(f => f.path.replace(paths.package() + '/', ''))
|
|
41
|
+
.map((f) => f.path.replace(paths.package() + '/', ''))
|
|
42
42
|
.join(', ')}`, false);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -52,9 +52,9 @@ function auditStepFactory(dry, scaffoldDir, modules, templateParams, excludeScaf
|
|
|
52
52
|
}
|
|
53
53
|
return _fs;
|
|
54
54
|
},
|
|
55
|
-
exposes: modules.map(m => `modules.${m.name}`),
|
|
55
|
+
exposes: modules.map((m) => `modules.${m.name}`),
|
|
56
56
|
getExposed(_paths, _paramProvider) {
|
|
57
|
-
return (0, rename_keys_1.renameKeys)(modulesEnabled, k => `modules.${k}`);
|
|
57
|
+
return (0, rename_keys_1.renameKeys)(modulesEnabled, (k) => `modules.${k}`);
|
|
58
58
|
},
|
|
59
59
|
};
|
|
60
60
|
}
|
|
@@ -4,7 +4,7 @@ exports.infraStepFactory = void 0;
|
|
|
4
4
|
const module_1 = require("./module");
|
|
5
5
|
const template_param_1 = require("./template-param");
|
|
6
6
|
function infraStepFactory(scaffoldDir, moduleName, modules, templateParams, excludeScaffoldingFunc, moduleStatusCache) {
|
|
7
|
-
const module = modules.find(m => m.name === moduleName);
|
|
7
|
+
const module = modules.find((m) => m.name === moduleName);
|
|
8
8
|
if (!module) {
|
|
9
9
|
throw new Error(`Module ${moduleName} not found`);
|
|
10
10
|
}
|
|
@@ -17,7 +17,7 @@ function infraStepFactory(scaffoldDir, moduleName, modules, templateParams, excl
|
|
|
17
17
|
if (!module.updatable) {
|
|
18
18
|
io.error(`${module.name} is not updatable.`, true);
|
|
19
19
|
}
|
|
20
|
-
const excludeScaffolding = excludeScaffoldingFunc ? excludeScaffoldingFunc(fs, paths) : [];
|
|
20
|
+
const excludeScaffolding = excludeScaffoldingFunc ? excludeScaffoldingFunc(fs, paths) : { files: [], configKeys: {} };
|
|
21
21
|
const initializing = !modulesEnabled[module.name];
|
|
22
22
|
(0, module_1.applyModule)(module, Object.assign(Object.assign({}, modulesEnabled), { [module.name]: true }), paramVals, scaffoldDir, fs, paths, excludeScaffolding, initializing);
|
|
23
23
|
if (moduleStatusCache) {
|
|
@@ -12,22 +12,22 @@ function initStepFactory(scaffoldDir, modules, templateParams, excludeScaffoldin
|
|
|
12
12
|
async run(fs, paths, io, _providers) {
|
|
13
13
|
const paramVals = await (0, template_param_1.promptParamValues)(templateParams, paths, io);
|
|
14
14
|
modulesEnabled = await (0, module_1.promptModulesEnabled)(modules, io);
|
|
15
|
-
const excludeScaffolding = excludeScaffoldingFunc ? excludeScaffoldingFunc(fs, paths) : [];
|
|
15
|
+
const excludeScaffolding = excludeScaffoldingFunc ? excludeScaffoldingFunc(fs, paths) : { files: [], configKeys: {} };
|
|
16
16
|
for (const m of modules) {
|
|
17
|
-
if (modulesEnabled[m.name] && (!m.togglable || !m.dependsOn.some(dep => !modulesEnabled[dep]))) {
|
|
17
|
+
if (modulesEnabled[m.name] && (!m.togglable || !m.dependsOn.some((dep) => !modulesEnabled[dep]))) {
|
|
18
18
|
(0, module_1.applyModule)(m, modulesEnabled, paramVals, scaffoldDir, fs, paths, excludeScaffolding, true);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
if (moduleStatusCache) {
|
|
22
|
-
modules.forEach(m => {
|
|
22
|
+
modules.forEach((m) => {
|
|
23
23
|
(0, module_1.setModuleValue)(m, modulesEnabled[m.name], fs, paths, moduleStatusCache);
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
return fs;
|
|
27
27
|
},
|
|
28
|
-
exposes: modules.map(m => `modules.${m.name}`),
|
|
28
|
+
exposes: modules.map((m) => `modules.${m.name}`),
|
|
29
29
|
getExposed(_paths, _paramProvider) {
|
|
30
|
-
return (0, rename_keys_1.renameKeys)(modulesEnabled, k => `modules.${k}`);
|
|
30
|
+
return (0, rename_keys_1.renameKeys)(modulesEnabled, (k) => `modules.${k}`);
|
|
31
31
|
},
|
|
32
32
|
};
|
|
33
33
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Store } from 'mem-fs';
|
|
2
2
|
import { IO } from 'boilersmith/io';
|
|
3
3
|
import { Paths } from 'boilersmith/paths';
|
|
4
|
-
|
|
4
|
+
import { ExcludeScaffoldingFunc } from './scaffolder';
|
|
5
|
+
declare type FileOwnershipCommon<N extends string> = {
|
|
5
6
|
/**
|
|
6
7
|
* The path to the file
|
|
7
8
|
*/
|
|
@@ -11,15 +12,28 @@ interface FileOwnership {
|
|
|
11
12
|
*/
|
|
12
13
|
destPath?: string;
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
+
* Depends on other modules being enabled (or disabled).
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
+
moduleDeps?: (N | {
|
|
18
|
+
module: N;
|
|
19
|
+
enabled: boolean;
|
|
20
|
+
})[];
|
|
21
|
+
/**
|
|
22
|
+
* Only create the file if it doesn't exist; do not update existing files.
|
|
23
|
+
*/
|
|
24
|
+
doNotUpdate?: boolean;
|
|
25
|
+
};
|
|
26
|
+
declare type FileOwnership<N extends string> = (FileOwnershipCommon<N> & {
|
|
17
27
|
/**
|
|
18
28
|
* If in a monorepo, should the file be placed relative to the monorepo root, and if so, where?
|
|
19
29
|
* If provided, takes priority over destPath.
|
|
20
30
|
*/
|
|
21
|
-
monorepoPath
|
|
22
|
-
|
|
31
|
+
monorepoPath: string;
|
|
32
|
+
/**
|
|
33
|
+
* Only place this file if in a monorepo?
|
|
34
|
+
*/
|
|
35
|
+
requireMonorepo: boolean;
|
|
36
|
+
}) | FileOwnershipCommon<N>;
|
|
23
37
|
interface CommonModule<N extends string> {
|
|
24
38
|
name: N;
|
|
25
39
|
shortDescription: string;
|
|
@@ -31,7 +45,7 @@ interface CommonModule<N extends string> {
|
|
|
31
45
|
/**
|
|
32
46
|
* A list of scaffolding files managed by this module.
|
|
33
47
|
*/
|
|
34
|
-
filesToReplace: (string | FileOwnership)[];
|
|
48
|
+
filesToReplace: (string | FileOwnership<N>)[];
|
|
35
49
|
/**
|
|
36
50
|
* A map of names of JSON files to keys which should be deep-merged from the scaffolding.
|
|
37
51
|
*/
|
|
@@ -59,7 +73,13 @@ interface TogglableModule<N extends string> extends CommonModule<N> {
|
|
|
59
73
|
/**
|
|
60
74
|
* Can only be enabled if these other modules are enabled.
|
|
61
75
|
*/
|
|
62
|
-
dependsOn:
|
|
76
|
+
dependsOn: N[];
|
|
77
|
+
/**
|
|
78
|
+
* On an existing installation, if no information about whether this
|
|
79
|
+
* module is enabled or disabled is cached, infer whether it's enabled
|
|
80
|
+
* based on the current installation's state.
|
|
81
|
+
*/
|
|
82
|
+
inferEnabled?: (fs: Store, paths: Paths) => Promise<boolean | undefined>;
|
|
63
83
|
}
|
|
64
84
|
export declare type Module<N extends string = string> = UntoggleableModule<N> | TogglableModule<N>;
|
|
65
85
|
export declare type ModuleStatusCache<N extends string> = {
|
|
@@ -69,5 +89,5 @@ export declare type ModuleStatusCache<N extends string> = {
|
|
|
69
89
|
export declare function promptModulesEnabled<N extends string>(modules: Module<N>[], io: IO): Promise<Record<N, boolean>>;
|
|
70
90
|
export declare function currModulesEnabled<N extends string>(modules: Module<N>[], fs: Store, paths: Paths, cache?: ModuleStatusCache<N>): Promise<Record<N, boolean>>;
|
|
71
91
|
export declare function setModuleValue<MN extends string>(module: Module<MN>, enabled: boolean, fs: Store, paths: Paths, cache: ModuleStatusCache<MN>): Promise<void>;
|
|
72
|
-
export declare function applyModule<MN extends string, TN extends string>(module: Module<MN>, modulesEnabled: Record<string, boolean>, paramVals: Record<TN, unknown>, scaffoldDir: string, fs: Store, paths: Paths,
|
|
92
|
+
export declare function applyModule<MN extends string, TN extends string>(module: Module<MN>, modulesEnabled: Record<string, boolean>, paramVals: Record<TN, unknown>, scaffoldDir: string, fs: Store, paths: Paths, excludeScaffolding?: ReturnType<ExcludeScaffoldingFunc>, isInitial?: boolean): Promise<Store>;
|
|
73
93
|
export {};
|
|
@@ -4,7 +4,7 @@ exports.applyModule = exports.setModuleValue = exports.currModulesEnabled = expo
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
|
|
6
6
|
const mem_fs_editor_1 = require("mem-fs-editor");
|
|
7
|
-
const
|
|
7
|
+
const path_1 = require("path");
|
|
8
8
|
const pick_deep_1 = (0, tslib_1.__importDefault)(require("pick-deep"));
|
|
9
9
|
const read_tpl_1 = require("boilersmith/utils/read-tpl");
|
|
10
10
|
const clone_and_fill_1 = require("boilersmith/utils/clone-and-fill");
|
|
@@ -19,7 +19,7 @@ async function promptModulesEnabled(modules, io) {
|
|
|
19
19
|
message: `Advanced Initialization ${(0, cond_format_1.condFormat)(io.supportsAnsiColor, chalk_1.default.dim, '(fine-tune which features are enabled)')}`,
|
|
20
20
|
});
|
|
21
21
|
for (const m of modules) {
|
|
22
|
-
const missingDeps = !m.togglable || m.dependsOn.some(dep => !modulesEnabled[dep]);
|
|
22
|
+
const missingDeps = !m.togglable || m.dependsOn.some((dep) => !modulesEnabled[dep]);
|
|
23
23
|
if (!m.togglable) {
|
|
24
24
|
modulesEnabled[m.name] = true;
|
|
25
25
|
}
|
|
@@ -43,12 +43,13 @@ async function promptModulesEnabled(modules, io) {
|
|
|
43
43
|
}
|
|
44
44
|
exports.promptModulesEnabled = promptModulesEnabled;
|
|
45
45
|
async function currModulesEnabled(modules, fs, paths, cache) {
|
|
46
|
+
var _a, _b;
|
|
46
47
|
const modulesEnabled = {};
|
|
47
48
|
for (const m of modules) {
|
|
48
49
|
if (m.togglable) {
|
|
49
50
|
// eslint-disable-next-line no-await-in-loop
|
|
50
|
-
const
|
|
51
|
-
modulesEnabled[m.name] =
|
|
51
|
+
const isEnabled = (_a = (await (cache === null || cache === void 0 ? void 0 : cache.get(m, fs, paths)))) !== null && _a !== void 0 ? _a : (await ((_b = m.inferEnabled) === null || _b === void 0 ? void 0 : _b.call(m, fs, paths)));
|
|
52
|
+
modulesEnabled[m.name] = isEnabled !== null && isEnabled !== void 0 ? isEnabled : m.defaultEnabled;
|
|
52
53
|
}
|
|
53
54
|
else {
|
|
54
55
|
modulesEnabled[m.name] = true;
|
|
@@ -63,21 +64,23 @@ async function setModuleValue(module, enabled, fs, paths, cache) {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
exports.setModuleValue = setModuleValue;
|
|
66
|
-
// eslint-disable-next-line max-params
|
|
67
|
-
async function applyModule(module, modulesEnabled, paramVals, scaffoldDir, fs, paths,
|
|
68
|
-
|
|
67
|
+
// eslint-disable-next-line max-params,complexity
|
|
68
|
+
async function applyModule(module, modulesEnabled, paramVals, scaffoldDir, fs, paths,
|
|
69
|
+
// eslint-disable-next-line unicorn/no-object-as-default-parameter
|
|
70
|
+
excludeScaffolding = { files: [], configKeys: {} }, isInitial = false) {
|
|
71
|
+
var _a, _b;
|
|
69
72
|
const fsEditor = (0, mem_fs_editor_1.create)(fs);
|
|
70
73
|
// Validate that module can be enabled
|
|
71
74
|
if (!(modulesEnabled === null || modulesEnabled === void 0 ? void 0 : modulesEnabled[module.name])) {
|
|
72
75
|
throw new Error(`Could not apply module "${module.name}", because it is not enabled in the provided module statuses.`);
|
|
73
76
|
}
|
|
74
77
|
// Validate that dependencies are enabled
|
|
75
|
-
const missingDeps = module.togglable ? module.dependsOn.filter(dep => !modulesEnabled[dep]) : [];
|
|
78
|
+
const missingDeps = module.togglable ? module.dependsOn.filter((dep) => !modulesEnabled[dep]) : [];
|
|
76
79
|
if (missingDeps.length > 0) {
|
|
77
80
|
throw new Error(`Could not apply module "${module.name}", because the following dependency modules are missing: "${missingDeps.join(', ')}".`);
|
|
78
81
|
}
|
|
79
82
|
// Validate that all needed params are present
|
|
80
|
-
const missingParams = module.needsTemplateParams.filter(p => !(p in paramVals));
|
|
83
|
+
const missingParams = module.needsTemplateParams.filter((p) => !(p in paramVals));
|
|
81
84
|
if (missingParams.length > 0) {
|
|
82
85
|
throw new Error(`Could not apply module "${module.name}", because the following params are missing: "${missingParams.join(', ')}".`);
|
|
83
86
|
}
|
|
@@ -88,24 +91,63 @@ async function applyModule(module, modulesEnabled, paramVals, scaffoldDir, fs, p
|
|
|
88
91
|
params: paramVals,
|
|
89
92
|
modules: modulesEnabled,
|
|
90
93
|
};
|
|
91
|
-
const tplDataFlat = Object.assign(Object.assign({}, (0, rename_keys_1.renameKeys)(tplData.modules, k => `modules.${k}`)), (0, rename_keys_1.renameKeys)(tplData.params, k => `params.${k}`));
|
|
94
|
+
const tplDataFlat = Object.assign(Object.assign({}, (0, rename_keys_1.renameKeys)(tplData.modules, (k) => `modules.${k}`)), (0, rename_keys_1.renameKeys)(tplData.params, (k) => `params.${k}`));
|
|
95
|
+
// This is necessary because one layer of escaped backslashes is lost on template population.
|
|
96
|
+
tplData.params = Object.fromEntries(Object.entries(paramVals).map(([k, v]) => [k, typeof v === 'string' ? v.replace('\\', '\\\\') : v]));
|
|
92
97
|
for (const file of module.filesToReplace) {
|
|
93
98
|
const path = typeof file === 'string' ? file : file.path;
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
const moduleDeps = typeof file === 'string' ? [] : (_a = file.moduleDeps) !== null && _a !== void 0 ? _a : [];
|
|
100
|
+
const copyToIfMonorepo = typeof file !== 'string' && 'monorepoPath' in file && file.monorepoPath
|
|
101
|
+
? paths.monorepo((0, clone_and_fill_1.cloneAndFill)(file.monorepoPath, tplDataFlat))
|
|
102
|
+
: undefined;
|
|
103
|
+
const copyTo = copyToIfMonorepo !== null && copyToIfMonorepo !== void 0 ? copyToIfMonorepo : paths.package(typeof file !== 'string' && file.destPath ? (0, clone_and_fill_1.cloneAndFill)(file.destPath, tplDataFlat) : path);
|
|
104
|
+
if (typeof file !== 'string' && file.doNotUpdate && fsEditor.exists(copyTo)) {
|
|
105
|
+
continue;
|
|
99
106
|
}
|
|
107
|
+
if (typeof file !== 'string' && 'requireMonorepo' in file && file.requireMonorepo && paths.monorepo() === null) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (excludeScaffolding.files.includes(path) ||
|
|
111
|
+
moduleDeps.some((dep) => {
|
|
112
|
+
const depName = typeof dep === 'string' ? dep : dep.module;
|
|
113
|
+
const enabled = modulesEnabled[depName];
|
|
114
|
+
return typeof dep === 'string' || dep.enabled ? !enabled : enabled;
|
|
115
|
+
})) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
let source = (0, read_tpl_1.readTpl)((0, path_1.resolve)(scaffoldDir, path), tplData);
|
|
119
|
+
if (fsEditor.exists(copyTo)) {
|
|
120
|
+
source = applyCustomizations(source, fsEditor.read(copyTo));
|
|
121
|
+
}
|
|
122
|
+
fsEditor.write(copyTo, source);
|
|
100
123
|
}
|
|
101
124
|
const jsonPaths = (0, clone_and_fill_1.cloneAndFill)(module.jsonToAugment, tplDataFlat);
|
|
102
125
|
for (const jsonPath of Object.keys(jsonPaths)) {
|
|
103
|
-
const scaffoldContents = (0, read_tpl_1.readTpl)((0,
|
|
126
|
+
const scaffoldContents = (0, read_tpl_1.readTpl)((0, path_1.resolve)(scaffoldDir, jsonPath), tplData);
|
|
104
127
|
const scaffoldContentsJson = JSON.parse(scaffoldContents);
|
|
105
|
-
const
|
|
128
|
+
const excludeKeys = (0, clone_and_fill_1.cloneAndFill)((_b = excludeScaffolding.configKeys[jsonPath]) !== null && _b !== void 0 ? _b : [], tplDataFlat);
|
|
129
|
+
const fieldsToAugment = jsonPaths[jsonPath].filter((key) => !excludeKeys.includes(key));
|
|
106
130
|
const relevant = (0, pick_deep_1.default)(scaffoldContentsJson, fieldsToAugment);
|
|
107
131
|
fsEditor.extendJSON(paths.package(jsonPath), relevant, undefined, 4);
|
|
108
132
|
}
|
|
109
133
|
return fs;
|
|
110
134
|
}
|
|
111
135
|
exports.applyModule = applyModule;
|
|
136
|
+
function applyCustomizations(source, curr) {
|
|
137
|
+
const commentStructures = [
|
|
138
|
+
['//', '\n'],
|
|
139
|
+
['/*', ' */'],
|
|
140
|
+
['<!--', '-->'],
|
|
141
|
+
['#', '\n'],
|
|
142
|
+
];
|
|
143
|
+
commentStructures.forEach((x) => x);
|
|
144
|
+
return commentStructures.reduce((acc, [start, end]) => {
|
|
145
|
+
const CUSTOMIZATION_REGEX = new RegExp(`(${start}\\s*<CUSTOM-(?<id>.*)>\\s*${end})(?<contents>.*)(${start}\\s*</CUSTOM-\\k<id>>\\s*${end})`, 'gs');
|
|
146
|
+
const matches = curr.matchAll(CUSTOMIZATION_REGEX);
|
|
147
|
+
const customizations = Object.fromEntries([...matches]
|
|
148
|
+
.map((m) => m.groups)
|
|
149
|
+
.filter(Boolean)
|
|
150
|
+
.map((g) => [g === null || g === void 0 ? void 0 : g.id, g === null || g === void 0 ? void 0 : g.contents]));
|
|
151
|
+
return acc.replace(CUSTOMIZATION_REGEX, (_m, open, id, _c, close) => { var _a; return `${open}${(_a = customizations[id]) !== null && _a !== void 0 ? _a : ''}${close}`; });
|
|
152
|
+
}, source);
|
|
153
|
+
}
|