makepack 1.6.9 → 1.6.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makepack",
3
- "version": "1.6.9",
3
+ "version": "1.6.10",
4
4
  "type": "module",
5
5
  "description": "A CLI tool to create, build, and manage JavaScript, TypeScript, React, and React-TypeScript libraries for npm projects.",
6
6
  "files": [
@@ -33,15 +33,14 @@
33
33
  "chalk": "^5.4.1",
34
34
  "chokidar": "^4.0.3",
35
35
  "commander": "^12.1.0",
36
- "cosmiconfig": "^9.0.0",
37
- "esbuild": "^0.25.0",
36
+ "esbuild": "^0.25.5",
38
37
  "express": "^4.21.1",
39
- "figures": "^6.1.0",
40
38
  "fs-extra": "^11.2.0",
41
39
  "glob": "^11.0.0",
42
40
  "inquirer": "^12.1.0",
41
+ "lodash.debounce": "^4.0.8",
42
+ "madge": "^8.0.0",
43
43
  "ora": "^8.1.1",
44
- "typescript": "^5.7.2",
45
44
  "vite": "^6.0.2"
46
45
  },
47
46
  "keywords": [
@@ -56,6 +55,7 @@
56
55
  "devDependencies": {
57
56
  "@types/fs-extra": "^11.0.4",
58
57
  "react": "^19.0.0",
59
- "react-dom": "^19.0.0"
58
+ "react-dom": "^19.0.0",
59
+ "typescript": "^5.7.2"
60
60
  }
61
61
  }
@@ -1,117 +1,172 @@
1
- import path from 'path'
2
- import fs from 'fs'
3
- import { spawn } from 'child_process'
4
- import esbuild from 'esbuild';
5
- import { fileURLToPath } from 'url';
1
+ import express from 'express';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+ import { pathToFileURL } from 'url';
5
+ import { createRequire } from 'module';
6
6
  import chokidar from 'chokidar';
7
+ import madge from 'madge';
8
+ import viteSetup from './vite.js';
9
+ import * as esbuild from 'esbuild';
10
+ import { randomUUID } from 'crypto';
11
+ import debounce from 'lodash.debounce';
12
+ import { logger, concolor } from '../../helpers.js';
13
+
14
+ const projectRoot = process.cwd();
15
+ const requireFn = createRequire(import.meta.url);
16
+
17
+ let server = null;
18
+ let app = null;
19
+ let viteServer = null;
20
+
21
+ const pkg = path.join(process.cwd(), 'package.json');
22
+ const pkgjson = JSON.parse(fs.readFileSync(pkg, 'utf-8'));
23
+ let isEsmProject = pkgjson.type === 'module';
24
+
25
+ const uxpfileJS = path.resolve(projectRoot, 'express.js');
26
+ const uxpfileTS = path.resolve(projectRoot, 'express.ts');
27
+ const expExists = fs.existsSync(uxpfileJS) || fs.existsSync(uxpfileTS);
28
+ let uxpfile = expExists ? (fs.existsSync(uxpfileJS) ? uxpfileJS : uxpfileTS) : null;
29
+
30
+ const connections = new Set();
31
+
32
+ function trackConnections(srv) {
33
+ srv.on('connection', (conn) => {
34
+ connections.add(conn);
35
+ conn.on('close', () => connections.delete(conn));
36
+ });
37
+ }
7
38
 
8
- let __filename, __dirname;
39
+ async function bootServer(args) {
40
+ let wasServer = !!server;
41
+ if (server) {
42
+ for (const conn of connections) {
43
+ conn.destroy();
44
+ }
45
+ await new Promise((resolve, reject) => {
46
+ server.close(err => {
47
+ if (err) {
48
+ logger.error(`while closing server: ${err.message || err}`);
49
+ reject(err);
50
+ } else {
51
+ resolve();
52
+ }
53
+ });
54
+ });
55
+ server = null;
56
+ }
9
57
 
10
- if (typeof import.meta.url !== 'undefined') {
11
- __filename = fileURLToPath(import.meta.url);
12
- __dirname = path.dirname(__filename);
13
- } else {
14
- __filename = __filename;
15
- __dirname = __dirname;
16
- }
58
+ if (viteServer) {
59
+ await viteServer.close();
60
+ }
17
61
 
18
- const startServer = () => {
19
- const mpack = path.join(process.cwd(), '.mpack')
20
- const server = spawn('node', [path.resolve(mpack, 'index.js')], {
21
- stdio: 'inherit',
22
- });
62
+ app = express();
63
+ try {
64
+ const middleware = await loadExp();
65
+ if (typeof middleware === 'function') {
66
+ middleware(app);
67
+ }
23
68
 
24
- server.on('error', (err) => {
25
- console.error(`Error starting server: ${err.message}`);
26
- });
27
- return server;
69
+ viteServer = await viteSetup(app);
70
+ const port = args.port || 4000;
71
+ server = app.listen(port, () => {
72
+ if (!wasServer) {
73
+ logger.success(`Server running on: ${concolor.green(concolor.bold(`http://localhost:${port}`))}`, '')
74
+ }
75
+ trackConnections(server);
76
+ })
77
+ } catch (err) {
78
+ logger.error(`Failed to start server: ${err.message || err}`);
79
+ }
28
80
  }
29
81
 
30
- const start = async (args) => {
31
- let port = args.port || 4000
32
82
 
33
- // create a folder call .mpack
34
- const mpack = path.join(process.cwd(), '.mpack')
35
- if (fs.existsSync(mpack)) {
36
- fs.rmSync(mpack, { recursive: true, force: true });
83
+ let esbuildCtx = null;
84
+ const mpack = path.join(projectRoot, '.mpack');
85
+ if (fs.existsSync(mpack)) {
86
+ fs.rmSync(mpack, { recursive: true, force: true });
87
+ }
88
+ fs.mkdirSync(mpack, { recursive: true });
89
+ const buildFile = path.join(mpack, `${randomUUID().substring(0, 15)}.js`);
90
+
91
+ async function loadExp() {
92
+ if (!expExists) return null
93
+
94
+ const cacheKeys = Object.keys(requireFn.cache || {});
95
+ if (!isEsmProject) {
96
+ for (const key of cacheKeys) {
97
+ if (key.startsWith(process.cwd())) {
98
+ delete requireFn.cache[key];
99
+ }
100
+ }
37
101
  }
38
- fs.mkdirSync(mpack)
39
-
40
- let format = 'esm'
41
- const pkg = path.join(process.cwd(), 'package.json')
42
- if (fs.existsSync(pkg)) {
43
- const pkgjson = JSON.parse(fs.readFileSync(pkg, 'utf-8'))
44
- if (pkgjson.type === 'commonjs') {
45
- format = 'cjs'
102
+
103
+ const ext = path.extname(uxpfile);
104
+ const isTs = ext === '.ts';
105
+
106
+ if (isTs) {
107
+ if (esbuildCtx) {
108
+ await esbuildCtx.rebuild();
109
+ } else {
110
+ esbuildCtx = await esbuild.context({
111
+ entryPoints: [uxpfile],
112
+ outfile: buildFile,
113
+ format: isEsmProject ? 'esm' : 'cjs',
114
+ platform: 'node',
115
+ sourcemap: 'inline',
116
+ bundle: true,
117
+ packages: 'external',
118
+ });
119
+ await esbuildCtx.rebuild();
120
+ }
121
+
122
+ if (isEsmProject) {
123
+ const mod = await import(pathToFileURL(buildFile).href + `?update=${Date.now()}`);
124
+ return mod.default || mod;
125
+ } else {
126
+ return requireFn(buildFile);
46
127
  }
47
128
  }
48
129
 
49
- await esbuild.build({
50
- entryPoints: [path.resolve(__dirname, 'express.js')],
51
- outfile: path.join(mpack, 'core.js'),
52
- bundle: true,
53
- minify: true,
54
- format,
55
- platform: 'node',
56
- packages: 'external',
57
- define: {
58
- 'process.env.PORT': JSON.stringify(port),
59
- },
60
- })
61
-
62
- const uxpjs = path.join(process.cwd(), 'express.js')
63
- const uxpts = path.join(process.cwd(), 'express.ts')
64
- const exists = fs.existsSync(uxpjs) || fs.existsSync(uxpts);
65
- const uxpFile = exists ? (fs.existsSync(uxpjs) ? 'express.js' : 'express.ts') : '';
66
- let contents = `import server from './.mpack/core';`;
67
- contents += uxpFile ? `
68
- import uxp from './${uxpFile}';
69
- server(uxp);
70
- ` : `server();`;
71
-
72
- const result = await esbuild.build({
73
- bundle: true,
74
- stdin: {
75
- contents,
76
- resolveDir: process.cwd(),
77
- sourcefile: 'virtual.js',
78
- loader: 'ts',
79
- },
80
- format,
81
- outfile: path.join(mpack, 'index.js'),
82
- platform: 'node',
83
- packages: 'external',
84
- sourcemap: true,
85
- metafile: true,
86
- })
87
-
88
- let server = startServer();
89
- if (uxpFile) {
90
- const importedFiles = Object.keys(result.metafile.inputs);
91
- const watcher = chokidar.watch(importedFiles, {
92
- ignored: /node_modules/,
93
- ignoreInitial: true
94
- });
130
+ if (isEsmProject) {
131
+ const mod = await import(pathToFileURL(uxpfile).href + `?update=${Date.now()}`);
132
+ return mod.default || mod;
133
+ } else {
134
+ return requireFn(uxpfile);
135
+ }
136
+ }
95
137
 
96
- watcher.on('change', async () => {
97
- server.kill();
98
- server = startServer();
99
- });
138
+ async function getAllDependencies() {
139
+ try {
140
+ const result = await madge(uxpfile, { fileExtensions: ['ts', 'js'] });
141
+ const deps = Object.keys(result.obj());
142
+ const circular = await result.circular();
143
+ if (circular.length) {
144
+ logger.warn(`Circular dependencies detected: ${circular.map(c => c.join(' -> ')).join(', ')}`);
145
+ }
146
+ return deps.map(dep => path.resolve(path.dirname(uxpfile), dep));
147
+ } catch (err) {
148
+ logger.error(`Failed to analyze dependencies with madge: ${err.message || err}`);
149
+ return [uxpfile];
100
150
  }
151
+ }
101
152
 
102
- process.on('SIGINT', () => {
103
- console.log('Received SIGINT, killing server...');
104
- server.kill('SIGINT');
105
- process.exit(0);
106
- });
107
153
 
108
- process.on('SIGTERM', () => {
109
- console.log('Received SIGTERM, killing server...');
110
- server.kill('SIGTERM');
111
- process.exit(0);
112
- });
154
+ let watcher;
155
+ async function startDevServer(args) {
156
+ await bootServer(args);
157
+ const filesToWatch = await getAllDependencies();
158
+ if (watcher) watcher.close();
159
+ watcher = chokidar.watch(filesToWatch, { ignoreInitial: true });
113
160
 
114
- }
161
+ const reload = debounce(async (f) => {
162
+ await bootServer(args);
163
+ const prettyPath = concolor.dim(path.relative(process.cwd(), f));
164
+ logger.info(`${concolor.green('server reload')} ${prettyPath}`);
165
+ }, 100);
115
166
 
167
+ watcher.on('change', reload);
168
+ watcher.on('add', reload);
169
+ watcher.on('unlink', reload);
170
+ }
116
171
 
117
- export default start
172
+ export default startDevServer
@@ -55,6 +55,7 @@ const viteSetup = async (app) => {
55
55
  next(e);
56
56
  }
57
57
  });
58
+ return vite;
58
59
  }
59
60
 
60
61
 
@@ -1,45 +0,0 @@
1
- import express from 'express';
2
- import path from 'path'
3
- import fs from 'fs'
4
- import viteSetup from './vite.js';
5
- const port = process.env.PORT || 3000;
6
- const app = express();
7
- const server = async (cb) => {
8
-
9
- // get type from package.json
10
- const pkg = path.join(process.cwd(), 'package.json');
11
- let type = 'module';
12
- if (fs.existsSync(pkg)) {
13
- const pkgjson = JSON.parse(fs.readFileSync(pkg, 'utf-8'));
14
- type = pkgjson.type || 'module';
15
- }
16
-
17
- if (cb) {
18
- cb(app)
19
- }
20
-
21
- // const mpack = path.join(process.cwd(), '.mpack');
22
- // const uxp = path.join(mpack, 'uxp.js')
23
- // if (fs.existsSync(uxp)) {
24
- // // load user-express.js based on type
25
- // if (type === 'module') {
26
- // const { default: userExpress } = await import(uxp);
27
- // userExpress(app);
28
- // } else {
29
- // const userExpress = require(uxp).default;
30
- // userExpress(app);
31
- // }
32
- // }
33
-
34
-
35
- await viteSetup(app)
36
- app.use((_req, res) => {
37
- res.status(500).send('Internal Server Error');
38
- });
39
-
40
- app.listen(port, () => {
41
- console.log(`Server is running on: http://localhost:${port}`);
42
- });
43
- }
44
-
45
- export default server;