nexfpack 0.1.0 → 0.1.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/index.d.cts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/index.d.mts ADDED
@@ -0,0 +1,17 @@
1
+ interface NexfpackOptions {
2
+ name?: string;
3
+ root?: string;
4
+ relativeRoot?: boolean;
5
+ entry?: string;
6
+ output?: string;
7
+ tempdir?: string;
8
+ autoDeleteTempFiles?: boolean;
9
+ ignorefile?: string;
10
+ ignore?: string[];
11
+ enabledSign?: boolean;
12
+ autoRun?: boolean;
13
+ configFile?: string;
14
+ }
15
+ declare function nexfpack(options: NexfpackOptions): Promise<void>;
16
+ export default nexfpack;
17
+ export { NexfpackOptions, nexfpack };
@@ -1,99 +1,74 @@
1
- import copyfiles from 'copyfiles'
2
- import fs from 'fs'
3
- import path from 'path'
4
- import os from 'os'
5
- import child_process from 'child_process'
6
- import { pipeline } from 'stream/promises'
7
- import { packTar } from 'modern-tar/fs'
8
- // @ts-ignore
9
- import { inject } from 'postject';
10
- interface NexfpackOptions {
11
- name?: string,
12
- root?: string,
13
- relativeRoot?: boolean,
14
- entry?: string,
15
- output?: string,
16
- tempdir?: string,
17
- autoDeleteTempFiles?: boolean,
18
- ignorefile?: string,
19
- ignore?: string[],
20
- enabledSign?: boolean,
21
- autoRun?: boolean,
22
- configFile?: string,
23
- }
24
-
25
- interface NexfpackOptionsFilled {
26
- name: string,
27
- root: string,
28
- entry: string,
29
- output: string,
30
- tempdir: string,
31
- autoDeleteTempFiles: boolean,
32
- ignore: string[],
33
- enabledSign: boolean,
34
- autoRun: boolean,
35
- }
36
-
37
- async function fillOptions(options: NexfpackOptions): Promise<NexfpackOptionsFilled> {
38
- let cwd: string;
39
- if (options.root && !options.relativeRoot) {
40
- cwd = options.root;
41
- } else if (options.configFile) {
42
- cwd = path.dirname(options.configFile);
43
- } else {
44
- cwd = process.cwd();
45
- }
46
- if (options.root && options.relativeRoot) {
47
- cwd = path.resolve(cwd, options.root);
48
- }
49
- function getIgnores() {
50
- if (options.ignorefile) {
51
- return fs.readFileSync(path.resolve(cwd, options.ignorefile), 'utf8').split('\n').map(line => {
52
- return line.split('#')[0].trim();
53
- }).filter(line => line !== '');
54
- } else if (options.ignore) {
55
- return options.ignore;
56
- } else if (fs.existsSync(path.resolve(cwd, '.nexfpackignore'))) {
57
- return fs.readFileSync(path.resolve(cwd, '.nexfpackignore'), 'utf8').split('\n').map(line => {
58
- return line.split('#')[0].trim();
59
- }).filter(line => line !== '');
60
- } else {
61
- return [];
62
- }
63
- }
64
- return {
65
- name: options.name ?? 'nexfpack-app',
66
- root: cwd,
67
- entry: path.resolve(cwd, options.entry ?? 'index.js'),
68
- output: path.resolve(cwd, options.output ?? 'dist'),
69
- tempdir: path.resolve(cwd, options.tempdir ?? '.nexfpack-temp'),
70
- autoDeleteTempFiles: options.autoDeleteTempFiles ?? true,
71
- ignore: getIgnores(),
72
- enabledSign: options.enabledSign ?? false,
73
- autoRun: options.autoRun ?? false,
74
- }
75
- }
76
-
77
- function listAllFiles(dir: string): string[] {
78
- const result: string[] = [];
79
- const entries = fs.readdirSync(dir);
80
-
81
- for (const entry of entries) {
82
- const fullPath = path.join(dir, entry);
83
- const stat = fs.statSync(fullPath);
84
- if (stat.isDirectory()) {
85
- result.push(...listAllFiles(fullPath));
86
- } else {
87
- result.push(fullPath);
88
- }
89
- }
90
- return result;
91
- }
92
-
93
- async function nexfpack(options: NexfpackOptions) {
94
- try {
95
- console.log(
96
- `
1
+ import copyfiles from 'copyfiles';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import child_process from 'child_process';
6
+ import { pipeline } from 'stream/promises';
7
+ import { packTar } from 'modern-tar/fs';
8
+ // @ts-ignore
9
+ import { inject } from 'postject';
10
+ async function fillOptions(options) {
11
+ let cwd;
12
+ if (options.root && !options.relativeRoot) {
13
+ cwd = options.root;
14
+ }
15
+ else if (options.configFile) {
16
+ cwd = path.dirname(options.configFile);
17
+ }
18
+ else {
19
+ cwd = process.cwd();
20
+ }
21
+ if (options.root && options.relativeRoot) {
22
+ cwd = path.resolve(cwd, options.root);
23
+ }
24
+ function getIgnores() {
25
+ if (options.ignorefile) {
26
+ return fs.readFileSync(path.resolve(cwd, options.ignorefile), 'utf8').split('\n').map(line => {
27
+ return line.split('#')[0].trim();
28
+ }).filter(line => line !== '');
29
+ }
30
+ else if (options.ignore) {
31
+ return options.ignore;
32
+ }
33
+ else if (fs.existsSync(path.resolve(cwd, '.nexfpackignore'))) {
34
+ return fs.readFileSync(path.resolve(cwd, '.nexfpackignore'), 'utf8').split('\n').map(line => {
35
+ return line.split('#')[0].trim();
36
+ }).filter(line => line !== '');
37
+ }
38
+ else {
39
+ return [];
40
+ }
41
+ }
42
+ return {
43
+ name: options.name ?? 'nexfpack-app',
44
+ root: cwd,
45
+ entry: path.resolve(cwd, options.entry ?? 'index.js'),
46
+ output: path.resolve(cwd, options.output ?? 'dist'),
47
+ tempdir: path.resolve(cwd, options.tempdir ?? '.nexfpack-temp'),
48
+ autoDeleteTempFiles: options.autoDeleteTempFiles ?? true,
49
+ ignore: getIgnores(),
50
+ enabledSign: options.enabledSign ?? false,
51
+ autoRun: options.autoRun ?? false,
52
+ };
53
+ }
54
+ function listAllFiles(dir) {
55
+ const result = [];
56
+ const entries = fs.readdirSync(dir);
57
+ for (const entry of entries) {
58
+ const fullPath = path.join(dir, entry);
59
+ const stat = fs.statSync(fullPath);
60
+ if (stat.isDirectory()) {
61
+ result.push(...listAllFiles(fullPath));
62
+ }
63
+ else {
64
+ result.push(fullPath);
65
+ }
66
+ }
67
+ return result;
68
+ }
69
+ async function nexfpack(options) {
70
+ try {
71
+ console.log(`
97
72
  __ _ __ _
98
73
  / \\ / /\\_____\\ \\ / /
99
74
  / /\\ \\ / / / ____/\\ \\/ /
@@ -110,77 +85,71 @@ async function nexfpack(options: NexfpackOptions) {
110
85
  | | / ____ \\ | |___ | |\\ \\
111
86
  |_| /_/ \\_\\ |_____| |_| \\_\\
112
87
 
113
- `)
114
- console.log('▶️ Start packing...');
115
- console.log('🧪 Tips: Nexfpack is very experimental. It may have some errors.')
116
- let config: NexfpackOptions;
117
- if (options.configFile) {
118
- config = JSON.parse(fs.readFileSync(options.configFile, 'utf8')) as NexfpackOptions;
119
- } else {
120
- config = options;
121
- }
122
- const filledConfig = await fillOptions(config);
123
-
124
- if (!fs.existsSync(filledConfig.tempdir)) {
125
- fs.mkdirSync(filledConfig.tempdir, { recursive: true });
126
- } else {
127
- fs.rmSync(filledConfig.tempdir, { recursive: true, force: true });
128
- fs.mkdirSync(filledConfig.tempdir, { recursive: true });
129
- }
130
-
131
- console.log('📄 Copying files...');
132
-
133
- if (!fs.existsSync(path.join(filledConfig.tempdir, 'source-copy'))) {
134
- fs.mkdirSync(path.join(filledConfig.tempdir, 'source-copy'), { recursive: true });
135
- }
136
-
137
- await new Promise<void>((resolve, reject) => {
138
- copyfiles([filledConfig.root, path.join(filledConfig.tempdir, 'source-copy')], { up: 1, exclude: filledConfig.ignore }, (err) => {
139
- if (err) {
140
- console.error('❌ Failed to copy files:', err);
141
- reject(err);
142
- } else {
143
- resolve();
144
- }
145
- })
146
- })
147
-
148
- console.log('📜 Packing source...');
149
-
150
- const tarStream = packTar(path.join(filledConfig.tempdir, 'source-copy'));
151
- const writeStream = fs.createWriteStream(path.join(filledConfig.tempdir, 'source.tar'));
152
- await pipeline(tarStream, writeStream);
153
-
154
- console.log('📦 Packing executable...');
155
- fs.writeFileSync(path.join(filledConfig.tempdir, 'package.json'), JSON.stringify({
156
- name: filledConfig.name,
157
- version: '1.0.0',
158
- type: 'commonjs',
159
- main: 'launcher.cjs',
160
- dependencies: {
161
- "modern-tar": "^0.7.6"
162
- }
163
- }, null, 2));
164
- const installSpawnResult = child_process.spawnSync('npm install --omit=dev', { stdio: 'inherit', cwd: filledConfig.tempdir, shell: true });
165
- if (installSpawnResult.status !== 0) {
166
- throw new Error('❌ Failed to install dependencies');
167
- }
168
-
169
- const allNodeModulesFiles = listAllFiles(path.join(filledConfig.tempdir, 'node_modules'));
170
- const seaConfigContent: any =
171
- {
172
- "main": "./launcher.cjs",
173
- "output": "./sea-prep.blob",
174
- "disableExperimentalSEAWarning": true,
175
- "assets": {
176
- "source.tar": "./source.tar",
177
- }
178
- };
179
- for (const file of allNodeModulesFiles) {
180
- const relativePath = path.relative(path.join(filledConfig.tempdir, 'node_modules'), file);
181
- seaConfigContent.assets[`node_modules/${relativePath}`] = file;
182
- }
183
- fs.writeFileSync(path.join(filledConfig.tempdir, 'sea-config.json'), JSON.stringify(seaConfigContent));
88
+ `);
89
+ console.log('▶️ Start packing...');
90
+ console.log('🧪 Tips: Nexfpack is very experimental. It may have some errors.');
91
+ let config;
92
+ if (options.configFile) {
93
+ config = JSON.parse(fs.readFileSync(options.configFile, 'utf8'));
94
+ }
95
+ else {
96
+ config = options;
97
+ }
98
+ const filledConfig = await fillOptions(config);
99
+ if (!fs.existsSync(filledConfig.tempdir)) {
100
+ fs.mkdirSync(filledConfig.tempdir, { recursive: true });
101
+ }
102
+ else {
103
+ fs.rmSync(filledConfig.tempdir, { recursive: true, force: true });
104
+ fs.mkdirSync(filledConfig.tempdir, { recursive: true });
105
+ }
106
+ console.log('📄 Copying files...');
107
+ if (!fs.existsSync(path.join(filledConfig.tempdir, 'source-copy'))) {
108
+ fs.mkdirSync(path.join(filledConfig.tempdir, 'source-copy'), { recursive: true });
109
+ }
110
+ await new Promise((resolve, reject) => {
111
+ copyfiles([filledConfig.root, path.join(filledConfig.tempdir, 'source-copy')], { up: 1, exclude: filledConfig.ignore }, (err) => {
112
+ if (err) {
113
+ console.error(' Failed to copy files:', err);
114
+ reject(err);
115
+ }
116
+ else {
117
+ resolve();
118
+ }
119
+ });
120
+ });
121
+ console.log('📜 Packing source...');
122
+ const tarStream = packTar(path.join(filledConfig.tempdir, 'source-copy'));
123
+ const writeStream = fs.createWriteStream(path.join(filledConfig.tempdir, 'source.tar'));
124
+ await pipeline(tarStream, writeStream);
125
+ console.log('📦 Packing executable...');
126
+ fs.writeFileSync(path.join(filledConfig.tempdir, 'package.json'), JSON.stringify({
127
+ name: filledConfig.name,
128
+ version: '1.0.0',
129
+ type: 'commonjs',
130
+ main: 'launcher.cjs',
131
+ dependencies: {
132
+ "modern-tar": "^0.7.6"
133
+ }
134
+ }, null, 2));
135
+ const installSpawnResult = child_process.spawnSync('npm install --omit=dev', { stdio: 'inherit', cwd: filledConfig.tempdir, shell: true });
136
+ if (installSpawnResult.status !== 0) {
137
+ throw new Error('❌ Failed to install dependencies');
138
+ }
139
+ const allNodeModulesFiles = listAllFiles(path.join(filledConfig.tempdir, 'node_modules'));
140
+ const seaConfigContent = {
141
+ "main": "./launcher.cjs",
142
+ "output": "./sea-prep.blob",
143
+ "disableExperimentalSEAWarning": true,
144
+ "assets": {
145
+ "source.tar": "./source.tar",
146
+ }
147
+ };
148
+ for (const file of allNodeModulesFiles) {
149
+ const relativePath = path.relative(path.join(filledConfig.tempdir, 'node_modules'), file);
150
+ seaConfigContent.assets[`node_modules/${relativePath}`] = file;
151
+ }
152
+ fs.writeFileSync(path.join(filledConfig.tempdir, 'sea-config.json'), JSON.stringify(seaConfigContent));
184
153
  const launcherContent = `
185
154
  (async () => {
186
155
  const fs = require('fs');
@@ -236,43 +205,43 @@ async function nexfpack(options: NexfpackOptions) {
236
205
  }
237
206
  fs.rmSync(tempDir, { recursive: true, force: true });
238
207
  })();
239
- `;
240
- fs.writeFileSync(path.join(filledConfig.tempdir, 'launcher.cjs'), launcherContent);
241
- const blobSpawnResult = child_process.spawnSync('node --experimental-sea-config sea-config.json', { stdio: 'inherit', cwd: filledConfig.tempdir, shell: true });
242
- if (blobSpawnResult.status !== 0) {
243
- throw new Error('❌ Failed to generate blob');
244
- }
245
- const NODE_SEA_FUSE = 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2';
246
- const blobData = fs.readFileSync(path.join(filledConfig.tempdir, 'sea-prep.blob'));
247
- const injectOptions: any = {
248
- sentinelFuse: NODE_SEA_FUSE,
249
- };
250
- if (os.platform() === 'darwin') {
251
- injectOptions.machoSegmentName = 'NODE_SEA';
252
- }
253
- const ext = os.platform() === 'win32' ? '.exe' : '';
254
- const exePath = path.join(filledConfig.output, filledConfig.name + ext);
255
- if (!fs.existsSync(filledConfig.output)) {
256
- fs.mkdirSync(filledConfig.output, { recursive: true });
257
- }
258
- fs.copyFileSync(process.execPath, exePath);
259
- await inject(exePath, 'NODE_SEA_BLOB', blobData, injectOptions);
260
- if (filledConfig.enabledSign) {
261
- console.log("⚠️ Sorry, we can't sign your executable file. Please sign it by yourself.");
262
- }
263
- if (filledConfig.autoDeleteTempFiles) {
264
- console.log('♻️ Deleting temp files...');
265
- fs.rmSync(filledConfig.tempdir, { recursive: true, force: true });
266
- }
267
- console.log('✅ Done!');
268
- if (filledConfig.autoRun) {
269
- console.log('🚀 Auto-run executable...');
270
- child_process.spawnSync(exePath, { stdio: 'inherit', cwd: filledConfig.output, shell: true });
271
- }
272
- } catch (err) {
273
- console.error('❌ Nexfpack Failed:', err);
274
- }
275
- }
276
-
277
- export default nexfpack
278
- export { NexfpackOptions, nexfpack }
208
+ `;
209
+ fs.writeFileSync(path.join(filledConfig.tempdir, 'launcher.cjs'), launcherContent);
210
+ const blobSpawnResult = child_process.spawnSync('node --experimental-sea-config sea-config.json', { stdio: 'inherit', cwd: filledConfig.tempdir, shell: true });
211
+ if (blobSpawnResult.status !== 0) {
212
+ throw new Error('❌ Failed to generate blob');
213
+ }
214
+ const NODE_SEA_FUSE = 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2';
215
+ const blobData = fs.readFileSync(path.join(filledConfig.tempdir, 'sea-prep.blob'));
216
+ const injectOptions = {
217
+ sentinelFuse: NODE_SEA_FUSE,
218
+ };
219
+ if (os.platform() === 'darwin') {
220
+ injectOptions.machoSegmentName = 'NODE_SEA';
221
+ }
222
+ const ext = os.platform() === 'win32' ? '.exe' : '';
223
+ const exePath = path.join(filledConfig.output, filledConfig.name + ext);
224
+ if (!fs.existsSync(filledConfig.output)) {
225
+ fs.mkdirSync(filledConfig.output, { recursive: true });
226
+ }
227
+ fs.copyFileSync(process.execPath, exePath);
228
+ await inject(exePath, 'NODE_SEA_BLOB', blobData, injectOptions);
229
+ if (filledConfig.enabledSign) {
230
+ console.log("⚠️ Sorry, we can't sign your executable file. Please sign it by yourself.");
231
+ }
232
+ if (filledConfig.autoDeleteTempFiles) {
233
+ console.log('♻️ Deleting temp files...');
234
+ fs.rmSync(filledConfig.tempdir, { recursive: true, force: true });
235
+ }
236
+ console.log('✅ Done!');
237
+ if (filledConfig.autoRun) {
238
+ console.log('🚀 Auto-run executable...');
239
+ child_process.spawnSync(exePath, { stdio: 'inherit', cwd: filledConfig.output, shell: true });
240
+ }
241
+ }
242
+ catch (err) {
243
+ console.error('❌ Nexfpack Failed:', err);
244
+ }
245
+ }
246
+ export default nexfpack;
247
+ export { nexfpack };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexfpack",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "A tool for building single executable files from Node.js scripts or modules.",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/nexfteam/Nexfpack",
@@ -21,6 +21,16 @@
21
21
  "bin": {
22
22
  "nexfpack": "cli.mjs"
23
23
  },
24
+ "files": [
25
+ "index.cjs",
26
+ "index.mjs",
27
+ "cli.mjs",
28
+ "README.md",
29
+ "README-CN.md",
30
+ "LICENSE",
31
+ "index.d.mts",
32
+ "index.d.cts"
33
+ ],
24
34
  "scripts": {
25
35
  "compile": "tsc"
26
36
  },
package/index.cts DELETED
@@ -1,3 +0,0 @@
1
- (async() => {
2
- module.exports = await import("./index.mjs");
3
- })();
package/tsconfig.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "types": ["node"],
7
- "lib": ["ES2022", "ESNext"],
8
- "outDir": "./",
9
- "rootDir": "./",
10
- "strict": true,
11
- "esModuleInterop": true,
12
- "skipLibCheck": true,
13
- "declaration": true,
14
- "declarationMap": false,
15
- "sourceMap": false
16
- },
17
- "include": ["**/*.mts", "**/*.cts", "**/*.ts"],
18
- "exclude": ["node_modules", "test", "**/*.d.ts", "**/*.d.mts", "**/*.d.cts", "**/test.*"]
19
- }