@emeryld/manager 0.5.1 â 0.6.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 +55 -19
- package/dist/create-package/index.js +43 -1
- package/dist/create-package/variants/client/client_expo_rn.js +530 -0
- package/dist/create-package/variants/client/client_vite_r.js +583 -0
- package/dist/create-package/variants/client/shared.js +56 -0
- package/dist/create-package/variants/client.js +1 -122
- package/dist/create-package/variants/docker.js +21 -142
- package/dist/create-package/variants/empty.js +1 -0
- package/dist/create-package/variants/fullstack.js +262 -10
- package/dist/docker.js +128 -0
- package/dist/menu.js +44 -10
- package/dist/packages.js +12 -1
- package/package.json +1 -1
package/dist/docker.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { access } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { runHelperCli } from './helper-cli.js';
|
|
4
|
+
import { run } from './utils/run.js';
|
|
5
|
+
function sanitizeName(name) {
|
|
6
|
+
return name
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.replace(/[^a-z0-9]/gi, '-')
|
|
9
|
+
.replace(/-+/g, '-')
|
|
10
|
+
.replace(/^-+|-+$/g, '');
|
|
11
|
+
}
|
|
12
|
+
async function ensureDockerfileExists(dockerfilePath) {
|
|
13
|
+
try {
|
|
14
|
+
await access(dockerfilePath);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
throw new Error(`Dockerfile not found at ${dockerfilePath}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function dockerCommand(args, pkg, options) {
|
|
21
|
+
try {
|
|
22
|
+
await run('docker', args, { cwd: pkg.path });
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (!options?.ignoreErrors)
|
|
26
|
+
throw error;
|
|
27
|
+
// eslint-disable-next-line no-console
|
|
28
|
+
console.warn(error instanceof Error ? error.message : String(error));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function printHelp(image, container) {
|
|
32
|
+
console.log([
|
|
33
|
+
'Docker helper commands:',
|
|
34
|
+
` build -> docker build -t ${image} .`,
|
|
35
|
+
' up -> build then run in detached mode',
|
|
36
|
+
' dev -> build, run, and tail logs',
|
|
37
|
+
' run -> run existing image detached',
|
|
38
|
+
` logs -> docker logs -f ${container}`,
|
|
39
|
+
` stop -> docker stop ${container}`,
|
|
40
|
+
` clean -> docker stop/rm ${container}`,
|
|
41
|
+
` reset -> clean container and remove ${image}`,
|
|
42
|
+
].join('\n'));
|
|
43
|
+
}
|
|
44
|
+
export async function openDockerHelper(pkg) {
|
|
45
|
+
const dockerfilePath = pkg.dockerfilePath ?? path.join(pkg.path, 'Dockerfile');
|
|
46
|
+
await ensureDockerfileExists(dockerfilePath);
|
|
47
|
+
const image = `${pkg.name ?? pkg.dirName}:latest`;
|
|
48
|
+
const container = sanitizeName(pkg.name ?? pkg.dirName) || 'rrr-service';
|
|
49
|
+
const port = process.env.PORT ?? '3000';
|
|
50
|
+
const dockerfileLabel = path
|
|
51
|
+
.relative(process.cwd(), dockerfilePath)
|
|
52
|
+
.replace(/\\/g, '/');
|
|
53
|
+
const scripts = [
|
|
54
|
+
{
|
|
55
|
+
name: 'build',
|
|
56
|
+
emoji: 'đ¨',
|
|
57
|
+
description: 'docker build -t image .',
|
|
58
|
+
handler: () => dockerCommand(['build', '-t', image, '.'], pkg),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'up',
|
|
62
|
+
emoji: 'âŦī¸',
|
|
63
|
+
description: 'Build + run detached',
|
|
64
|
+
handler: async () => {
|
|
65
|
+
await dockerCommand(['build', '-t', image, '.'], pkg);
|
|
66
|
+
await dockerCommand(['run', '-d', '--rm', '-p', `${port}:${port}`, '--name', container, image], pkg);
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'dev',
|
|
71
|
+
emoji: 'đ ī¸',
|
|
72
|
+
description: 'Build, run, tail logs',
|
|
73
|
+
handler: async () => {
|
|
74
|
+
await dockerCommand(['build', '-t', image, '.'], pkg);
|
|
75
|
+
await dockerCommand(['run', '-d', '--rm', '-p', `${port}:${port}`, '--name', container, image], pkg);
|
|
76
|
+
await dockerCommand(['logs', '-f', container], pkg);
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: 'run',
|
|
81
|
+
emoji: 'đ',
|
|
82
|
+
description: 'Run existing image detached',
|
|
83
|
+
handler: () => dockerCommand(['run', '-d', '--rm', '-p', `${port}:${port}`, '--name', container, image], pkg),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'logs',
|
|
87
|
+
emoji: 'đ',
|
|
88
|
+
description: 'Tail docker logs',
|
|
89
|
+
handler: () => dockerCommand(['logs', '-f', container], pkg),
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'stop',
|
|
93
|
+
emoji: 'đ',
|
|
94
|
+
description: 'Stop container',
|
|
95
|
+
handler: () => dockerCommand(['stop', container], pkg),
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: 'clean',
|
|
99
|
+
emoji: 'đ§š',
|
|
100
|
+
description: 'Stop + remove container',
|
|
101
|
+
handler: async () => {
|
|
102
|
+
await dockerCommand(['stop', container], pkg, { ignoreErrors: true });
|
|
103
|
+
await dockerCommand(['rm', '-f', container], pkg, { ignoreErrors: true });
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'reset',
|
|
108
|
+
emoji: 'âģī¸',
|
|
109
|
+
description: 'Clean container and remove image',
|
|
110
|
+
handler: async () => {
|
|
111
|
+
await dockerCommand(['stop', container], pkg, { ignoreErrors: true });
|
|
112
|
+
await dockerCommand(['rm', '-f', container], pkg, { ignoreErrors: true });
|
|
113
|
+
await dockerCommand(['rmi', '-f', image], pkg, { ignoreErrors: true });
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'help',
|
|
118
|
+
emoji: 'âšī¸',
|
|
119
|
+
description: 'Print commands',
|
|
120
|
+
handler: () => printHelp(image, container),
|
|
121
|
+
},
|
|
122
|
+
];
|
|
123
|
+
await runHelperCli({
|
|
124
|
+
title: `Docker helper for ${pkg.name ?? pkg.dirName} (${dockerfileLabel})`,
|
|
125
|
+
scripts,
|
|
126
|
+
argv: [],
|
|
127
|
+
});
|
|
128
|
+
}
|
package/dist/menu.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
// src/menu.js
|
|
2
|
+
import path from 'node:path';
|
|
1
3
|
import { colors, globalEmoji } from './utils/log.js';
|
|
2
4
|
import { updateDependencies, testAll, testSingle, buildAll, buildSingle, } from './workspace.js';
|
|
3
5
|
import { releaseMultiple, releaseSingle } from './release.js';
|
|
4
6
|
import { getOrderedPackages } from './packages.js';
|
|
5
7
|
import { runHelperCli } from './helper-cli.js';
|
|
6
8
|
import { ensureWorkingTreeCommitted } from './preflight.js';
|
|
9
|
+
import { openDockerHelper } from './docker.js';
|
|
7
10
|
import { run } from './utils/run.js';
|
|
8
|
-
function makeManagerStepEntries(targets, packages, state) {
|
|
11
|
+
function makeManagerStepEntries(targets, packages, state, options) {
|
|
12
|
+
const includeBack = options?.includeBack ?? true;
|
|
9
13
|
return [
|
|
10
14
|
{
|
|
11
15
|
name: 'update dependencies',
|
|
@@ -75,19 +79,36 @@ function makeManagerStepEntries(targets, packages, state) {
|
|
|
75
79
|
state.lastStep = 'full';
|
|
76
80
|
},
|
|
77
81
|
},
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
...(includeBack
|
|
83
|
+
? [
|
|
84
|
+
{
|
|
85
|
+
name: 'back',
|
|
86
|
+
emoji: 'âŠī¸',
|
|
87
|
+
description: 'Pick packages again',
|
|
88
|
+
handler: async () => {
|
|
89
|
+
state.lastStep = 'back';
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
]
|
|
93
|
+
: []),
|
|
86
94
|
];
|
|
87
95
|
}
|
|
88
96
|
function makePackageScriptEntries(pkg) {
|
|
89
97
|
const scripts = pkg.json?.scripts ?? {};
|
|
90
98
|
const entries = [];
|
|
99
|
+
if (pkg.dockerfilePath) {
|
|
100
|
+
const dockerLabel = path
|
|
101
|
+
.relative(process.cwd(), pkg.dockerfilePath)
|
|
102
|
+
.replace(/\\/g, '/');
|
|
103
|
+
entries.push({
|
|
104
|
+
name: `Dockerfile (${dockerLabel})`,
|
|
105
|
+
emoji: 'đŗ',
|
|
106
|
+
description: 'manager -> opens the docker cli',
|
|
107
|
+
handler: async () => {
|
|
108
|
+
await openDockerHelper(pkg);
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
}
|
|
91
112
|
Object.entries(scripts)
|
|
92
113
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
93
114
|
.forEach(([name, command]) => {
|
|
@@ -142,7 +163,20 @@ export async function runStepLoop(targets, packages) {
|
|
|
142
163
|
emoji: globalEmoji,
|
|
143
164
|
description: 'update/test/build/publish',
|
|
144
165
|
handler: async () => {
|
|
145
|
-
const managerEntries =
|
|
166
|
+
const managerEntries = [
|
|
167
|
+
...makeManagerStepEntries(targets, packages, state, {
|
|
168
|
+
includeBack: false,
|
|
169
|
+
}),
|
|
170
|
+
{
|
|
171
|
+
name: 'back',
|
|
172
|
+
emoji: 'âŠī¸',
|
|
173
|
+
description: 'Return to package scripts',
|
|
174
|
+
handler: () => {
|
|
175
|
+
// no state change; just exit to the package scripts menu
|
|
176
|
+
state.lastStep = undefined;
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
];
|
|
146
180
|
await runHelperCli({
|
|
147
181
|
title: `Manager actions for ${pkg.name}`,
|
|
148
182
|
scripts: managerEntries,
|
package/dist/packages.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/packages.js
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import { readdir, readFile } from 'node:fs/promises';
|
|
4
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
5
5
|
const rootDir = process.cwd();
|
|
6
6
|
const ignoredDirs = new Set([
|
|
7
7
|
'node_modules',
|
|
@@ -181,6 +181,16 @@ export async function loadPackages() {
|
|
|
181
181
|
byName.get((pkgName ?? '').toLowerCase());
|
|
182
182
|
const substitute = meta?.substitute ?? deriveSubstitute(pkgName) ?? path.basename(pkgDir);
|
|
183
183
|
const color = meta?.color ?? colorFromSeed(pkgName);
|
|
184
|
+
let dockerfilePath;
|
|
185
|
+
try {
|
|
186
|
+
const candidate = path.join(pkgDir, 'Dockerfile');
|
|
187
|
+
const stats = await stat(candidate);
|
|
188
|
+
if (stats.isFile())
|
|
189
|
+
dockerfilePath = candidate;
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// ignore missing Dockerfile
|
|
193
|
+
}
|
|
184
194
|
packages.push({
|
|
185
195
|
dirName: path.basename(pkgDir),
|
|
186
196
|
relativeDir: relativePath,
|
|
@@ -191,6 +201,7 @@ export async function loadPackages() {
|
|
|
191
201
|
name: pkgName ?? path.basename(pkgDir),
|
|
192
202
|
substitute,
|
|
193
203
|
color,
|
|
204
|
+
dockerfilePath,
|
|
194
205
|
});
|
|
195
206
|
}
|
|
196
207
|
catch (error) {
|