@sapphire/cli 1.2.0-next.4c47d1a.0 → 1.2.1-next.00d2a50.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/CHANGELOG.md +81 -0
- package/dist/cli.js +14 -6
- package/dist/commands/generate.js +49 -56
- package/dist/commands/init.js +8 -8
- package/dist/commands/new.js +69 -102
- package/dist/functions/CommandExists.js +54 -46
- package/dist/functions/CreateFileFromTemplate.js +38 -39
- package/dist/functions/FileExists.js +7 -0
- package/package.json +120 -117
- package/dist/functions/index.js +0 -3
- package/dist/prompts/index.js +0 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [1.2.0](https://github.com/sapphiredev/cli/compare/v1.1.0...v1.2.0) (2022-02-26)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- add yarn v3 support ([#84](https://github.com/sapphiredev/cli/issues/84)) ([4c47d1a](https://github.com/sapphiredev/cli/commit/4c47d1aef07b600c0727106bd8d008213f3c2d04))
|
|
10
|
+
|
|
11
|
+
## [1.1.0](https://github.com/sapphiredev/cli/compare/v1.0.2...v1.1.0) (2022-01-31)
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- add tsup and swc template options ([#71](https://github.com/sapphiredev/cli/issues/71)) ([625dd8e](https://github.com/sapphiredev/cli/commit/625dd8ea9d43f7005c72212fb5a65bf0b8aa7492))
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
- **deps:** update dependency commander to v9 ([#76](https://github.com/sapphiredev/cli/issues/76)) ([d75ea1b](https://github.com/sapphiredev/cli/commit/d75ea1b1542490fd67a14630ee67e3223dc3b6e7))
|
|
20
|
+
- Generated command comportnent code has error ([#67](https://github.com/sapphiredev/cli/issues/67)) ([9901517](https://github.com/sapphiredev/cli/commit/990151771e3d1da09dee34c9995d70abc241a769))
|
|
21
|
+
|
|
22
|
+
### [1.0.2](https://github.com/sapphiredev/cli/compare/v1.0.1...v1.0.2) (2021-11-08)
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
- update URL for guide ([0b7e402](https://github.com/sapphiredev/cli/commit/0b7e402e3db26af818824f423059c643374ed920))
|
|
27
|
+
|
|
28
|
+
### [1.0.1](https://github.com/sapphiredev/cli/compare/v1.0.0...v1.0.1) (2021-11-06)
|
|
29
|
+
|
|
30
|
+
### Bug Fixes
|
|
31
|
+
|
|
32
|
+
- allow more node & npm versions in engines field ([ce6c97f](https://github.com/sapphiredev/cli/commit/ce6c97f8c2934796e9d6ab159195f2c0fa05188a))
|
|
33
|
+
- **deps:** update all non-major dependencies ([#36](https://github.com/sapphiredev/cli/issues/36)) ([1a9e791](https://github.com/sapphiredev/cli/commit/1a9e791768ebbe5edd11875ac07c31b9d3cec50e))
|
|
34
|
+
- typo `msg` -> `message` ([#39](https://github.com/sapphiredev/cli/issues/39)) ([0f8933b](https://github.com/sapphiredev/cli/commit/0f8933b1af3927c96a79a1f4d9b1bcc46727dd24))
|
|
35
|
+
|
|
36
|
+
## [1.0.0](https://github.com/sapphiredev/cli/compare/v0.0.3...v1.0.0) (2021-10-16)
|
|
37
|
+
|
|
38
|
+
### [0.0.3](https://github.com/sapphiredev/cli/compare/v0.0.2...v0.0.3) (2021-10-16)
|
|
39
|
+
|
|
40
|
+
### Bug Fixes
|
|
41
|
+
|
|
42
|
+
- **templates:** Overridden run method to messageRun ([#30](https://github.com/sapphiredev/cli/issues/30)) ([07fc1d5](https://github.com/sapphiredev/cli/commit/07fc1d5516f057cd346340de853ded314741335f))
|
|
43
|
+
|
|
44
|
+
### [0.0.2](https://github.com/sapphiredev/cli/compare/v0.0.1...v0.0.2) (2021-10-16)
|
|
45
|
+
|
|
46
|
+
### Features
|
|
47
|
+
|
|
48
|
+
- add `init` command ([588e956](https://github.com/sapphiredev/cli/commit/588e956eeb9867be1e16db9bcd962fd72864d8fc))
|
|
49
|
+
- add JSON scheme for CLI config ([1ca569b](https://github.com/sapphiredev/cli/commit/1ca569b8ed89a869af3d5e39c6f1f4cc988edf08))
|
|
50
|
+
- add prompt for `init` command ([67d5a10](https://github.com/sapphiredev/cli/commit/67d5a106c66df3235260810ac6770234a7e7f2fc))
|
|
51
|
+
- category support ([0498b31](https://github.com/sapphiredev/cli/commit/0498b3125767b1b37614e50795402dbb8d72627e))
|
|
52
|
+
- switch to commander ([#15](https://github.com/sapphiredev/cli/issues/15)) ([8f34fa8](https://github.com/sapphiredev/cli/commit/8f34fa8323a6dfdb79abf2ebaf7fdd4d17f3df4b))
|
|
53
|
+
- YAML support ([#17](https://github.com/sapphiredev/cli/issues/17)) ([f69ae95](https://github.com/sapphiredev/cli/commit/f69ae959b664a3aa4342cf67c27802e197505c08))
|
|
54
|
+
|
|
55
|
+
### Bug Fixes
|
|
56
|
+
|
|
57
|
+
- add timeout when finding the config file ([46e3e21](https://github.com/sapphiredev/cli/commit/46e3e21e2b3e0d431e1eeea612a5da9b636ed34a))
|
|
58
|
+
- create the config file on project root instead of the current folder ([aa3b352](https://github.com/sapphiredev/cli/commit/aa3b352aa22b7cecb2117ced37f8e33202fa492b))
|
|
59
|
+
- include `templates` directory in the npm package ([c85406f](https://github.com/sapphiredev/cli/commit/c85406f9e9ba764a8063f5b7af458eb8b8f23924))
|
|
60
|
+
- path and executable issues on Windows ([f317d7f](https://github.com/sapphiredev/cli/commit/f317d7f35d39d388798e6250d79915e7cfdfa23a))
|
|
61
|
+
- **templates:** typescript types ([3812b34](https://github.com/sapphiredev/cli/commit/3812b34f7467e30624c7993a64366d2cb0821ac9))
|
|
62
|
+
|
|
63
|
+
### 0.0.1 (2021-09-23)
|
|
64
|
+
|
|
65
|
+
### Features
|
|
66
|
+
|
|
67
|
+
- add a function to check if a command exists ([107ccee](https://github.com/sapphiredev/cli/commit/107ccee0b55b3ddf6261d177d6b0b5730512811c))
|
|
68
|
+
- add command: `generate` ([b14a965](https://github.com/sapphiredev/cli/commit/b14a965548f5548ce7ac5e0e53d23c85ca827da2))
|
|
69
|
+
- add command: `new` ([4afa8cd](https://github.com/sapphiredev/cli/commit/4afa8cdaf122bac4bc7b16a8f18a9bda40663d4c))
|
|
70
|
+
- add command: `new` ([ffe5a69](https://github.com/sapphiredev/cli/commit/ffe5a695c0126523a4c9e79ea4817542023de193))
|
|
71
|
+
- add function to create files using templates ([e95db50](https://github.com/sapphiredev/cli/commit/e95db50555a9f02e241bea9753506e12a14b0395))
|
|
72
|
+
- add path aliases ([1b65110](https://github.com/sapphiredev/cli/commit/1b65110d0135f4ee9a064d8ac6f130f06ec8ab4c))
|
|
73
|
+
- add PWSH script for Windows ([c69c55f](https://github.com/sapphiredev/cli/commit/c69c55f44f39b6d1984adaded486e29759118375))
|
|
74
|
+
- add templates for `generate` command ([be6f535](https://github.com/sapphiredev/cli/commit/be6f53583ecba3d959a76a12310ff3d80cbd52dd))
|
|
75
|
+
- update batch file for Windows Command Prompt ([746ab83](https://github.com/sapphiredev/cli/commit/746ab838bc668c863a8fc6b2d9632e4c5790acdc))
|
|
76
|
+
- update config template ([65c47a0](https://github.com/sapphiredev/cli/commit/65c47a0728f4652b725b37ebcf758fb60155de7c))
|
|
77
|
+
- use new template format ([1adcbeb](https://github.com/sapphiredev/cli/commit/1adcbeb39678fbbfe6ea119dd9586d3a022cbc11))
|
|
78
|
+
|
|
79
|
+
### Bug Fixes
|
|
80
|
+
|
|
81
|
+
- language value was not getting replaced when creating the `.sapphirerc.json` file from template ([946a40a](https://github.com/sapphiredev/cli/commit/946a40a4365411c2f20a1ed8806e0057c0afbc56))
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command } from 'commander';
|
|
3
|
-
import { readFile } from 'fs/promises';
|
|
4
|
-
import { URL } from 'url';
|
|
5
|
-
import newCmd from '#commands/new';
|
|
6
2
|
import generateCmd from '#commands/generate';
|
|
7
3
|
import initCmd from '#commands/init';
|
|
4
|
+
import newCmd from '#commands/new';
|
|
5
|
+
import { createColors } from 'colorette';
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { readFile } from 'node:fs/promises';
|
|
8
|
+
import { URL } from 'node:url';
|
|
9
|
+
createColors({ useColor: true });
|
|
8
10
|
const sapphire = new Command();
|
|
9
11
|
const packageFile = new URL('../package.json', import.meta.url);
|
|
10
12
|
const packageJson = JSON.parse(await readFile(packageFile, 'utf-8'));
|
|
11
|
-
sapphire
|
|
13
|
+
sapphire //
|
|
14
|
+
.name('sapphire')
|
|
15
|
+
.version(packageJson.version);
|
|
12
16
|
sapphire
|
|
13
17
|
.command('new')
|
|
14
18
|
.description('creates a new Sapphire project')
|
|
@@ -23,6 +27,10 @@ sapphire
|
|
|
23
27
|
.argument('<component>', 'component/piece name')
|
|
24
28
|
.argument('<name>', 'file name')
|
|
25
29
|
.action(generateCmd);
|
|
26
|
-
sapphire
|
|
30
|
+
sapphire //
|
|
31
|
+
.command('init')
|
|
32
|
+
.description('creates a config file on an existing Sapphire project')
|
|
33
|
+
.alias('i')
|
|
34
|
+
.action(initCmd);
|
|
27
35
|
sapphire.parse(process.argv);
|
|
28
36
|
//# sourceMappingURL=cli.js.map
|
|
@@ -1,69 +1,62 @@
|
|
|
1
1
|
import { componentsFolder } from '#constants';
|
|
2
|
-
import { CreateFileFromTemplate } from '#functions';
|
|
3
|
-
import
|
|
2
|
+
import { CreateFileFromTemplate } from '#functions/CreateFileFromTemplate';
|
|
3
|
+
import { fileExists } from '#functions/FileExists';
|
|
4
|
+
import { Spinner } from '@favware/colorette-spinner';
|
|
5
|
+
import { Result } from '@sapphire/result';
|
|
6
|
+
import { blueBright, red } from 'colorette';
|
|
4
7
|
import findUp from 'find-up';
|
|
5
|
-
import {
|
|
6
|
-
import { readFile } from 'fs/promises';
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return CreateFileFromTemplate(`components/${template}`, target, config, params, false, true).then(resolve).catch(reject);
|
|
27
|
-
}
|
|
28
|
-
return reject(new Error("Can't find the template."));
|
|
29
|
-
});
|
|
8
|
+
import { load } from 'js-yaml';
|
|
9
|
+
import { readFile } from 'node:fs/promises';
|
|
10
|
+
import { basename, join } from 'node:path';
|
|
11
|
+
import { setTimeout as sleep } from 'node:timers/promises';
|
|
12
|
+
async function createComponent(component, name, config, configLoc) {
|
|
13
|
+
const { projectLanguage } = config;
|
|
14
|
+
if (!projectLanguage) {
|
|
15
|
+
throw new Error("There is no 'projectLanguage' field in .sapphirerc.json");
|
|
16
|
+
}
|
|
17
|
+
const template = `${component.toLowerCase()}.${projectLanguage}.sapphire`;
|
|
18
|
+
const corePath = `${componentsFolder}${template}`;
|
|
19
|
+
const userPath = config.customFileTemplates.enabled ? join(configLoc, config.customFileTemplates.location, template) : null;
|
|
20
|
+
const target = join(configLoc, config.locations.base, '%L%', `${name}.${projectLanguage}`);
|
|
21
|
+
const params = { name: basename(name) };
|
|
22
|
+
if (userPath && (await fileExists(userPath))) {
|
|
23
|
+
return CreateFileFromTemplate(userPath, target, config, params, true, true);
|
|
24
|
+
}
|
|
25
|
+
else if (await fileExists(corePath)) {
|
|
26
|
+
return CreateFileFromTemplate(`components/${template}`, target, config, params, false, true);
|
|
27
|
+
}
|
|
28
|
+
throw new Error("Can't find the template.");
|
|
30
29
|
}
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return resolve(null);
|
|
38
|
-
})
|
|
39
|
-
.catch(reject);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
function fetchConfig() {
|
|
43
|
-
return Promise.race([findUp('.sapphirerc.json', { cwd: '.' }), timeout(5000)]).then((a) => {
|
|
44
|
-
if (a)
|
|
45
|
-
return a;
|
|
46
|
-
return Promise.race([findUp('.sapphirerc.yml', { cwd: '.' }), timeout(5000)]);
|
|
47
|
-
});
|
|
30
|
+
async function fetchConfig() {
|
|
31
|
+
const a = await Promise.race([findUp('.sapphirerc.json', { cwd: '.' }), sleep(5000)]);
|
|
32
|
+
if (a) {
|
|
33
|
+
return a;
|
|
34
|
+
}
|
|
35
|
+
return Promise.race([findUp('.sapphirerc.yml', { cwd: '.' }), sleep(5000)]);
|
|
48
36
|
}
|
|
49
37
|
export default async (component, name) => {
|
|
50
|
-
const spinner =
|
|
51
|
-
const fail = (error) => {
|
|
52
|
-
spinner.
|
|
38
|
+
const spinner = new Spinner(`Creating a ${component.toLowerCase()}`).start();
|
|
39
|
+
const fail = (error, additionalExecution) => {
|
|
40
|
+
spinner.error({ text: error });
|
|
41
|
+
additionalExecution?.();
|
|
53
42
|
process.exit(1);
|
|
54
43
|
};
|
|
55
44
|
const configLoc = await fetchConfig();
|
|
56
|
-
if (!configLoc)
|
|
45
|
+
if (!configLoc) {
|
|
57
46
|
return fail("Can't find the Sapphire CLI config.");
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
}
|
|
48
|
+
const config = configLoc.endsWith('json') ? JSON.parse(await readFile(configLoc, 'utf8')) : load(await readFile(configLoc, 'utf8'));
|
|
49
|
+
if (!config) {
|
|
60
50
|
return fail("Can't parse the Sapphire CLI config.");
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
}
|
|
52
|
+
const result = await Result.fromAsync(() => createComponent(component, name, config, configLoc.replace(/.sapphirerc.(json|yml)/g, '')));
|
|
53
|
+
return result.match({
|
|
54
|
+
ok: () => {
|
|
55
|
+
spinner.success();
|
|
56
|
+
console.log(blueBright('Done!'));
|
|
57
|
+
process.exit(0);
|
|
58
|
+
},
|
|
59
|
+
err: (error) => fail(error.message, () => console.log(red(error.message)))
|
|
65
60
|
});
|
|
66
|
-
spinner.succeed();
|
|
67
|
-
return console.log(blueBright('Done!'));
|
|
68
61
|
};
|
|
69
62
|
//# sourceMappingURL=generate.js.map
|
package/dist/commands/init.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { PromptInit } from '#prompts';
|
|
2
|
-
import
|
|
1
|
+
import { PromptInit } from '#prompts/PromptInit';
|
|
2
|
+
import { red } from 'colorette';
|
|
3
3
|
import findUp from 'find-up';
|
|
4
|
-
import {
|
|
4
|
+
import { dump } from 'js-yaml';
|
|
5
|
+
import { writeFile } from 'node:fs/promises';
|
|
5
6
|
import prompts from 'prompts';
|
|
6
|
-
import YAML from 'yaml';
|
|
7
|
-
const { red } = chalk;
|
|
8
7
|
export default async () => {
|
|
9
8
|
const packageJson = await findUp('package.json');
|
|
10
9
|
if (!packageJson) {
|
|
@@ -13,7 +12,7 @@ export default async () => {
|
|
|
13
12
|
}
|
|
14
13
|
const response = await prompts(PromptInit);
|
|
15
14
|
if (!response.preconditions)
|
|
16
|
-
|
|
15
|
+
process.exit(1);
|
|
17
16
|
const config = {
|
|
18
17
|
projectLanguage: response.projectLanguage,
|
|
19
18
|
locations: {
|
|
@@ -28,7 +27,8 @@ export default async () => {
|
|
|
28
27
|
location: response.cftLocation ?? ''
|
|
29
28
|
}
|
|
30
29
|
};
|
|
31
|
-
const file = response.configFormat === 'json' ? JSON.stringify(config, null, 2) :
|
|
32
|
-
|
|
30
|
+
const file = response.configFormat === 'json' ? JSON.stringify(config, null, 2) : dump(config);
|
|
31
|
+
await writeFile(packageJson.replace('package.json', `.sapphirerc.${response.configFormat}`), file);
|
|
32
|
+
process.exit(0);
|
|
33
33
|
};
|
|
34
34
|
//# sourceMappingURL=init.js.map
|
package/dist/commands/new.js
CHANGED
|
@@ -1,120 +1,86 @@
|
|
|
1
|
-
import { CommandExists, CreateFileFromTemplate } from '#functions';
|
|
2
|
-
import { PromptNew } from '#prompts';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import { exec, spawn } from 'child_process';
|
|
5
|
-
import { existsSync } from 'fs';
|
|
6
|
-
import { cp, readFile, rm, writeFile } from 'fs/promises';
|
|
7
|
-
import ora from 'ora';
|
|
8
|
-
import { resolve } from 'path';
|
|
9
|
-
import prompts from 'prompts';
|
|
10
1
|
import { repoUrl } from '#constants';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
2
|
+
import { CommandExists } from '#functions/CommandExists';
|
|
3
|
+
import { CreateFileFromTemplate } from '#functions/CreateFileFromTemplate';
|
|
4
|
+
import { fileExists } from '#functions/FileExists';
|
|
5
|
+
import { PromptNew } from '#prompts/PromptNew';
|
|
6
|
+
import { Spinner } from '@favware/colorette-spinner';
|
|
7
|
+
import { Result } from '@sapphire/result';
|
|
8
|
+
import { blueBright, red } from 'colorette';
|
|
9
|
+
import { execa } from 'execa';
|
|
10
|
+
import { cp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
11
|
+
import { resolve } from 'node:path';
|
|
12
|
+
import prompts from 'prompts';
|
|
13
|
+
async function editPackageJson(location, name) {
|
|
14
|
+
const pjLocation = `./${location}/package.json`;
|
|
15
|
+
const output = JSON.parse(await readFile(pjLocation, 'utf8'));
|
|
16
|
+
if (!output)
|
|
17
|
+
throw new Error("Can't read file.");
|
|
18
|
+
output.name = name;
|
|
19
|
+
const result = await Result.fromAsync(() => writeFile(pjLocation, JSON.stringify(output, null, 2)));
|
|
20
|
+
return result.isOk();
|
|
22
21
|
}
|
|
23
|
-
function installDeps(location, pm, verbose) {
|
|
24
|
-
const
|
|
22
|
+
async function installDeps(location, pm, verbose) {
|
|
23
|
+
const value = await execa(pm.toLowerCase(), ['install'], {
|
|
25
24
|
stdio: verbose ? 'inherit' : undefined,
|
|
26
25
|
cwd: `./${location}/`
|
|
27
26
|
});
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
reject(new Error('An unknown error occured while installing the dependencies. Try running Sapphire CLI with "--verbose" flag.'));
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
});
|
|
27
|
+
if (value.exitCode !== 0) {
|
|
28
|
+
throw new Error('An unknown error occurred while installing the dependencies. Try running Sapphire CLI with "--verbose" flag.');
|
|
29
|
+
}
|
|
30
|
+
const oppositeLockfile = `./${location}/${pm === 'npm' ? 'yarn.lock' : 'package-lock.json'}`;
|
|
31
|
+
if (await fileExists(oppositeLockfile)) {
|
|
32
|
+
await rm(oppositeLockfile);
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
42
35
|
}
|
|
43
|
-
function configureYarnRc(location) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return exec(`yarn config set ${name} ${value}`, { cwd: `./${location}/` }, (e) => {
|
|
47
|
-
if (e)
|
|
48
|
-
return reject(e);
|
|
49
|
-
return resolve(true);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
};
|
|
36
|
+
async function configureYarnRc(location, name, value) {
|
|
37
|
+
await execa('yarn', ['config', 'set', name, value], { cwd: `./${location}/` });
|
|
38
|
+
return true;
|
|
53
39
|
}
|
|
54
|
-
function installYarnV3(location, verbose) {
|
|
55
|
-
const
|
|
40
|
+
async function installYarnV3(location, verbose) {
|
|
41
|
+
const value = await execa('yarn', ['set', 'version', 'berry'], {
|
|
56
42
|
stdio: verbose ? 'inherit' : undefined,
|
|
57
43
|
cwd: `./${location}/`
|
|
58
44
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
reject(new Error('An unknown error occured while installing Yarn v3. Try running Sapphire CLI with "--verbose" flag.'));
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
});
|
|
45
|
+
if (value.exitCode !== 0) {
|
|
46
|
+
throw new Error('An unknown error occurred while installing Yarn v3. Try running Sapphire CLI with "--verbose" flag.');
|
|
47
|
+
}
|
|
48
|
+
await Promise.all([
|
|
49
|
+
//
|
|
50
|
+
configureYarnRc(location, 'enableGlobalCache', 'true'),
|
|
51
|
+
configureYarnRc(location, 'nodeLinker', 'node-modules')
|
|
52
|
+
]);
|
|
53
|
+
return true;
|
|
72
54
|
}
|
|
73
|
-
function installYarnTypescriptPlugin(location) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (!e)
|
|
77
|
-
return resolve(true);
|
|
78
|
-
return reject(e);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
55
|
+
async function installYarnTypescriptPlugin(location) {
|
|
56
|
+
await execa('yarn', ['plugin', 'import', 'typescript'], { cwd: `./${location}/` });
|
|
57
|
+
return true;
|
|
81
58
|
}
|
|
82
|
-
function initializeGitRepo(location) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (!e)
|
|
86
|
-
return resolve(true);
|
|
87
|
-
return reject(e);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
59
|
+
async function initializeGitRepo(location) {
|
|
60
|
+
await execa('git', ['init'], { cwd: `./${location}/` });
|
|
61
|
+
return true;
|
|
90
62
|
}
|
|
91
|
-
function runJob(job, name) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
spinner.
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
spinner.
|
|
101
|
-
console.
|
|
102
|
-
|
|
103
|
-
}
|
|
63
|
+
async function runJob(job, name) {
|
|
64
|
+
const spinner = new Spinner(name).start();
|
|
65
|
+
const result = await Result.fromAsync(() => job());
|
|
66
|
+
return result.match({
|
|
67
|
+
ok: () => {
|
|
68
|
+
spinner.success();
|
|
69
|
+
return true;
|
|
70
|
+
},
|
|
71
|
+
err: (error) => {
|
|
72
|
+
spinner.error({ text: red(error.message) });
|
|
73
|
+
console.error(red(error.message));
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
104
76
|
});
|
|
105
77
|
}
|
|
106
|
-
function cloneRepo(location, verbose) {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
git.on('exit', (code) => {
|
|
113
|
-
code === 0
|
|
114
|
-
? resolve(true)
|
|
115
|
-
: reject(new Error('An unknown error occured while cloning the repository. Try running Sapphire CLI with "--verbose" flag.'));
|
|
116
|
-
});
|
|
117
|
-
});
|
|
78
|
+
async function cloneRepo(location, verbose) {
|
|
79
|
+
const value = await execa('git', ['clone', repoUrl, `${location}/ghr`], { stdio: verbose ? 'inherit' : undefined });
|
|
80
|
+
if (value.exitCode !== 0) {
|
|
81
|
+
throw new Error('An unknown error occurred while cloning the repository. Try running Sapphire CLI with "--verbose" flag.');
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
118
84
|
}
|
|
119
85
|
export default async (name, flags) => {
|
|
120
86
|
const response = await prompts(PromptNew(name, await CommandExists('yarn')));
|
|
@@ -153,5 +119,6 @@ export default async (name, flags) => {
|
|
|
153
119
|
await runJob(job, name).catch(() => process.exit(1));
|
|
154
120
|
}
|
|
155
121
|
console.log(blueBright('Done!'));
|
|
122
|
+
process.exit(0);
|
|
156
123
|
};
|
|
157
124
|
//# sourceMappingURL=new.js.map
|
|
@@ -1,59 +1,67 @@
|
|
|
1
1
|
/*
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
The MIT License (MIT)
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2019 Raphaël Thériault
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
4
23
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
24
|
+
import { fileExists } from '#functions/FileExists';
|
|
25
|
+
import { Result } from '@sapphire/result';
|
|
26
|
+
import { execa } from 'execa';
|
|
27
|
+
import { constants } from 'node:fs';
|
|
28
|
+
import { access } from 'node:fs/promises';
|
|
8
29
|
const windows = process.platform === 'win32';
|
|
9
|
-
function
|
|
10
|
-
|
|
30
|
+
async function isExecutable(command) {
|
|
31
|
+
const result = await Result.fromAsync(() => access(command, constants.X_OK));
|
|
32
|
+
return result.isErr();
|
|
11
33
|
}
|
|
12
|
-
function
|
|
13
|
-
|
|
34
|
+
function cleanWindowsCommand(input) {
|
|
35
|
+
if (/[^A-Za-z0-9_\/:=-]/.test(input)) {
|
|
36
|
+
input = `'${input.replace(/'/g, "'\\''")}'`;
|
|
37
|
+
input = input.replace(/^(?:'')+/g, '').replace(/\\'''/g, "\\'");
|
|
38
|
+
}
|
|
39
|
+
return input;
|
|
14
40
|
}
|
|
15
|
-
function
|
|
16
|
-
if (
|
|
17
|
-
if (
|
|
18
|
-
|
|
19
|
-
input = input.replace(/^(?:'')+/g, '').replace(/\\'''/g, "\\'");
|
|
41
|
+
async function commandExistsUnix(command) {
|
|
42
|
+
if (await fileExists(command)) {
|
|
43
|
+
if (await isExecutable(command)) {
|
|
44
|
+
return true;
|
|
20
45
|
}
|
|
21
|
-
return input;
|
|
22
|
-
}
|
|
23
|
-
if (/[\\]/.test(input)) {
|
|
24
|
-
const dirname = `"${path.dirname(input)}"`;
|
|
25
|
-
const basename = `"${path.basename(input)}"`;
|
|
26
|
-
return `${dirname}:${basename}`;
|
|
27
46
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return fileExists(command).then((exists) => {
|
|
33
|
-
if (exists) {
|
|
34
|
-
void executable(command).then((exists) => res(exists));
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
exec(`command -v ${cleanCommand} 2>/dev/null && { echo >&1 ${cleanCommand}; exit 0; }`, (_err, stdout) => res(Boolean(stdout)));
|
|
38
|
-
}
|
|
39
|
-
});
|
|
47
|
+
const result = await Result.fromAsync(() => execa('which', [command]));
|
|
48
|
+
return result.match({
|
|
49
|
+
err: () => false,
|
|
50
|
+
ok: (value) => Boolean(value.stdout)
|
|
40
51
|
});
|
|
41
52
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
res(true);
|
|
52
|
-
});
|
|
53
|
+
const invalidWindowsCommandNameRegex = /[\x00-\x1f<>:"|?*]/;
|
|
54
|
+
async function commandExistsWindows(command) {
|
|
55
|
+
if (invalidWindowsCommandNameRegex.test(command)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const result = await Result.fromAsync(async () => execa('where', [cleanWindowsCommand(command)]));
|
|
59
|
+
return result.match({
|
|
60
|
+
err: () => fileExists(command),
|
|
61
|
+
ok: () => true
|
|
53
62
|
});
|
|
54
63
|
}
|
|
55
|
-
export function CommandExists(command) {
|
|
56
|
-
|
|
57
|
-
return windows ? commandExistsWindows(command, cleanCommand) : commandExistsUnix(command, cleanCommand);
|
|
64
|
+
export async function CommandExists(command) {
|
|
65
|
+
return windows ? commandExistsWindows(command) : commandExistsUnix(command);
|
|
58
66
|
}
|
|
59
67
|
//# sourceMappingURL=CommandExists.js.map
|
|
@@ -1,45 +1,44 @@
|
|
|
1
|
-
import { existsSync } from 'fs';
|
|
2
|
-
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
3
|
-
import path from 'path';
|
|
4
1
|
import { templatesFolder } from '#constants';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
import { fileExists } from '#functions/FileExists';
|
|
3
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
export async function CreateFileFromTemplate(template, target, config, params, custom = false, component = false) {
|
|
6
|
+
const location = custom ? template : `${templatesFolder}${template}`;
|
|
7
|
+
const output = {};
|
|
8
|
+
if (component) {
|
|
9
|
+
const [c, f] = await getComponentTemplateWithConfig(location);
|
|
10
|
+
output.c = c;
|
|
11
|
+
output.f = f;
|
|
12
|
+
}
|
|
13
|
+
output.f ??= await readFile(location, 'utf8');
|
|
14
|
+
if (!output.f) {
|
|
15
|
+
throw new Error("Can't read file.");
|
|
16
|
+
}
|
|
17
|
+
if (params) {
|
|
18
|
+
for (const param of Object.entries(params)) {
|
|
19
|
+
output.f = output.f.replaceAll(`{{${param[0]}}}`, param[1]);
|
|
13
20
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const ta = component ? target.replace('%L%', dir) : target;
|
|
26
|
-
if (existsSync(ta))
|
|
27
|
-
reject(new Error('Component already exists'));
|
|
28
|
-
await writeFileRecursive(ta, output.f).catch(reject);
|
|
29
|
-
return resolve(true);
|
|
30
|
-
});
|
|
21
|
+
}
|
|
22
|
+
if (!output || (component && (!output.c || !output.c.category))) {
|
|
23
|
+
throw new Error('Invalid template.');
|
|
24
|
+
}
|
|
25
|
+
const dir = component ? config.locations[output.c.category] : null;
|
|
26
|
+
const ta = component ? target.replace('%L%', dir) : target;
|
|
27
|
+
if (await fileExists(ta)) {
|
|
28
|
+
throw new Error('Component already exists');
|
|
29
|
+
}
|
|
30
|
+
await writeFileRecursive(ta, output.f);
|
|
31
|
+
return true;
|
|
31
32
|
}
|
|
32
|
-
function getComponentTemplateWithConfig(path) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
});
|
|
33
|
+
async function getComponentTemplateWithConfig(path) {
|
|
34
|
+
const file = await readFile(path, 'utf8');
|
|
35
|
+
const fa = file.split(/---(\r\n|\r|\n|)/gm);
|
|
36
|
+
return [JSON.parse(fa[0]), fa[2]];
|
|
37
37
|
}
|
|
38
|
-
function writeFileRecursive(target, data) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
38
|
+
async function writeFileRecursive(target, data) {
|
|
39
|
+
const resolvedTarget = resolve(target);
|
|
40
|
+
const dir = dirname(resolvedTarget);
|
|
41
|
+
await mkdir(dir, { recursive: true });
|
|
42
|
+
return writeFile(resolvedTarget, data);
|
|
44
43
|
}
|
|
45
44
|
//# sourceMappingURL=CreateFileFromTemplate.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Result } from '@sapphire/result';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
export async function fileExists(filePath) {
|
|
4
|
+
const result = await Result.fromAsync(() => access(filePath));
|
|
5
|
+
return result.isOk();
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=FileExists.js.map
|
package/package.json
CHANGED
|
@@ -1,118 +1,121 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
2
|
+
"name": "@sapphire/cli",
|
|
3
|
+
"version": "1.2.1-next.00d2a50.0",
|
|
4
|
+
"description": "CLI for Sapphire Framework",
|
|
5
|
+
"author": "@sapphire",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/cli.js",
|
|
9
|
+
"bin": {
|
|
10
|
+
"sapphire": "./dist/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"imports": {
|
|
13
|
+
"#prompts/*": "./dist/prompts/*.js",
|
|
14
|
+
"#functions/*": "./dist/functions/*.js",
|
|
15
|
+
"#commands/*": "./dist/commands/*.js",
|
|
16
|
+
"#constants": "./dist/constants.js"
|
|
17
|
+
},
|
|
18
|
+
"sideEffects": "false",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"!dist/*.tsbuildinfo",
|
|
22
|
+
"!dist/**/*.js.map",
|
|
23
|
+
"!dist/**/*.d.ts",
|
|
24
|
+
"!dist/**/*.d.ts.map",
|
|
25
|
+
"templates"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"lint": "eslint src --ext ts --fix",
|
|
29
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
30
|
+
"update": "yarn upgrade-interactive",
|
|
31
|
+
"build": "tsc -b src",
|
|
32
|
+
"clean": "tsc -b src --clean",
|
|
33
|
+
"watch": "tsc -b src -w",
|
|
34
|
+
"bump": "cliff-jumper",
|
|
35
|
+
"check-update": "cliff-jumper --dry-run",
|
|
36
|
+
"_postinstall": "husky install .github/husky",
|
|
37
|
+
"prepack": "yarn build && pinst --disable",
|
|
38
|
+
"postpack": "pinst --enable"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@favware/colorette-spinner": "^1.0.0",
|
|
42
|
+
"@sapphire/result": "^2.0.1",
|
|
43
|
+
"colorette": "^2.0.19",
|
|
44
|
+
"commander": "^9.4.0",
|
|
45
|
+
"execa": "^6.1.0",
|
|
46
|
+
"find-up": "^5.0.0",
|
|
47
|
+
"js-yaml": "^4.1.0",
|
|
48
|
+
"prompts": "^2.4.2",
|
|
49
|
+
"tslib": "^2.4.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@commitlint/cli": "^17.0.3",
|
|
53
|
+
"@commitlint/config-conventional": "^17.0.3",
|
|
54
|
+
"@favware/cliff-jumper": "^1.8.5",
|
|
55
|
+
"@favware/npm-deprecate": "^1.0.4",
|
|
56
|
+
"@sapphire/eslint-config": "^4.3.7",
|
|
57
|
+
"@sapphire/prettier-config": "^1.4.3",
|
|
58
|
+
"@sapphire/ts-config": "^3.3.4",
|
|
59
|
+
"@types/js-yaml": "^4.0.5",
|
|
60
|
+
"@types/node": "^18.0.1",
|
|
61
|
+
"@types/prompts": "^2.4.0",
|
|
62
|
+
"@typescript-eslint/eslint-plugin": "^5.30.6",
|
|
63
|
+
"@typescript-eslint/parser": "^5.30.6",
|
|
64
|
+
"cz-conventional-changelog": "^3.3.0",
|
|
65
|
+
"eslint": "^8.20.0",
|
|
66
|
+
"eslint-config-prettier": "^8.5.0",
|
|
67
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
68
|
+
"globby": "^13.1.2",
|
|
69
|
+
"husky": "^8.0.1",
|
|
70
|
+
"lint-staged": "^13.0.3",
|
|
71
|
+
"pinst": "^3.0.0",
|
|
72
|
+
"prettier": "^2.7.1",
|
|
73
|
+
"pretty-quick": "^3.1.3",
|
|
74
|
+
"ts-node": "^10.9.1",
|
|
75
|
+
"typescript": "^4.7.4"
|
|
76
|
+
},
|
|
77
|
+
"resolutions": {
|
|
78
|
+
"ansi-regex": "^5.0.1",
|
|
79
|
+
"minimist": "^1.2.6"
|
|
80
|
+
},
|
|
81
|
+
"engines": {
|
|
82
|
+
"node": ">=v16.6.0",
|
|
83
|
+
"npm": ">=7.0.0"
|
|
84
|
+
},
|
|
85
|
+
"keywords": [
|
|
86
|
+
"@sapphire/cli",
|
|
87
|
+
"bot",
|
|
88
|
+
"typescript",
|
|
89
|
+
"ts",
|
|
90
|
+
"yarn",
|
|
91
|
+
"discord",
|
|
92
|
+
"sapphire",
|
|
93
|
+
"discordjs"
|
|
94
|
+
],
|
|
95
|
+
"repository": {
|
|
96
|
+
"type": "git",
|
|
97
|
+
"url": "git+https://github.com/sapphiredev/cli.git"
|
|
98
|
+
},
|
|
99
|
+
"bugs": {
|
|
100
|
+
"url": "https://github.com/sapphiredev/cli/issues"
|
|
101
|
+
},
|
|
102
|
+
"homepage": "https://www.sapphirejs.dev",
|
|
103
|
+
"commitlint": {
|
|
104
|
+
"extends": [
|
|
105
|
+
"@commitlint/config-conventional"
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"lint-staged": {
|
|
109
|
+
"*.{mjs,js,ts}": "eslint --fix --ext mjs,js,ts"
|
|
110
|
+
},
|
|
111
|
+
"config": {
|
|
112
|
+
"commitizen": {
|
|
113
|
+
"path": "./node_modules/cz-conventional-changelog"
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"publishConfig": {
|
|
117
|
+
"access": "public"
|
|
118
|
+
},
|
|
119
|
+
"prettier": "@sapphire/prettier-config",
|
|
120
|
+
"packageManager": "yarn@3.2.1"
|
|
121
|
+
}
|
package/dist/functions/index.js
DELETED
package/dist/prompts/index.js
DELETED