@i-santos/create-package-starter 0.1.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 +34 -0
- package/bin/create-package-starter.js +8 -0
- package/lib/run.js +154 -0
- package/package.json +41 -0
- package/template/CHANGELOG.md +5 -0
- package/template/README.md +15 -0
- package/template/package.json +15 -0
- package/template/scripts/check.js +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# @i-santos/create-package-starter
|
|
2
|
+
|
|
3
|
+
Scaffold new npm packages with a consistent release workflow.
|
|
4
|
+
|
|
5
|
+
## Install / Run
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @i-santos/create-package-starter --name hello-package
|
|
9
|
+
npx @i-santos/create-package-starter --name @i-santos/swarm
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Options
|
|
13
|
+
|
|
14
|
+
- `--name <name>` (required, supports `pkg` and `@scope/pkg`)
|
|
15
|
+
- `--out <directory>` (default: current directory)
|
|
16
|
+
- `--release-cli-pkg <package>` (default: `@i-santos/release-cli`)
|
|
17
|
+
- `--release-cli-version <version>` (default: `^0.1.0`)
|
|
18
|
+
|
|
19
|
+
## Output
|
|
20
|
+
|
|
21
|
+
Generated package includes:
|
|
22
|
+
|
|
23
|
+
- `release:beta`
|
|
24
|
+
- `release:stable`
|
|
25
|
+
- `release:publish`
|
|
26
|
+
- `registry:start`
|
|
27
|
+
|
|
28
|
+
plus a minimal README, CHANGELOG, `.gitignore`, and check script.
|
|
29
|
+
|
|
30
|
+
## Notes
|
|
31
|
+
|
|
32
|
+
- For scoped names, folder uses the short package name.
|
|
33
|
+
- Example: `@i-santos/swarm` creates `./swarm`.
|
|
34
|
+
- Template follows `npm init -y` behavior by default (no `private` field).
|
package/lib/run.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const DEFAULT_RELEASE_CLI_PKG = '@i-santos/release-cli';
|
|
5
|
+
const DEFAULT_RELEASE_CLI_VERSION = '^0.1.0';
|
|
6
|
+
|
|
7
|
+
function usage() {
|
|
8
|
+
return [
|
|
9
|
+
'Uso:',
|
|
10
|
+
' create-package-starter --name <nome> [--out <diretorio>] [--release-cli-pkg <pkg>] [--release-cli-version <versao>]',
|
|
11
|
+
'',
|
|
12
|
+
'Exemplo:',
|
|
13
|
+
' create-package-starter --name hello-package',
|
|
14
|
+
' create-package-starter --name @i-santos/swarm',
|
|
15
|
+
' create-package-starter --name hello-package --out ./packages',
|
|
16
|
+
' create-package-starter --name hello-package --release-cli-pkg @i-santos/release-cli --release-cli-version ^1.0.0'
|
|
17
|
+
].join('\n');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function parseArgs(argv) {
|
|
21
|
+
const args = {
|
|
22
|
+
out: process.cwd(),
|
|
23
|
+
releaseCliPkg: DEFAULT_RELEASE_CLI_PKG,
|
|
24
|
+
releaseCliVersion: DEFAULT_RELEASE_CLI_VERSION
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
28
|
+
const token = argv[i];
|
|
29
|
+
|
|
30
|
+
if (token === '--name') {
|
|
31
|
+
args.name = argv[i + 1];
|
|
32
|
+
i += 1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (token === '--out') {
|
|
37
|
+
args.out = argv[i + 1];
|
|
38
|
+
i += 1;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (token === '--release-cli-pkg') {
|
|
43
|
+
args.releaseCliPkg = argv[i + 1];
|
|
44
|
+
i += 1;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (token === '--release-cli-version') {
|
|
49
|
+
args.releaseCliVersion = argv[i + 1];
|
|
50
|
+
i += 1;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (token === '--help' || token === '-h') {
|
|
55
|
+
args.help = true;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
throw new Error(`Argumento inválido: ${token}\n\n${usage()}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return args;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function validateName(name) {
|
|
66
|
+
if (typeof name !== 'string') {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const plain = /^[a-z0-9][a-z0-9._-]*$/;
|
|
71
|
+
const scoped = /^@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/;
|
|
72
|
+
return plain.test(name) || scoped.test(name);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function packageDirFromName(packageName) {
|
|
76
|
+
const parts = packageName.split('/');
|
|
77
|
+
return parts[parts.length - 1];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function copyDirRecursive(sourceDir, targetDir) {
|
|
81
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
82
|
+
const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
|
|
83
|
+
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
const srcPath = path.join(sourceDir, entry.name);
|
|
86
|
+
const destPath = path.join(targetDir, entry.name);
|
|
87
|
+
|
|
88
|
+
if (entry.isDirectory()) {
|
|
89
|
+
copyDirRecursive(srcPath, destPath);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fs.copyFileSync(srcPath, destPath);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function renderTemplateFile(filePath, variables) {
|
|
98
|
+
const source = fs.readFileSync(filePath, 'utf8');
|
|
99
|
+
const output = source
|
|
100
|
+
.replace(/__PACKAGE_NAME__/g, variables.packageName)
|
|
101
|
+
.replace(/__RELEASE_CLI_PKG__/g, variables.releaseCliPkg)
|
|
102
|
+
.replace(/__RELEASE_CLI_VERSION__/g, variables.releaseCliVersion);
|
|
103
|
+
|
|
104
|
+
fs.writeFileSync(filePath, output);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function run(argv) {
|
|
108
|
+
const args = parseArgs(argv);
|
|
109
|
+
|
|
110
|
+
if (args.help) {
|
|
111
|
+
console.log(usage());
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!validateName(args.name)) {
|
|
116
|
+
throw new Error('Erro: informe um nome válido com --name (ex: hello-package ou @i-santos/swarm).');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!args.releaseCliPkg || !args.releaseCliVersion) {
|
|
120
|
+
throw new Error('Erro: --release-cli-pkg e --release-cli-version devem ser informados corretamente.');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
124
|
+
const templateDir = path.join(packageRoot, 'template');
|
|
125
|
+
|
|
126
|
+
if (!fs.existsSync(templateDir)) {
|
|
127
|
+
throw new Error(`Erro: template não encontrado em ${templateDir}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const outputDir = path.resolve(args.out);
|
|
131
|
+
const targetDir = path.join(outputDir, packageDirFromName(args.name));
|
|
132
|
+
|
|
133
|
+
if (fs.existsSync(targetDir)) {
|
|
134
|
+
throw new Error(`Erro: diretório já existe: ${targetDir}`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
copyDirRecursive(templateDir, targetDir);
|
|
138
|
+
|
|
139
|
+
renderTemplateFile(path.join(targetDir, 'package.json'), {
|
|
140
|
+
packageName: args.name,
|
|
141
|
+
releaseCliPkg: args.releaseCliPkg,
|
|
142
|
+
releaseCliVersion: args.releaseCliVersion
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
renderTemplateFile(path.join(targetDir, 'README.md'), {
|
|
146
|
+
packageName: args.name,
|
|
147
|
+
releaseCliPkg: args.releaseCliPkg,
|
|
148
|
+
releaseCliVersion: args.releaseCliVersion
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
console.log(`Pacote criado em ${targetDir}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = { run };
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@i-santos/create-package-starter",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scaffold new npm packages with standardized release scripts",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Igor Santos",
|
|
7
|
+
"homepage": "https://github.com/i-santos/package-starter#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/i-santos/package-starter.git",
|
|
11
|
+
"directory": "packages/create-package-starter"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/i-santos/package-starter/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"scaffold",
|
|
18
|
+
"npm",
|
|
19
|
+
"starter",
|
|
20
|
+
"cli",
|
|
21
|
+
"template"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"create-package-starter": "bin/create-package-starter.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"bin",
|
|
34
|
+
"lib",
|
|
35
|
+
"template",
|
|
36
|
+
"README.md"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"check": "node scripts/check.js"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# __PACKAGE_NAME__
|
|
2
|
+
|
|
3
|
+
Pacote criado pelo `@i-santos/create-package-starter`.
|
|
4
|
+
|
|
5
|
+
## Comandos
|
|
6
|
+
|
|
7
|
+
- `npm run check`
|
|
8
|
+
- `npm run registry:start`
|
|
9
|
+
- `npm run release:beta`
|
|
10
|
+
- `npm run release:stable`
|
|
11
|
+
- `npm run release:publish`
|
|
12
|
+
|
|
13
|
+
## Dependência de release
|
|
14
|
+
|
|
15
|
+
Este pacote foi gerado para usar `__RELEASE_CLI_PKG__@__RELEASE_CLI_VERSION__`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PACKAGE_NAME__",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Pacote gerado pelo create-package-starter",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"check": "node scripts/check.js",
|
|
7
|
+
"release:beta": "release-cli beta",
|
|
8
|
+
"release:stable": "release-cli stable",
|
|
9
|
+
"release:publish": "release-cli publish",
|
|
10
|
+
"registry:start": "release-cli registry http://127.0.0.1:4873"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"__RELEASE_CLI_PKG__": "__RELEASE_CLI_VERSION__"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
7
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
8
|
+
|
|
9
|
+
const requiredScripts = ['release:beta', 'release:stable', 'release:publish', 'registry:start'];
|
|
10
|
+
for (const scriptName of requiredScripts) {
|
|
11
|
+
if (!pkg.scripts || !pkg.scripts[scriptName]) {
|
|
12
|
+
console.error(`Script obrigatório ausente: ${scriptName}`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
console.log(`check ok para ${pkg.name}@${pkg.version}`);
|