@emeryld/manager 0.3.3 → 0.4.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 +40 -42
- package/dist/create-package/index.js +177 -10
- package/dist/create-package/shared.js +183 -0
- package/dist/create-package/variants/client.js +56 -25
- package/dist/create-package/variants/contract.js +46 -21
- package/dist/create-package/variants/docker.js +96 -29
- package/dist/create-package/variants/empty.js +40 -20
- package/dist/create-package/variants/fullstack.js +130 -406
- package/dist/create-package/variants/server.js +59 -26
- package/dist/publish.js +9 -1
- package/package.json +1 -1
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import { baseTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
2
|
-
const
|
|
1
|
+
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts, baseTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
2
|
+
const CONTRACT_SCRIPTS = [
|
|
3
|
+
'dev',
|
|
4
|
+
'build',
|
|
5
|
+
'typecheck',
|
|
6
|
+
'lint',
|
|
7
|
+
'lint:fix',
|
|
8
|
+
'format',
|
|
9
|
+
'format:check',
|
|
10
|
+
'clean',
|
|
11
|
+
'test',
|
|
12
|
+
];
|
|
13
|
+
export const CONTRACT_TS = `import { defineSocketEvents, finalize, resource } from '@emeryld/rrroutes-contract'
|
|
3
14
|
import { z } from 'zod'
|
|
4
15
|
|
|
5
16
|
const routes = resource('/api')
|
|
@@ -70,51 +81,65 @@ export const socketEvents = sockets.events
|
|
|
70
81
|
export type AppRegistry = typeof registry
|
|
71
82
|
`;
|
|
72
83
|
function contractPackageJson(name) {
|
|
73
|
-
return
|
|
84
|
+
return basePackageJson({
|
|
74
85
|
name,
|
|
75
|
-
version: '0.1.0',
|
|
76
86
|
private: false,
|
|
77
|
-
type: 'module',
|
|
78
|
-
main: 'dist/index.js',
|
|
79
|
-
types: 'dist/index.d.ts',
|
|
80
87
|
exports: {
|
|
81
88
|
'.': {
|
|
82
89
|
types: './dist/index.d.ts',
|
|
83
90
|
import: './dist/index.js',
|
|
84
91
|
},
|
|
85
92
|
},
|
|
86
|
-
|
|
87
|
-
scripts: {
|
|
88
|
-
build: 'tsc -p tsconfig.json',
|
|
89
|
-
typecheck: 'tsc -p tsconfig.json --noEmit',
|
|
90
|
-
},
|
|
93
|
+
scripts: baseScripts('tsx watch src/index.ts'),
|
|
91
94
|
dependencies: {
|
|
92
95
|
'@emeryld/rrroutes-contract': '^2.5.2',
|
|
93
96
|
zod: '^4.2.1',
|
|
94
97
|
},
|
|
95
98
|
devDependencies: {
|
|
96
|
-
|
|
99
|
+
...BASE_LINT_DEV_DEPENDENCIES,
|
|
97
100
|
},
|
|
98
|
-
}
|
|
101
|
+
});
|
|
99
102
|
}
|
|
100
103
|
function contractFiles(pkgName) {
|
|
101
104
|
return {
|
|
102
105
|
'package.json': contractPackageJson(pkgName),
|
|
103
106
|
'tsconfig.json': baseTsConfig(),
|
|
107
|
+
...basePackageFiles(),
|
|
104
108
|
'src/index.ts': CONTRACT_TS,
|
|
105
|
-
'README.md':
|
|
106
|
-
|
|
107
|
-
Contract package scaffolded by manager-cli.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
'README.md': buildReadme({
|
|
110
|
+
name: pkgName,
|
|
111
|
+
description: 'Contract package scaffolded by manager-cli.',
|
|
112
|
+
scripts: CONTRACT_SCRIPTS,
|
|
113
|
+
sections: [
|
|
114
|
+
{
|
|
115
|
+
title: 'Getting Started',
|
|
116
|
+
lines: [
|
|
117
|
+
'- Install deps: `npm install` (or `pnpm install`)',
|
|
118
|
+
'- Start dev mode: `npm run dev`',
|
|
119
|
+
'- Build output: `npm run build`',
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
title: 'Usage',
|
|
124
|
+
lines: [
|
|
125
|
+
'- Edit `src/index.ts` to add routes and socket events.',
|
|
126
|
+
'- Import and share the generated registry in server/client packages.',
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
}),
|
|
112
131
|
};
|
|
113
132
|
}
|
|
114
133
|
export const contractVariant = {
|
|
115
134
|
id: 'rrr-contract',
|
|
116
135
|
label: 'rrr contract',
|
|
117
136
|
defaultDir: 'packages/rrr-contract',
|
|
137
|
+
summary: 'Shared RRRoutes registry + sockets to be consumed by server/client packages.',
|
|
138
|
+
keyFiles: ['src/index.ts', 'README.md'],
|
|
139
|
+
scripts: CONTRACT_SCRIPTS,
|
|
140
|
+
notes: [
|
|
141
|
+
'Edit src/index.ts to define routes and socket events; exports registry/socket config.',
|
|
142
|
+
],
|
|
118
143
|
async scaffold(ctx) {
|
|
119
144
|
const files = contractFiles(ctx.pkgName);
|
|
120
145
|
for (const [relative, contents] of Object.entries(files)) {
|
|
@@ -1,38 +1,49 @@
|
|
|
1
|
-
import { baseTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
1
|
+
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts, baseTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
2
|
+
const DOCKER_SCRIPTS = [
|
|
3
|
+
'dev',
|
|
4
|
+
'build',
|
|
5
|
+
'typecheck',
|
|
6
|
+
'lint',
|
|
7
|
+
'lint:fix',
|
|
8
|
+
'format',
|
|
9
|
+
'format:check',
|
|
10
|
+
'clean',
|
|
11
|
+
'test',
|
|
12
|
+
'start',
|
|
13
|
+
'docker:build',
|
|
14
|
+
'docker:up',
|
|
15
|
+
'docker:dev',
|
|
16
|
+
'docker:logs',
|
|
17
|
+
'docker:stop',
|
|
18
|
+
'docker:clean',
|
|
19
|
+
'docker:reset',
|
|
20
|
+
];
|
|
2
21
|
function dockerPackageJson(name) {
|
|
3
|
-
return
|
|
22
|
+
return basePackageJson({
|
|
4
23
|
name,
|
|
5
|
-
|
|
6
|
-
private: true,
|
|
7
|
-
type: 'module',
|
|
8
|
-
main: 'dist/index.js',
|
|
9
|
-
types: 'dist/index.d.ts',
|
|
10
|
-
files: ['dist'],
|
|
11
|
-
scripts: {
|
|
12
|
-
dev: 'tsx watch src/index.ts',
|
|
13
|
-
build: 'tsc -p tsconfig.json',
|
|
14
|
-
typecheck: 'tsc -p tsconfig.json --noEmit',
|
|
24
|
+
scripts: baseScripts('tsx watch src/index.ts', {
|
|
15
25
|
start: 'node dist/index.js',
|
|
16
26
|
'docker:cli': 'tsx scripts/docker.ts',
|
|
17
27
|
'docker:build': 'npm run docker:cli -- build',
|
|
18
28
|
'docker:up': 'npm run docker:cli -- up',
|
|
29
|
+
'docker:dev': 'npm run docker:cli -- dev',
|
|
19
30
|
'docker:logs': 'npm run docker:cli -- logs',
|
|
20
31
|
'docker:stop': 'npm run docker:cli -- stop',
|
|
21
32
|
'docker:clean': 'npm run docker:cli -- clean',
|
|
22
|
-
|
|
33
|
+
'docker:reset': 'npm run docker:cli -- reset',
|
|
34
|
+
}),
|
|
23
35
|
dependencies: {
|
|
24
36
|
cors: '^2.8.5',
|
|
25
37
|
express: '^5.1.0',
|
|
26
38
|
},
|
|
27
39
|
devDependencies: {
|
|
40
|
+
...BASE_LINT_DEV_DEPENDENCIES,
|
|
28
41
|
'@types/cors': '^2.8.5',
|
|
29
42
|
'@types/express': '^5.0.6',
|
|
30
43
|
'@types/node': '^24.10.2',
|
|
31
44
|
'docker-cli-js': '^3.0.9',
|
|
32
|
-
tsx: '^4.19.0',
|
|
33
|
-
typescript: '^5.9.3',
|
|
34
45
|
},
|
|
35
|
-
}
|
|
46
|
+
});
|
|
36
47
|
}
|
|
37
48
|
function dockerIndexTs() {
|
|
38
49
|
return `import express from 'express'
|
|
@@ -91,14 +102,40 @@ function dockerFiles(pkgName) {
|
|
|
91
102
|
'src/index.ts': dockerIndexTs(),
|
|
92
103
|
'scripts/docker.ts': dockerCliScript(pkgName),
|
|
93
104
|
'.dockerignore': DOCKER_DOCKERIGNORE,
|
|
105
|
+
...basePackageFiles(),
|
|
94
106
|
Dockerfile: dockerDockerfile(),
|
|
95
|
-
'README.md':
|
|
96
|
-
|
|
97
|
-
Dockerized service scaffolded by manager-cli.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
'README.md': buildReadme({
|
|
108
|
+
name: pkgName,
|
|
109
|
+
description: 'Dockerized service scaffolded by manager-cli.',
|
|
110
|
+
scripts: DOCKER_SCRIPTS,
|
|
111
|
+
sections: [
|
|
112
|
+
{
|
|
113
|
+
title: 'Getting Started',
|
|
114
|
+
lines: [
|
|
115
|
+
'- Install deps: `npm install` (or `pnpm install`)',
|
|
116
|
+
'- Local dev: `npm run dev`',
|
|
117
|
+
'- Build output: `npm run build`',
|
|
118
|
+
'- Start built app: `npm start`',
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
title: 'Docker Helpers',
|
|
123
|
+
lines: [
|
|
124
|
+
'- Build image: `npm run docker:build`',
|
|
125
|
+
'- Build + run detached: `npm run docker:up`',
|
|
126
|
+
'- Build + run + tail logs: `npm run docker:dev`',
|
|
127
|
+
'- Tail logs: `npm run docker:logs`',
|
|
128
|
+
'- Stop container: `npm run docker:stop`',
|
|
129
|
+
'- Clean container: `npm run docker:clean`',
|
|
130
|
+
'- Reset container/image: `npm run docker:reset`',
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
title: 'Environment',
|
|
135
|
+
lines: ['- `PORT` sets the exposed port (default 3000).'],
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
}),
|
|
102
139
|
};
|
|
103
140
|
}
|
|
104
141
|
function dockerCliScript(pkgName) {
|
|
@@ -126,32 +163,50 @@ async function main() {
|
|
|
126
163
|
await docker.command(\`build -t \${image} .\`)
|
|
127
164
|
return docker.command(\`run -d --rm -p \${port}:\${port} --name \${container} \${image}\`)
|
|
128
165
|
}
|
|
166
|
+
if (command === 'dev') {
|
|
167
|
+
await docker.command(\`build -t \${image} .\`)
|
|
168
|
+
await docker.command(\`run -d --rm -p \${port}:\${port} --name \${container} \${image}\`)
|
|
169
|
+
return docker.command(\`logs -f \${container}\`)
|
|
170
|
+
}
|
|
129
171
|
if (command === 'run') {
|
|
130
172
|
return docker.command(\`run -d --rm -p \${port}:\${port} --name \${container} \${image}\`)
|
|
131
173
|
}
|
|
132
174
|
if (command === 'logs') return docker.command(\`logs -f \${container}\`)
|
|
133
175
|
if (command === 'stop') return docker.command(\`stop \${container}\`)
|
|
134
176
|
if (command === 'clean') {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
177
|
+
await safe(() => docker.command(\`stop \${container}\`))
|
|
178
|
+
await safe(() => docker.command(\`rm -f \${container}\`))
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
if (command === 'reset') {
|
|
182
|
+
await safe(() => docker.command(\`stop \${container}\`))
|
|
183
|
+
await safe(() => docker.command(\`rm -f \${container}\`))
|
|
184
|
+
await safe(() => docker.command(\`rmi -f \${image}\`))
|
|
140
185
|
return
|
|
141
186
|
}
|
|
142
187
|
return printHelp()
|
|
143
188
|
}
|
|
144
189
|
|
|
190
|
+
async function safe(run: () => Promise<unknown>) {
|
|
191
|
+
try {
|
|
192
|
+
await run()
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.warn(String(error))
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
145
198
|
function printHelp() {
|
|
146
199
|
console.log(
|
|
147
200
|
[
|
|
148
201
|
'Docker helper commands:',
|
|
149
202
|
' build -> docker build -t ${pkgName}:latest .',
|
|
150
203
|
' up -> build then run in detached mode',
|
|
204
|
+
' dev -> build, run, and tail logs',
|
|
151
205
|
' run -> run existing image detached',
|
|
152
206
|
' logs -> docker logs -f <container>',
|
|
153
207
|
' stop -> docker stop <container>',
|
|
154
|
-
' clean -> docker rm
|
|
208
|
+
' clean -> docker stop/rm <container>',
|
|
209
|
+
' reset -> clean container and remove image',
|
|
155
210
|
].join('\\n'),
|
|
156
211
|
)
|
|
157
212
|
}
|
|
@@ -166,6 +221,18 @@ export const dockerVariant = {
|
|
|
166
221
|
id: 'rrr-docker',
|
|
167
222
|
label: 'dockerized service',
|
|
168
223
|
defaultDir: 'packages/rrr-docker',
|
|
224
|
+
summary: 'Express service plus Dockerfile and a helper CLI for local runs.',
|
|
225
|
+
keyFiles: [
|
|
226
|
+
'src/index.ts',
|
|
227
|
+
'scripts/docker.ts',
|
|
228
|
+
'Dockerfile',
|
|
229
|
+
'README.md',
|
|
230
|
+
],
|
|
231
|
+
scripts: DOCKER_SCRIPTS,
|
|
232
|
+
notes: [
|
|
233
|
+
'Use docker:dev or docker:up to build and run the container quickly.',
|
|
234
|
+
'scripts/docker.ts wraps common docker commands with consistent naming.',
|
|
235
|
+
],
|
|
169
236
|
async scaffold(ctx) {
|
|
170
237
|
const files = dockerFiles(ctx.pkgName);
|
|
171
238
|
for (const [relative, contents] of Object.entries(files)) {
|
|
@@ -1,39 +1,59 @@
|
|
|
1
|
-
import { baseTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
1
|
+
import { BASE_LINT_DEV_DEPENDENCIES, basePackageFiles, basePackageJson, buildReadme, baseScripts, baseTsConfig, writeFileIfMissing, } from '../shared.js';
|
|
2
|
+
const EMPTY_SCRIPTS = [
|
|
3
|
+
'dev',
|
|
4
|
+
'build',
|
|
5
|
+
'typecheck',
|
|
6
|
+
'lint',
|
|
7
|
+
'lint:fix',
|
|
8
|
+
'format',
|
|
9
|
+
'format:check',
|
|
10
|
+
'clean',
|
|
11
|
+
'test',
|
|
12
|
+
];
|
|
2
13
|
function emptyPackageJson(name) {
|
|
3
|
-
return
|
|
14
|
+
return basePackageJson({
|
|
4
15
|
name,
|
|
5
|
-
|
|
6
|
-
private: true,
|
|
7
|
-
type: 'module',
|
|
8
|
-
main: 'dist/index.js',
|
|
9
|
-
types: 'dist/index.d.ts',
|
|
10
|
-
files: ['dist'],
|
|
11
|
-
scripts: {
|
|
12
|
-
build: 'tsc -p tsconfig.json',
|
|
13
|
-
typecheck: 'tsc -p tsconfig.json --noEmit',
|
|
14
|
-
},
|
|
16
|
+
scripts: baseScripts('tsx watch src/index.ts'),
|
|
15
17
|
devDependencies: {
|
|
16
|
-
|
|
18
|
+
...BASE_LINT_DEV_DEPENDENCIES,
|
|
17
19
|
},
|
|
18
|
-
}
|
|
20
|
+
});
|
|
19
21
|
}
|
|
20
22
|
function emptyFiles(pkgName) {
|
|
21
23
|
return {
|
|
22
24
|
'package.json': emptyPackageJson(pkgName),
|
|
23
25
|
'tsconfig.json': baseTsConfig({ types: ['node'] }),
|
|
26
|
+
...basePackageFiles(),
|
|
24
27
|
'src/index.ts': "export const hello = 'world'\n",
|
|
25
|
-
'README.md':
|
|
26
|
-
|
|
27
|
-
Empty package scaffolded by manager-cli.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
'README.md': buildReadme({
|
|
29
|
+
name: pkgName,
|
|
30
|
+
description: 'Empty package scaffolded by manager-cli.',
|
|
31
|
+
scripts: EMPTY_SCRIPTS,
|
|
32
|
+
sections: [
|
|
33
|
+
{
|
|
34
|
+
title: 'Getting Started',
|
|
35
|
+
lines: [
|
|
36
|
+
'- Install deps: `npm install` (or `pnpm install`)',
|
|
37
|
+
'- Start dev mode: `npm run dev`',
|
|
38
|
+
'- Build output: `npm run build`',
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
title: 'Notes',
|
|
43
|
+
lines: ['- Edit `src/index.ts` to start coding.'],
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
}),
|
|
31
47
|
};
|
|
32
48
|
}
|
|
33
49
|
export const emptyVariant = {
|
|
34
50
|
id: 'rrr-empty',
|
|
35
51
|
label: 'empty package',
|
|
36
52
|
defaultDir: 'packages/rrr-empty',
|
|
53
|
+
summary: 'Minimal TypeScript package with lint/format/test scaffolding.',
|
|
54
|
+
keyFiles: ['src/index.ts', 'README.md'],
|
|
55
|
+
scripts: EMPTY_SCRIPTS,
|
|
56
|
+
notes: ['Start coding in src/index.ts; everything else is wired up.'],
|
|
37
57
|
async scaffold(ctx) {
|
|
38
58
|
const files = emptyFiles(ctx.pkgName);
|
|
39
59
|
for (const [relative, contents] of Object.entries(files)) {
|