dazscript-framework 0.1.17 → 0.2.1
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/README.md +49 -60
- package/babel.config.js +10 -18
- package/dist/config.js +9 -0
- package/dist/scripts/build.js +82 -0
- package/dist/scripts/cli.js +155 -0
- package/dist/scripts/config-loader.js +83 -0
- package/dist/scripts/icons.js +27 -0
- package/dist/scripts/init.js +120 -0
- package/dist/scripts/install-generator.js +67 -54
- package/package.json +18 -17
- package/webpack.config.js +28 -7
- package/dist/babel/trace-babel-plugin.js +0 -243
- package/dist/babel/trace-log-babel-plugin.js +0 -164
package/README.md
CHANGED
|
@@ -21,76 +21,36 @@ The **DazScript Framework** is a TypeScript-based framework for writing Daz Stud
|
|
|
21
21
|
To install the **DazScript Framework**, run the following command:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
npm install dazscript-framework
|
|
24
|
+
npm install dazscript-framework dazscript-types
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## Setup
|
|
28
28
|
|
|
29
|
-
After installing the package,
|
|
29
|
+
After installing the package, scaffold the project files:
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
```javascript
|
|
36
|
-
const sharedBabelConfig = require('dazscript-framework/babel');
|
|
37
|
-
|
|
38
|
-
module.exports = {
|
|
39
|
-
...sharedBabelConfig,
|
|
40
|
-
presets: [...sharedBabelConfig.presets],
|
|
41
|
-
plugins: [...sharedBabelConfig.plugins],
|
|
42
|
-
};
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
2. **package.json**
|
|
46
|
-
|
|
47
|
-
Add the following scripts to your package.json:
|
|
48
|
-
|
|
49
|
-
```json
|
|
50
|
-
"scripts": {
|
|
51
|
-
"prebuild": "npm run installer",
|
|
52
|
-
"build": "webpack --env outputPath=./out",
|
|
53
|
-
"postbuild": "npm run icons",
|
|
54
|
-
"watch": "webpack --env outputPath=./out --watch",
|
|
55
|
-
"icons": "copyfiles -u 1 src/**/*.png out/",
|
|
56
|
-
"installer": "node ./node_modules/dazscript-framework/dist/scripts/install-generator.js -p ./src/scripts -m /MyScripts"
|
|
57
|
-
}
|
|
58
|
-
```
|
|
31
|
+
```bash
|
|
32
|
+
npx dazscript init
|
|
33
|
+
```
|
|
59
34
|
|
|
60
|
-
|
|
35
|
+
This generates:
|
|
61
36
|
|
|
62
|
-
|
|
37
|
+
- `dazscript.config.ts`
|
|
38
|
+
- `tsconfig.json`
|
|
39
|
+
- `package.json` script wiring for `build`, `watch`, `icons`, and `installer`
|
|
63
40
|
|
|
64
|
-
|
|
65
|
-
{
|
|
66
|
-
"extends": "./node_modules/dazscript-framework/tsconfig.json",
|
|
67
|
-
"compilerOptions": {
|
|
68
|
-
"baseUrl": "./",
|
|
69
|
-
"paths": {
|
|
70
|
-
"shared/*": ["src/shared/*"],
|
|
71
|
-
"@dst/*": ["node_modules/dazscript-types/*"],
|
|
72
|
-
"@dsf/*": ["node_modules/dazscript-framework/src/*"]
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
"include": ["node_modules/dazscript-types/**/*", "src/**/*"]
|
|
76
|
-
}
|
|
77
|
-
```
|
|
41
|
+
The generated package scripts use the framework CLI directly, so consumer projects do not need their own webpack or Babel setup.
|
|
78
42
|
|
|
79
|
-
|
|
80
|
-
Create the file and add the following content:
|
|
43
|
+
You can customize the generated defaults:
|
|
81
44
|
|
|
82
|
-
|
|
83
|
-
|
|
45
|
+
```bash
|
|
46
|
+
npx dazscript init --menu-path /MyScripts --scripts-path ./src --out-dir ./out
|
|
47
|
+
```
|
|
84
48
|
|
|
85
|
-
|
|
86
|
-
|
|
49
|
+
- `--menu-path` sets which Daz Studio menu the scripts are added to by default. See [The `@action` Decorator](#the-action-decorator) for how a script can override that with `menuPath`.
|
|
50
|
+
- `--scripts-path` tells the installer generator where to scan for runnable `.dsa.ts` entry files.
|
|
51
|
+
- `--out-dir` sets the webpack build output directory for generated `.dsa` files and copied icons.
|
|
87
52
|
|
|
88
|
-
|
|
89
|
-
...sharedConfig,
|
|
90
|
-
// You can override or add more customizations here if needed
|
|
91
|
-
};
|
|
92
|
-
};
|
|
93
|
-
```
|
|
53
|
+
Use `--scripts-path ./src/scripts` for projects shaped like `scripts/common`, where runnable `.dsa.ts` files live under `src/scripts/`. Use `--scripts-path ./src` for packages shaped like `scripts/power-menu`, where runnable `.dsa.ts` files live at the source root.
|
|
94
54
|
|
|
95
55
|
## Usage
|
|
96
56
|
|
|
@@ -115,6 +75,36 @@ class HelloWorldScript extends BaseScript {
|
|
|
115
75
|
new HelloWorldScript().exec();
|
|
116
76
|
```
|
|
117
77
|
|
|
78
|
+
### The `@action` Decorator
|
|
79
|
+
|
|
80
|
+
Use `@action(...)` on a script class to register how it should appear in Daz Studio.
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
@action({
|
|
84
|
+
text: 'Hello World',
|
|
85
|
+
menuPath: '#{defaultMenuPath}/Examples',
|
|
86
|
+
shortcut: 'CTRL+SHIFT+H',
|
|
87
|
+
toolbar: 'MyToolbar',
|
|
88
|
+
group: 'Examples',
|
|
89
|
+
description: 'Runs the Hello World script',
|
|
90
|
+
})
|
|
91
|
+
class HelloWorldScript extends BaseScript {
|
|
92
|
+
protected run(): void {
|
|
93
|
+
info('Hello World!');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Common `@action(...)` parameters:
|
|
99
|
+
|
|
100
|
+
- `text`: the label shown for the script in Daz Studio.
|
|
101
|
+
- `menuPath`: the menu path where the script should be added. Set it to `false` to skip adding the script to a menu. If omitted, the default menu from `--menu-path` is used.
|
|
102
|
+
- `shortcut`: the keyboard shortcut for the action.
|
|
103
|
+
- `toolbar`: the toolbar name used when the action should appear on a toolbar.
|
|
104
|
+
- `group`: an optional grouping label used by Daz Studio for related actions.
|
|
105
|
+
- `description`: a longer description for the action.
|
|
106
|
+
- `bundle`: generates installer and uninstaller entries as a package bundle instead of a single action entry.
|
|
107
|
+
|
|
118
108
|
### Building UIs with Observables & Dialogs
|
|
119
109
|
|
|
120
110
|
The framework uses a **Model-View pattern** with reactive data bindings:
|
|
@@ -318,8 +308,7 @@ my-daz-scripts/
|
|
|
318
308
|
├── out/ # Generated .dsa files (build output)
|
|
319
309
|
├── package.json
|
|
320
310
|
├── tsconfig.json
|
|
321
|
-
|
|
322
|
-
└── babel.config.js
|
|
311
|
+
└── dazscript.config.ts
|
|
323
312
|
```
|
|
324
313
|
|
|
325
314
|
**Key points:**
|
package/babel.config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
presets: [
|
|
3
3
|
[
|
|
4
|
-
'@babel/preset-env',
|
|
4
|
+
require.resolve('@babel/preset-env'),
|
|
5
5
|
{
|
|
6
6
|
targets: {
|
|
7
7
|
esmodules: true,
|
|
@@ -10,24 +10,16 @@ module.exports = {
|
|
|
10
10
|
include: ['@babel/plugin-transform-class-properties'],
|
|
11
11
|
},
|
|
12
12
|
],
|
|
13
|
-
'@babel/preset-typescript',
|
|
13
|
+
require.resolve('@babel/preset-typescript'),
|
|
14
14
|
],
|
|
15
15
|
plugins: [
|
|
16
|
-
'@babel/plugin-transform-class-properties',
|
|
17
|
-
'babel-plugin-transform-typescript-metadata',
|
|
18
|
-
['@babel/plugin-proposal-decorators', { version: 'legacy' }],
|
|
19
|
-
['@babel/plugin-transform-arrow-functions'],
|
|
20
|
-
'@babel/plugin-transform-block-scoping',
|
|
21
|
-
'@babel/plugin-proposal-class-properties',
|
|
22
|
-
'@babel/plugin-transform-private-property-in-object',
|
|
23
|
-
'@babel/plugin-transform-private-methods',
|
|
24
|
-
[
|
|
25
|
-
'dazscript-framework/babel/trace-babel-plugin', // Ensure this path is correct
|
|
26
|
-
{ default: false, retainLines: false },
|
|
27
|
-
],
|
|
28
|
-
[
|
|
29
|
-
'dazscript-framework/babel/trace-log-babel-plugin', // Ensure this path is correct
|
|
30
|
-
{ default: false, retainLines: false },
|
|
31
|
-
],
|
|
16
|
+
require.resolve('@babel/plugin-transform-class-properties'),
|
|
17
|
+
require.resolve('babel-plugin-transform-typescript-metadata'),
|
|
18
|
+
[require.resolve('@babel/plugin-proposal-decorators'), { version: 'legacy' }],
|
|
19
|
+
[require.resolve('@babel/plugin-transform-arrow-functions')],
|
|
20
|
+
require.resolve('@babel/plugin-transform-block-scoping'),
|
|
21
|
+
require.resolve('@babel/plugin-proposal-class-properties'),
|
|
22
|
+
require.resolve('@babel/plugin-transform-private-property-in-object'),
|
|
23
|
+
require.resolve('@babel/plugin-transform-private-methods'),
|
|
32
24
|
],
|
|
33
25
|
};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const webpack = require('webpack');
|
|
5
|
+
const createWebpackConfig = require('../../webpack.config.js');
|
|
6
|
+
|
|
7
|
+
function runWebpack(workdir, options) {
|
|
8
|
+
const env = {
|
|
9
|
+
context: workdir,
|
|
10
|
+
outputPath: options.outDir || './out',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
if (options.file) {
|
|
14
|
+
env.file = options.file;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const config = createWebpackConfig(env, {
|
|
18
|
+
mode: options.watch ? 'development' : 'production',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const compiler = webpack(config);
|
|
23
|
+
|
|
24
|
+
const handleStats = (error, stats) => {
|
|
25
|
+
if (error) {
|
|
26
|
+
reject(error);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (stats.hasErrors()) {
|
|
31
|
+
reject(new Error(stats.toString({ colors: true })));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log(
|
|
36
|
+
stats.toString({
|
|
37
|
+
colors: true,
|
|
38
|
+
chunks: false,
|
|
39
|
+
modules: false,
|
|
40
|
+
})
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (!options.watch) {
|
|
44
|
+
resolve();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
if (options.watch) {
|
|
49
|
+
compiler.watch({}, handleStats);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
compiler.run((error, stats) => {
|
|
54
|
+
if (error || stats.hasErrors()) {
|
|
55
|
+
handleStats(error, stats);
|
|
56
|
+
compiler.close(() => {});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log(
|
|
61
|
+
stats.toString({
|
|
62
|
+
colors: true,
|
|
63
|
+
chunks: false,
|
|
64
|
+
modules: false,
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
compiler.close((closeError) => {
|
|
69
|
+
if (closeError) {
|
|
70
|
+
reject(closeError);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
resolve();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
runWebpack,
|
|
82
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { runWebpack } = require('./build');
|
|
4
|
+
const { loadConfig } = require('./config-loader');
|
|
5
|
+
const { copyIcons } = require('./icons');
|
|
6
|
+
const { generateInstallerFiles } = require('./install-generator');
|
|
7
|
+
const { initProject } = require('./init');
|
|
8
|
+
|
|
9
|
+
function printHelp() {
|
|
10
|
+
console.log(`dazscript <command> [options]
|
|
11
|
+
|
|
12
|
+
Commands:
|
|
13
|
+
init Scaffold a DazScript project in the current directory
|
|
14
|
+
build Build DazScript files
|
|
15
|
+
watch Build and watch DazScript files
|
|
16
|
+
icons Copy png assets into the output directory
|
|
17
|
+
installer Generate Install.dsa.ts and Uninstall.dsa.ts
|
|
18
|
+
|
|
19
|
+
Options for init:
|
|
20
|
+
--menu-path <path> Default menu path. Default: /MyScripts
|
|
21
|
+
--scripts-path <path> Source directory to scan. Default: ./src
|
|
22
|
+
--out-dir <path> Build output directory. Default: ./out
|
|
23
|
+
--force Overwrite generated files
|
|
24
|
+
--help Show this message
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function parseOptions(args, defaults) {
|
|
29
|
+
const options = { ...defaults };
|
|
30
|
+
|
|
31
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
32
|
+
const arg = args[index];
|
|
33
|
+
|
|
34
|
+
if (arg === '--force') {
|
|
35
|
+
options.force = true;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (arg === '--menu-path') {
|
|
40
|
+
options.menuPath = args[index + 1];
|
|
41
|
+
index += 1;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (arg === '--scripts-path') {
|
|
46
|
+
options.scriptsPath = args[index + 1];
|
|
47
|
+
index += 1;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (arg === '--out-dir') {
|
|
52
|
+
options.outDir = args[index + 1];
|
|
53
|
+
index += 1;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (arg === '--file') {
|
|
58
|
+
options.file = args[index + 1];
|
|
59
|
+
index += 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (arg === '--help') {
|
|
64
|
+
options.help = true;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return options;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getResolvedOptions(workdir, cliOptions) {
|
|
75
|
+
const { config } = loadConfig(workdir);
|
|
76
|
+
|
|
77
|
+
const options = {
|
|
78
|
+
...config,
|
|
79
|
+
...cliOptions,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
if (!options.menuPath && options.defaultMenuPath) {
|
|
83
|
+
options.menuPath = options.defaultMenuPath;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return options;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function main(argv) {
|
|
90
|
+
const [, , command, ...rest] = argv;
|
|
91
|
+
const workdir = process.cwd();
|
|
92
|
+
|
|
93
|
+
if (!command || command === '--help' || command === '-h') {
|
|
94
|
+
printHelp();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const options = parseOptions(rest, {
|
|
99
|
+
force: false,
|
|
100
|
+
menuPath: undefined,
|
|
101
|
+
scriptsPath: undefined,
|
|
102
|
+
outDir: undefined,
|
|
103
|
+
file: undefined,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (options.help) {
|
|
107
|
+
printHelp();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const resolvedOptions = getResolvedOptions(workdir, options);
|
|
112
|
+
resolvedOptions.menuPath = resolvedOptions.menuPath || '/MyScripts';
|
|
113
|
+
resolvedOptions.scriptsPath = resolvedOptions.scriptsPath || './src';
|
|
114
|
+
resolvedOptions.outDir = resolvedOptions.outDir || './out';
|
|
115
|
+
|
|
116
|
+
if (command === 'init') {
|
|
117
|
+
initProject(workdir, resolvedOptions);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (command === 'build') {
|
|
122
|
+
await runWebpack(workdir, resolvedOptions);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (command === 'watch') {
|
|
127
|
+
await runWebpack(workdir, { ...resolvedOptions, watch: true });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (command === 'icons') {
|
|
132
|
+
copyIcons(workdir, resolvedOptions);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (command === 'installer') {
|
|
137
|
+
generateInstallerFiles(workdir, {
|
|
138
|
+
scriptsPath: resolvedOptions.scriptsPath,
|
|
139
|
+
defaultMenuPath: resolvedOptions.menuPath,
|
|
140
|
+
});
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
throw new Error(`Unknown command: ${command}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
Promise.resolve(main(process.argv)).catch((error) => {
|
|
149
|
+
console.error(error.message);
|
|
150
|
+
process.exitCode = 1;
|
|
151
|
+
});
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error(error.message);
|
|
154
|
+
process.exitCode = 1;
|
|
155
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const ts = require('typescript');
|
|
6
|
+
|
|
7
|
+
function loadModuleFromString(code, filename) {
|
|
8
|
+
const module = { exports: {} };
|
|
9
|
+
const dirname = path.dirname(filename);
|
|
10
|
+
const localRequire = (request) => {
|
|
11
|
+
if (request.startsWith('.')) {
|
|
12
|
+
return require(path.resolve(dirname, request));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return require(request);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const fn = new Function(
|
|
19
|
+
'exports',
|
|
20
|
+
'require',
|
|
21
|
+
'module',
|
|
22
|
+
'__filename',
|
|
23
|
+
'__dirname',
|
|
24
|
+
code
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
fn(module.exports, localRequire, module, filename, dirname);
|
|
28
|
+
return module.exports;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getConfigCandidates(workdir) {
|
|
32
|
+
return [
|
|
33
|
+
path.join(workdir, 'dazscript.config.ts'),
|
|
34
|
+
path.join(workdir, 'dazscript.config.js'),
|
|
35
|
+
path.join(workdir, 'dazscript.config.cjs'),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function loadTsConfig(filePath) {
|
|
40
|
+
const source = fs.readFileSync(filePath, 'utf8');
|
|
41
|
+
const transpiled = ts.transpileModule(source, {
|
|
42
|
+
compilerOptions: {
|
|
43
|
+
module: ts.ModuleKind.CommonJS,
|
|
44
|
+
target: ts.ScriptTarget.ES2019,
|
|
45
|
+
esModuleInterop: true,
|
|
46
|
+
},
|
|
47
|
+
fileName: filePath,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const loaded = loadModuleFromString(transpiled.outputText, filePath);
|
|
51
|
+
return loaded.default || loaded;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function loadJsConfig(filePath) {
|
|
55
|
+
const loaded = require(filePath);
|
|
56
|
+
return loaded.default || loaded;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function loadConfig(workdir) {
|
|
60
|
+
for (const candidate of getConfigCandidates(workdir)) {
|
|
61
|
+
if (!fs.existsSync(candidate)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const config = candidate.endsWith('.ts')
|
|
66
|
+
? loadTsConfig(candidate)
|
|
67
|
+
: loadJsConfig(candidate);
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
config,
|
|
71
|
+
filePath: candidate,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
config: {},
|
|
77
|
+
filePath: null,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = {
|
|
82
|
+
loadConfig,
|
|
83
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const glob = require('glob');
|
|
6
|
+
|
|
7
|
+
function copyFile(sourcePath, targetPath) {
|
|
8
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
9
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
10
|
+
console.log(`copy ${path.relative(process.cwd(), targetPath)}`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function copyIcons(workdir, options) {
|
|
14
|
+
const sourceRoot = path.resolve(workdir, 'src');
|
|
15
|
+
const outDir = path.resolve(workdir, options.outDir || './out');
|
|
16
|
+
const pattern = path.join(sourceRoot, '**/*.png').replace(/\\/g, '/');
|
|
17
|
+
const files = glob.sync(pattern);
|
|
18
|
+
|
|
19
|
+
files.forEach((filePath) => {
|
|
20
|
+
const relativePath = path.relative(sourceRoot, filePath);
|
|
21
|
+
copyFile(filePath, path.join(outDir, relativePath));
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
copyIcons,
|
|
27
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
function normalizePath(value, fallback) {
|
|
7
|
+
if (!value) {
|
|
8
|
+
return fallback;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return value.replace(/\\/g, '/');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function formatConfigPath(value) {
|
|
15
|
+
if (value.startsWith('./') || value.startsWith('../') || value.startsWith('/')) {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return `./${value}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function ensureTrailingSlash(value) {
|
|
23
|
+
return value.endsWith('/') ? value : `${value}/`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function readJson(filePath) {
|
|
27
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function writeJson(filePath, json) {
|
|
31
|
+
fs.writeFileSync(filePath, `${JSON.stringify(json, null, 2)}\n`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function writeFileIfNeeded(filePath, content, force) {
|
|
35
|
+
if (fs.existsSync(filePath) && !force) {
|
|
36
|
+
console.log(`skip ${path.basename(filePath)}`);
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fs.writeFileSync(filePath, content);
|
|
41
|
+
console.log(`write ${path.basename(filePath)}`);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function buildConfigContent(options) {
|
|
46
|
+
return `import { defineConfig } from 'dazscript-framework/config';
|
|
47
|
+
|
|
48
|
+
export default defineConfig({
|
|
49
|
+
scriptsPath: '${options.scriptsPath}',
|
|
50
|
+
outDir: '${options.outDir}',
|
|
51
|
+
defaultMenuPath: '${options.menuPath}',
|
|
52
|
+
});
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function buildTsconfigContent() {
|
|
57
|
+
return `{
|
|
58
|
+
"extends": "./node_modules/dazscript-framework/tsconfig.json",
|
|
59
|
+
"compilerOptions": {
|
|
60
|
+
"baseUrl": "./",
|
|
61
|
+
"paths": {
|
|
62
|
+
"shared/*": ["src/shared/*"],
|
|
63
|
+
"@dst/*": ["node_modules/dazscript-types/src/types/*"],
|
|
64
|
+
"@dsf/*": ["node_modules/dazscript-framework/src/*"]
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"include": ["node_modules/dazscript-types/src/types/**/*", "src/**/*"]
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function updatePackageJson(workdir, options) {
|
|
73
|
+
const packageJsonPath = path.join(workdir, 'package.json');
|
|
74
|
+
const packageJson = fs.existsSync(packageJsonPath)
|
|
75
|
+
? readJson(packageJsonPath)
|
|
76
|
+
: { private: true };
|
|
77
|
+
|
|
78
|
+
if (packageJson.sideEffects === undefined) {
|
|
79
|
+
packageJson.sideEffects = false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
packageJson.scripts = {
|
|
83
|
+
...(packageJson.scripts || {}),
|
|
84
|
+
prebuild: 'npm run installer',
|
|
85
|
+
build: 'dazscript build',
|
|
86
|
+
postbuild: 'npm run icons',
|
|
87
|
+
watch: 'dazscript watch',
|
|
88
|
+
icons: 'dazscript icons',
|
|
89
|
+
installer: 'dazscript installer',
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
writeJson(packageJsonPath, packageJson);
|
|
93
|
+
console.log('update package.json');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function initProject(workdir, rawOptions) {
|
|
97
|
+
const options = {
|
|
98
|
+
force: Boolean(rawOptions.force),
|
|
99
|
+
menuPath: normalizePath(rawOptions.menuPath, '/MyScripts'),
|
|
100
|
+
scriptsPath: normalizePath(rawOptions.scriptsPath, './src'),
|
|
101
|
+
outDir: normalizePath(rawOptions.outDir, './out'),
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
writeFileIfNeeded(
|
|
105
|
+
path.join(workdir, 'dazscript.config.ts'),
|
|
106
|
+
buildConfigContent(options),
|
|
107
|
+
options.force
|
|
108
|
+
);
|
|
109
|
+
writeFileIfNeeded(
|
|
110
|
+
path.join(workdir, 'tsconfig.json'),
|
|
111
|
+
buildTsconfigContent(),
|
|
112
|
+
options.force
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
updatePackageJson(workdir, options);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = {
|
|
119
|
+
initProject,
|
|
120
|
+
};
|