ic-mops 0.23.0 → 0.25.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/README.md +6 -18
- package/cli.ts +25 -6
- package/commands/available-updates.ts +30 -0
- package/commands/init.ts +197 -31
- package/commands/outdated.ts +22 -0
- package/commands/template.ts +83 -15
- package/commands/update.ts +22 -0
- package/declarations/main/main.did +34 -11
- package/declarations/main/main.did.d.ts +19 -8
- package/declarations/main/main.did.js +32 -8
- package/dist/cli.js +23 -6
- package/dist/commands/available-updates.d.ts +2 -0
- package/dist/commands/available-updates.js +24 -0
- package/dist/commands/init.d.ts +3 -1
- package/dist/commands/init.js +174 -29
- package/dist/commands/outdated.d.ts +1 -0
- package/dist/commands/outdated.js +19 -0
- package/dist/commands/template.d.ts +1 -1
- package/dist/commands/template.js +78 -15
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +19 -0
- package/dist/declarations/main/main.did +34 -11
- package/dist/declarations/main/main.did.d.ts +19 -8
- package/dist/declarations/main/main.did.js +32 -8
- package/dist/package.json +2 -1
- package/dist/templates/README.md +13 -0
- package/dist/templates/licenses/Apache-2.0 +202 -0
- package/dist/templates/licenses/Apache-2.0-NOTICE +13 -0
- package/dist/templates/licenses/MIT +21 -0
- package/dist/templates/src/lib.mo +15 -0
- package/dist/templates/test/lib.test.mo +4 -0
- package/package.json +2 -1
- package/templates/README.md +13 -0
- package/templates/licenses/Apache-2.0 +202 -0
- package/templates/licenses/Apache-2.0-NOTICE +13 -0
- package/templates/licenses/MIT +21 -0
- package/templates/src/lib.mo +15 -0
- package/templates/test/lib.test.mo +4 -0
package/README.md
CHANGED
|
@@ -17,28 +17,16 @@ npm i -g ic-mops
|
|
|
17
17
|
|
|
18
18
|
## Install Packages
|
|
19
19
|
|
|
20
|
-
### 1.
|
|
21
|
-
Add `mops` as a packtool to your `dfx.json`
|
|
22
|
-
|
|
23
|
-
```json
|
|
24
|
-
{
|
|
25
|
-
"defaults": {
|
|
26
|
-
"build": {
|
|
27
|
-
"packtool": "mops sources"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### 2. Initialize
|
|
20
|
+
### 1. Initialize
|
|
34
21
|
Run this command in the root directory of your project (where is `dfx.json` placed)
|
|
22
|
+
|
|
35
23
|
If there are Vessel config files, mops will migrate packages from `vessel.dhall` to `mops.toml`
|
|
36
24
|
|
|
37
25
|
```
|
|
38
26
|
mops init
|
|
39
27
|
```
|
|
40
28
|
|
|
41
|
-
###
|
|
29
|
+
### 2. Install Motoko Packages
|
|
42
30
|
Use `mops add <package_name>` to install a specific package and save it to `mops.toml`
|
|
43
31
|
|
|
44
32
|
```
|
|
@@ -65,7 +53,7 @@ Use `mops install` to install all packages specified in `mops.toml`
|
|
|
65
53
|
mops install
|
|
66
54
|
```
|
|
67
55
|
|
|
68
|
-
###
|
|
56
|
+
### 3. Import Package
|
|
69
57
|
Now you can import installed packages in your Motoko code
|
|
70
58
|
|
|
71
59
|
```motoko
|
|
@@ -92,10 +80,10 @@ mops import-identity -- "$(dfx identity export mops)"
|
|
|
92
80
|
```
|
|
93
81
|
|
|
94
82
|
### 2. Initialize
|
|
95
|
-
Run this command in your package root
|
|
83
|
+
Run this command in your package root and select type "Package"
|
|
96
84
|
|
|
97
85
|
```
|
|
98
|
-
mops init
|
|
86
|
+
mops init
|
|
99
87
|
```
|
|
100
88
|
|
|
101
89
|
Edit `description` and `repository` fields in `mops.toml` file.
|
package/cli.ts
CHANGED
|
@@ -22,6 +22,8 @@ import {remove} from './commands/remove.js';
|
|
|
22
22
|
import {getUserProp, setUserProp} from './commands/user.js';
|
|
23
23
|
import {bump} from './commands/bump.js';
|
|
24
24
|
import {sync} from './commands/sync.js';
|
|
25
|
+
import {outdated} from './commands/outdated.js';
|
|
26
|
+
import {update} from './commands/update.js';
|
|
25
27
|
// import {docs} from './commands/docs.js';
|
|
26
28
|
|
|
27
29
|
program.name('mops');
|
|
@@ -32,10 +34,11 @@ program.version(`CLI ${packageJson.version}\nAPI ${apiVersion}`, '-v --version')
|
|
|
32
34
|
|
|
33
35
|
// init
|
|
34
36
|
program
|
|
35
|
-
.command('init
|
|
36
|
-
.description('
|
|
37
|
-
.
|
|
38
|
-
|
|
37
|
+
.command('init')
|
|
38
|
+
.description('Initialize a new project or package in the current directory')
|
|
39
|
+
.option('-y, --yes', 'Accept all defaults')
|
|
40
|
+
.action(async (options) => {
|
|
41
|
+
await init(options);
|
|
39
42
|
});
|
|
40
43
|
|
|
41
44
|
// add
|
|
@@ -111,7 +114,7 @@ program
|
|
|
111
114
|
program
|
|
112
115
|
.command('set-network <network>')
|
|
113
116
|
.alias('sn')
|
|
114
|
-
.description('Set network local|
|
|
117
|
+
.description('Set network local|staging|ic')
|
|
115
118
|
.action(async (network) => {
|
|
116
119
|
await setNetwork(network);
|
|
117
120
|
console.log(`Selected '${network}' network`);
|
|
@@ -290,7 +293,7 @@ program
|
|
|
290
293
|
.command('bump [major|minor|patch]')
|
|
291
294
|
.description('Bump current package version')
|
|
292
295
|
.action(async (part) => {
|
|
293
|
-
bump(part);
|
|
296
|
+
await bump(part);
|
|
294
297
|
});
|
|
295
298
|
|
|
296
299
|
// sync
|
|
@@ -301,4 +304,20 @@ program
|
|
|
301
304
|
await sync();
|
|
302
305
|
});
|
|
303
306
|
|
|
307
|
+
// outdated
|
|
308
|
+
program
|
|
309
|
+
.command('outdated')
|
|
310
|
+
.description('Print outdated dependencies specified in mops.toml')
|
|
311
|
+
.action(async () => {
|
|
312
|
+
await outdated();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// update
|
|
316
|
+
program
|
|
317
|
+
.command('update [pkg]')
|
|
318
|
+
.description('Update dependencies specified in mops.toml')
|
|
319
|
+
.action(async (pkg) => {
|
|
320
|
+
await update(pkg);
|
|
321
|
+
});
|
|
322
|
+
|
|
304
323
|
program.parse();
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import {mainActor} from '../mops.js';
|
|
3
|
+
import {Config} from '../types.js';
|
|
4
|
+
|
|
5
|
+
// [pkg, oldVersion, newVersion]
|
|
6
|
+
export async function getAvailableUpdates(config: Config, pkg?: string): Promise<Array<[string, string, string]>> {
|
|
7
|
+
let deps = Object.values(config.dependencies || {});
|
|
8
|
+
let devDeps = Object.values(config['dev-dependencies'] || {});
|
|
9
|
+
let allDeps = [...deps, ...devDeps].filter((dep) => dep.version);
|
|
10
|
+
let depsToUpdate = pkg ? allDeps.filter((dep) => dep.name === pkg) : allDeps;
|
|
11
|
+
|
|
12
|
+
let getCurrentVersion = (pkg: string) => {
|
|
13
|
+
for (let dep of allDeps) {
|
|
14
|
+
if (dep.name === pkg && dep.version) {
|
|
15
|
+
return dep.version;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return '';
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
let actor = await mainActor();
|
|
22
|
+
let res = await actor.getHighestSemverBatch(depsToUpdate.map((dep) => [dep.name, dep.version || '', {major: null}]));
|
|
23
|
+
|
|
24
|
+
if ('err' in res) {
|
|
25
|
+
console.log(chalk.red('Error:'), res.err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return res.ok.filter((dep) => dep[1] !== getCurrentVersion(dep[0])).map((dep) => [dep[0], getCurrentVersion(dep[0]), dep[1]]);
|
|
30
|
+
}
|
package/commands/init.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import {execSync} from 'node:child_process';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import
|
|
3
|
+
import {existsSync, readFileSync, writeFileSync} from 'node:fs';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
|
-
import
|
|
5
|
+
import prompts from 'prompts';
|
|
6
|
+
|
|
7
|
+
import {checkApiCompatibility, mainActor, writeConfig} from '../mops.js';
|
|
6
8
|
import {installAll} from './install-all.js';
|
|
7
9
|
import {VesselConfig, readVesselConfig} from '../vessel.js';
|
|
8
10
|
import {Config, Dependencies} from '../types.js';
|
|
11
|
+
import {template} from './template.js';
|
|
9
12
|
|
|
10
|
-
export async function init(
|
|
13
|
+
export async function init({yes = false} = {}) {
|
|
11
14
|
let configFile = path.join(process.cwd(), 'mops.toml');
|
|
12
|
-
let exists =
|
|
15
|
+
let exists = existsSync(configFile);
|
|
13
16
|
if (exists) {
|
|
14
17
|
console.log(chalk.yellow('mops.toml already exists'));
|
|
15
18
|
return;
|
|
@@ -18,56 +21,179 @@ export async function init(name = '') {
|
|
|
18
21
|
console.log('Initializing...');
|
|
19
22
|
|
|
20
23
|
let config: Config = {};
|
|
21
|
-
let vesselConfig: VesselConfig = {dependencies: [], 'dev-dependencies': []};
|
|
22
|
-
let deps: Dependencies = {};
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
if (yes) {
|
|
26
|
+
await applyInit({
|
|
27
|
+
type: 'project',
|
|
28
|
+
config,
|
|
29
|
+
setupWorkflow: true,
|
|
30
|
+
addTest: false,
|
|
31
|
+
copyrightOwner: '',
|
|
32
|
+
});
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// migrate from vessel
|
|
37
|
+
let vesselFile = path.join(process.cwd(), 'vessel.dhall');
|
|
38
|
+
let vesselConfig: VesselConfig = {dependencies: [], 'dev-dependencies': []};
|
|
25
39
|
|
|
26
|
-
if (
|
|
40
|
+
if (existsSync(vesselFile)) {
|
|
27
41
|
console.log('Reading vessel.dhall file');
|
|
28
|
-
|
|
42
|
+
let res = await readVesselConfig(process.cwd(), {cache: false});
|
|
29
43
|
if (res) {
|
|
30
44
|
vesselConfig = {...res};
|
|
31
45
|
}
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
if (vesselConfig.dependencies) {
|
|
49
|
+
let deps: Dependencies = {};
|
|
35
50
|
deps = {};
|
|
36
51
|
|
|
37
52
|
for (const dep of (vesselConfig.dependencies || [])) {
|
|
38
53
|
deps[dep.name] = dep;
|
|
39
54
|
}
|
|
55
|
+
|
|
56
|
+
if (Object.keys(deps).length) {
|
|
57
|
+
config.dependencies = deps;
|
|
58
|
+
}
|
|
40
59
|
}
|
|
41
60
|
|
|
42
|
-
|
|
43
|
-
|
|
61
|
+
let promptsConfig = {
|
|
62
|
+
onCancel() {
|
|
63
|
+
console.log('aborted');
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// type
|
|
69
|
+
let {type} = await prompts({
|
|
70
|
+
type: 'select',
|
|
71
|
+
name: 'type',
|
|
72
|
+
message: 'Select type:',
|
|
73
|
+
choices: [
|
|
74
|
+
{title: `Project ${chalk.dim('(I just want to use mops packages in my project)')}`, value: 'project'},
|
|
75
|
+
{title: `Package ${chalk.dim('(I plan to publish this package on mops)')}`, value: 'package'},
|
|
76
|
+
],
|
|
77
|
+
}, promptsConfig);
|
|
78
|
+
|
|
79
|
+
let addTest = false;
|
|
80
|
+
let copyrightOwner = '';
|
|
81
|
+
|
|
82
|
+
// package details
|
|
83
|
+
if (type === 'package') {
|
|
84
|
+
let res = await prompts([
|
|
85
|
+
{
|
|
86
|
+
type: 'text',
|
|
87
|
+
name: 'name',
|
|
88
|
+
message: 'Enter package name:',
|
|
89
|
+
initial: '',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
type: 'text',
|
|
93
|
+
name: 'description',
|
|
94
|
+
message: 'Enter package description:',
|
|
95
|
+
initial: '',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: 'text',
|
|
99
|
+
name: 'repository',
|
|
100
|
+
message: 'Enter package repository url:',
|
|
101
|
+
initial: '',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: 'text',
|
|
105
|
+
name: 'keywords',
|
|
106
|
+
message: 'Enter keywords separated by spaces:',
|
|
107
|
+
initial: '',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: 'select',
|
|
111
|
+
name: 'license',
|
|
112
|
+
message: 'Choose a license:',
|
|
113
|
+
choices: [
|
|
114
|
+
{title: 'MIT', value: 'MIT'},
|
|
115
|
+
{title: 'Apache-2.0', value: 'Apache-2.0'},
|
|
116
|
+
],
|
|
117
|
+
initial: 0,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
type: 'text',
|
|
121
|
+
name: 'copyrightOwner',
|
|
122
|
+
message: 'Enter license copyright owner:',
|
|
123
|
+
initial: '',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'confirm',
|
|
127
|
+
name: 'addTest',
|
|
128
|
+
message: `Add example test file? ${chalk.dim('(test/lib.test.mo)')}`,
|
|
129
|
+
initial: true,
|
|
130
|
+
},
|
|
131
|
+
], promptsConfig);
|
|
132
|
+
|
|
44
133
|
config.package = {
|
|
45
|
-
name,
|
|
46
|
-
version: '
|
|
47
|
-
description: '',
|
|
48
|
-
repository: '',
|
|
134
|
+
name: (res.name || '').trim(),
|
|
135
|
+
version: '1.0.0',
|
|
136
|
+
description: (res.description || '').trim(),
|
|
137
|
+
repository: (res.repository || '').trim(),
|
|
138
|
+
keywords: [...new Set(res.keywords.split(' ').filter(Boolean))] as string[],
|
|
139
|
+
license: (res.license || '').trim(),
|
|
49
140
|
};
|
|
50
141
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
142
|
+
addTest = res.addTest;
|
|
143
|
+
copyrightOwner = res.copyrightOwner;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// GitHub workflow
|
|
147
|
+
let {setupWorkflow} = await prompts({
|
|
148
|
+
type: 'confirm',
|
|
149
|
+
name: 'setupWorkflow',
|
|
150
|
+
message: `Setup GitHub workflow? ${chalk.dim('(run `mops test` on push)')}`,
|
|
151
|
+
initial: true,
|
|
152
|
+
}, promptsConfig);
|
|
153
|
+
|
|
154
|
+
await applyInit({
|
|
155
|
+
type,
|
|
156
|
+
config,
|
|
157
|
+
setupWorkflow,
|
|
158
|
+
addTest,
|
|
159
|
+
copyrightOwner,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
54
162
|
|
|
55
|
-
|
|
163
|
+
type ApplyInitOptions = {
|
|
164
|
+
type: 'project' | 'package';
|
|
165
|
+
config: Config;
|
|
166
|
+
setupWorkflow: boolean;
|
|
167
|
+
addTest: boolean;
|
|
168
|
+
copyrightOwner: string;
|
|
169
|
+
}
|
|
56
170
|
|
|
57
|
-
|
|
58
|
-
|
|
171
|
+
async function applyInit({type, config, setupWorkflow, addTest, copyrightOwner} : ApplyInitOptions) {
|
|
172
|
+
// set packtool in dfx.json
|
|
173
|
+
let dfxJson = path.resolve(process.cwd(), 'dfx.json');
|
|
174
|
+
let dfxJsonData;
|
|
175
|
+
if (existsSync(dfxJson)) {
|
|
176
|
+
let dfxJsonText = readFileSync(dfxJson).toString();
|
|
177
|
+
dfxJsonData = JSON.parse(dfxJsonText);
|
|
178
|
+
console.log('Setting packtool in dfx.json...');
|
|
179
|
+
dfxJsonData.defaults = dfxJsonData.defaults || {};
|
|
180
|
+
dfxJsonData.defaults.build = dfxJsonData.defaults.build || {};
|
|
181
|
+
if (dfxJsonData.defaults.build.packtool !== 'mops sources') {
|
|
182
|
+
dfxJsonData.defaults.build.packtool = 'mops sources';
|
|
183
|
+
let indent = dfxJsonText.match(/([ \t]+)"/)?.[1] || ' ';
|
|
184
|
+
writeFileSync(path.join(process.cwd(), 'dfx.json'), JSON.stringify(dfxJsonData, null, indent));
|
|
185
|
+
console.log(chalk.green('packtool set to "mops sources"'));
|
|
59
186
|
}
|
|
60
187
|
}
|
|
61
188
|
|
|
62
|
-
//
|
|
63
|
-
if (
|
|
189
|
+
// get default packages
|
|
190
|
+
if (type === 'project') {
|
|
64
191
|
let compatible = await checkApiCompatibility();
|
|
65
192
|
if (!compatible) {
|
|
66
193
|
return;
|
|
67
194
|
}
|
|
68
195
|
|
|
69
|
-
let
|
|
70
|
-
let dfxVersion = dfxJson?.dfx || '';
|
|
196
|
+
let dfxVersion = dfxJsonData?.dfx || '';
|
|
71
197
|
if (!dfxVersion) {
|
|
72
198
|
try {
|
|
73
199
|
let res = execSync('dfx --version').toString();
|
|
@@ -79,6 +205,7 @@ export async function init(name = '') {
|
|
|
79
205
|
catch {}
|
|
80
206
|
}
|
|
81
207
|
|
|
208
|
+
console.log(`Fetching default packages for dfx ${dfxVersion}...`);
|
|
82
209
|
let actor = await mainActor();
|
|
83
210
|
let defaultPackages = await actor.getDefaultPackages(dfxVersion);
|
|
84
211
|
|
|
@@ -86,18 +213,57 @@ export async function init(name = '') {
|
|
|
86
213
|
config.dependencies = {};
|
|
87
214
|
}
|
|
88
215
|
|
|
89
|
-
if (deps) {
|
|
90
|
-
config.dependencies = deps;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
216
|
for (let [name, version] of defaultPackages) {
|
|
94
217
|
config.dependencies[name] = {name, version};
|
|
95
218
|
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// save config
|
|
222
|
+
let configFile = path.join(process.cwd(), 'mops.toml');
|
|
223
|
+
writeConfig(config, configFile);
|
|
224
|
+
console.log(chalk.green('Created'), 'mops.toml');
|
|
225
|
+
|
|
226
|
+
// add src/lib.mo
|
|
227
|
+
if (type === 'package' && !existsSync(path.join(process.cwd(), 'src'))) {
|
|
228
|
+
await template('lib.mo');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// add src/lib.test.mo
|
|
232
|
+
if (addTest && !existsSync(path.join(process.cwd(), 'test'))) {
|
|
233
|
+
await template('lib.test.mo');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// add license
|
|
237
|
+
if (config.package?.license) {
|
|
238
|
+
await template(`license:${config.package.license}`, {copyrightOwner});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// add readme
|
|
242
|
+
if (type === 'package') {
|
|
243
|
+
await template('readme');
|
|
244
|
+
}
|
|
96
245
|
|
|
97
|
-
|
|
246
|
+
// add GitHub workflow
|
|
247
|
+
if (setupWorkflow) {
|
|
248
|
+
await template('github-workflow:mops-test');
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// add .mops to .gitignore
|
|
252
|
+
{
|
|
253
|
+
let gitignore = path.join(process.cwd(), '.gitignore');
|
|
254
|
+
let gitignoreData = existsSync(gitignore) ? readFileSync(gitignore).toString() : '';
|
|
255
|
+
let lf = gitignoreData.endsWith('\n') ? '\n' : '';
|
|
256
|
+
if (!gitignoreData.includes('.mops')) {
|
|
257
|
+
writeFileSync(gitignore, `${gitignoreData}\n.mops${lf}`.trimStart());
|
|
258
|
+
console.log(chalk.green('Added'), '.mops to .gitignore');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
98
261
|
|
|
262
|
+
// install deps
|
|
263
|
+
if (Object.keys(config.dependencies || {}).length) {
|
|
264
|
+
console.log('Installing dependencies...');
|
|
99
265
|
await installAll({verbose: true});
|
|
100
266
|
}
|
|
101
267
|
|
|
102
|
-
console.log(chalk.green('
|
|
268
|
+
console.log(chalk.green('Done!'));
|
|
103
269
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import {checkConfigFile, readConfig} from '../mops.js';
|
|
3
|
+
import {getAvailableUpdates} from './available-updates.js';
|
|
4
|
+
|
|
5
|
+
export async function outdated() {
|
|
6
|
+
if (!checkConfigFile()) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
let config = readConfig();
|
|
10
|
+
|
|
11
|
+
let available = await getAvailableUpdates(config);
|
|
12
|
+
|
|
13
|
+
if (available.length === 0) {
|
|
14
|
+
console.log(chalk.green('All dependencies are up to date!'));
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
console.log('Available updates:');
|
|
18
|
+
for (let dep of available) {
|
|
19
|
+
console.log(`${dep[0]} ${chalk.yellow(dep[1])} -> ${chalk.green(dep[2])}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/commands/template.ts
CHANGED
|
@@ -2,29 +2,97 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import prompts from 'prompts';
|
|
5
|
-
import
|
|
5
|
+
import camelCase from 'camelcase';
|
|
6
|
+
import {getRootDir, readConfig} from '../mops.js';
|
|
6
7
|
|
|
7
|
-
export async function template() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
export async function template(templateName?: string, options: any = {}) {
|
|
9
|
+
if (!templateName) {
|
|
10
|
+
let res = await prompts({
|
|
11
|
+
type: 'select',
|
|
12
|
+
name: 'value',
|
|
13
|
+
message: 'Select template:',
|
|
14
|
+
choices: [
|
|
15
|
+
{title: 'README.md', value: 'readme'},
|
|
16
|
+
{title: 'src/lib.mo', value: 'lib.mo'},
|
|
17
|
+
{title: 'test/lib.test.mo', value: 'lib.test.mo'},
|
|
18
|
+
{title: 'License MIT', value: 'license:MIT'},
|
|
19
|
+
{title: 'License Apache-2.0', value: 'license:Apache-2.0'},
|
|
20
|
+
{title: 'GitHub Workflow to run \'mops test\'', value: 'github-workflow:mops-test'},
|
|
21
|
+
{title: '× Cancel', value: ''},
|
|
22
|
+
],
|
|
23
|
+
initial: 0,
|
|
24
|
+
});
|
|
25
|
+
templateName = res.value;
|
|
26
|
+
}
|
|
18
27
|
|
|
19
|
-
if (
|
|
28
|
+
if (templateName === 'github-workflow:mops-test') {
|
|
20
29
|
let dest = path.resolve(getRootDir(), '.github/workflows/mops-test.yml');
|
|
21
30
|
if (fs.existsSync(dest)) {
|
|
22
|
-
console.log(chalk.yellow('Workflow already exists:'), dest);
|
|
31
|
+
console.log(chalk.yellow('Workflow already exists:'), path.relative(getRootDir(), dest));
|
|
23
32
|
return;
|
|
24
33
|
}
|
|
25
34
|
let mopsTestYml = new URL('../templates/mops-test.yml', import.meta.url);
|
|
26
35
|
fs.mkdirSync(path.resolve(getRootDir(), '.github/workflows'), {recursive: true});
|
|
27
36
|
fs.copyFileSync(mopsTestYml, dest);
|
|
28
|
-
console.log(chalk.green('
|
|
37
|
+
console.log(chalk.green('Created'), path.relative(getRootDir(), dest));
|
|
38
|
+
}
|
|
39
|
+
else if (templateName?.startsWith('license:')) {
|
|
40
|
+
let dest = path.resolve(getRootDir(), 'LICENSE');
|
|
41
|
+
if (fs.existsSync(dest)) {
|
|
42
|
+
console.log(chalk.yellow('LICENSE already exists'));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let setYearAndOwner = (file: string) => {
|
|
47
|
+
let license = fs.readFileSync(file).toString();
|
|
48
|
+
license = license.replace(/<year>/g, new Date().getFullYear().toString());
|
|
49
|
+
if (options.copyrightOwner) {
|
|
50
|
+
license = license.replace(/<copyright-owner>/g, options.copyrightOwner);
|
|
51
|
+
}
|
|
52
|
+
fs.writeFileSync(file, license);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
if (templateName === 'license:MIT') {
|
|
56
|
+
fs.copyFileSync(new URL('../templates/licenses/MIT', import.meta.url), path.resolve(getRootDir(), 'LICENSE'));
|
|
57
|
+
setYearAndOwner(path.resolve(getRootDir(), 'LICENSE'));
|
|
58
|
+
console.log(chalk.green('Created'), path.relative(getRootDir(), 'LICENSE'));
|
|
59
|
+
}
|
|
60
|
+
else if (templateName === 'license:Apache-2.0') {
|
|
61
|
+
fs.copyFileSync(new URL('../templates/licenses/Apache-2.0', import.meta.url), path.resolve(getRootDir(), 'LICENSE'));
|
|
62
|
+
fs.copyFileSync(new URL('../templates/licenses/Apache-2.0-NOTICE', import.meta.url), path.resolve(getRootDir(), 'NOTICE'));
|
|
63
|
+
setYearAndOwner(path.resolve(getRootDir(), 'NOTICE'));
|
|
64
|
+
console.log(chalk.green('Created'), path.relative(getRootDir(), 'LICENSE'));
|
|
65
|
+
console.log(chalk.green('Created'), path.relative(getRootDir(), 'NOTICE'));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (templateName === 'lib.mo') {
|
|
69
|
+
fs.mkdirSync(path.join(getRootDir(), 'src'), {recursive: true});
|
|
70
|
+
fs.copyFileSync(new URL('../templates/src/lib.mo', import.meta.url), path.resolve(getRootDir(), 'src/lib.mo'));
|
|
71
|
+
console.log(chalk.green('Created'), path.relative(getRootDir(), 'src/lib.mo'));
|
|
72
|
+
}
|
|
73
|
+
else if (templateName === 'lib.test.mo') {
|
|
74
|
+
fs.mkdirSync(path.join(getRootDir(), 'test'), {recursive: true});
|
|
75
|
+
fs.copyFileSync(new URL('../templates/test/lib.test.mo', import.meta.url), path.resolve(getRootDir(), 'test/lib.test.mo'));
|
|
76
|
+
console.log(chalk.green('Created'), path.relative(getRootDir(), 'test/lib.test.mo'));
|
|
77
|
+
}
|
|
78
|
+
else if (templateName === 'readme') {
|
|
79
|
+
let dest = path.resolve(getRootDir(), 'README.md');
|
|
80
|
+
if (fs.existsSync(dest)) {
|
|
81
|
+
console.log(chalk.yellow('README.md already exists'));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
fs.copyFileSync(new URL('../templates/README.md', import.meta.url), dest);
|
|
85
|
+
|
|
86
|
+
let config = readConfig();
|
|
87
|
+
|
|
88
|
+
let data = fs.readFileSync(dest).toString();
|
|
89
|
+
data = data.replace(/<year>/g, new Date().getFullYear().toString());
|
|
90
|
+
if (config.package?.name) {
|
|
91
|
+
data = data.replace(/<name>/g, config.package.name);
|
|
92
|
+
data = data.replace(/<import-name>/g, camelCase(config.package.name, {pascalCase: true}));
|
|
93
|
+
}
|
|
94
|
+
fs.writeFileSync(dest, data);
|
|
95
|
+
|
|
96
|
+
console.log(chalk.green('Created'), path.relative(getRootDir(), 'README.md'));
|
|
29
97
|
}
|
|
30
98
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import {checkConfigFile, readConfig} from '../mops.js';
|
|
3
|
+
import {add} from './add.js';
|
|
4
|
+
import {getAvailableUpdates} from './available-updates.js';
|
|
5
|
+
|
|
6
|
+
export async function update(pkg?: string) {
|
|
7
|
+
if (!checkConfigFile()) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
let config = readConfig();
|
|
11
|
+
|
|
12
|
+
let available = await getAvailableUpdates(config, pkg);
|
|
13
|
+
|
|
14
|
+
if (available.length === 0) {
|
|
15
|
+
console.log(chalk.green('All dependencies are up to date!'));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
for (let dep of available) {
|
|
19
|
+
await add(`${dep[0]}@${dep[2]}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|