novac 2.2.0 → 2.2.2

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.
Files changed (122) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +0 -0
  3. package/bin/novac +6 -3
  4. package/bin/nvc +0 -0
  5. package/bin/nvml +0 -0
  6. package/demo.nv +0 -0
  7. package/demo_builtins.nv +0 -0
  8. package/demo_http.nv +0 -0
  9. package/examples/bf.nv +5 -13
  10. package/examples/math.nv +2 -2
  11. package/kits/kitffmpeg/kitdef.js +1174 -0
  12. package/kits/libos/kitdef.js +3135 -0
  13. package/kits/libtasker/kitdef.js +125 -0
  14. package/package.json +1 -1
  15. package/scripts/update-bin.js +0 -0
  16. package/src/core/executor.js +7 -4
  17. package/src/core/lexer.js +2 -2
  18. package/src/index.js +0 -0
  19. package/novac/LICENSE +0 -21
  20. package/novac/README.md +0 -1823
  21. package/novac/bin/novac +0 -950
  22. package/novac/bin/nvc +0 -522
  23. package/novac/bin/nvml +0 -542
  24. package/novac/demo.nv +0 -245
  25. package/novac/demo_builtins.nv +0 -209
  26. package/novac/demo_http.nv +0 -62
  27. package/novac/examples/bf.nv +0 -69
  28. package/novac/examples/math.nv +0 -21
  29. package/novac/kits/kitai/kitdef.js +0 -2185
  30. package/novac/kits/kitansi/kitdef.js +0 -1402
  31. package/novac/kits/kitformat/kitdef.js +0 -1485
  32. package/novac/kits/kitgps/kitdef.js +0 -1862
  33. package/novac/kits/kitlibfs/kitdef.js +0 -231
  34. package/novac/kits/kitlibproc/kitdef.js +0 -78
  35. package/novac/kits/kitmatrix/ex.js +0 -19
  36. package/novac/kits/kitmatrix/kitdef.js +0 -960
  37. package/novac/kits/kitmpatch/kitdef.js +0 -906
  38. package/novac/kits/kitnovacweb/README.md +0 -1572
  39. package/novac/kits/kitnovacweb/demo.nv +0 -12
  40. package/novac/kits/kitnovacweb/demo.nvml +0 -71
  41. package/novac/kits/kitnovacweb/index.nova +0 -12
  42. package/novac/kits/kitnovacweb/kitdef.js +0 -692
  43. package/novac/kits/kitnovacweb/nova.kit.json +0 -8
  44. package/novac/kits/kitnovacweb/nvml/executor.js +0 -739
  45. package/novac/kits/kitnovacweb/nvml/index.js +0 -67
  46. package/novac/kits/kitnovacweb/nvml/lexer.js +0 -263
  47. package/novac/kits/kitnovacweb/nvml/parser.js +0 -508
  48. package/novac/kits/kitnovacweb/nvml/renderer.js +0 -924
  49. package/novac/kits/kitparse/kitdef.js +0 -1688
  50. package/novac/kits/kitregex++/kitdef.js +0 -1353
  51. package/novac/kits/kitrequire/kitdef.js +0 -1599
  52. package/novac/kits/kitx11/kitdef.js +0 -1
  53. package/novac/kits/kitx11/kitx11.js +0 -2472
  54. package/novac/kits/kitx11/kitx11_conn.js +0 -948
  55. package/novac/kits/kitx11/kitx11_worker.js +0 -121
  56. package/novac/kits/libtea/tf.js +0 -2691
  57. package/novac/kits/libterm/ex.js +0 -285
  58. package/novac/kits/libterm/kitdef.js +0 -1927
  59. package/novac/node_modules/chalk/license +0 -9
  60. package/novac/node_modules/chalk/package.json +0 -83
  61. package/novac/node_modules/chalk/readme.md +0 -297
  62. package/novac/node_modules/chalk/source/index.d.ts +0 -325
  63. package/novac/node_modules/chalk/source/index.js +0 -225
  64. package/novac/node_modules/chalk/source/utilities.js +0 -33
  65. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +0 -236
  66. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.js +0 -223
  67. package/novac/node_modules/chalk/source/vendor/supports-color/browser.d.ts +0 -1
  68. package/novac/node_modules/chalk/source/vendor/supports-color/browser.js +0 -34
  69. package/novac/node_modules/chalk/source/vendor/supports-color/index.d.ts +0 -55
  70. package/novac/node_modules/chalk/source/vendor/supports-color/index.js +0 -190
  71. package/novac/node_modules/commander/LICENSE +0 -22
  72. package/novac/node_modules/commander/Readme.md +0 -1176
  73. package/novac/node_modules/commander/esm.mjs +0 -16
  74. package/novac/node_modules/commander/index.js +0 -24
  75. package/novac/node_modules/commander/lib/argument.js +0 -150
  76. package/novac/node_modules/commander/lib/command.js +0 -2777
  77. package/novac/node_modules/commander/lib/error.js +0 -39
  78. package/novac/node_modules/commander/lib/help.js +0 -747
  79. package/novac/node_modules/commander/lib/option.js +0 -380
  80. package/novac/node_modules/commander/lib/suggestSimilar.js +0 -101
  81. package/novac/node_modules/commander/package-support.json +0 -19
  82. package/novac/node_modules/commander/package.json +0 -82
  83. package/novac/node_modules/commander/typings/esm.d.mts +0 -3
  84. package/novac/node_modules/commander/typings/index.d.ts +0 -1113
  85. package/novac/node_modules/node-addon-api/LICENSE.md +0 -9
  86. package/novac/node_modules/node-addon-api/README.md +0 -95
  87. package/novac/node_modules/node-addon-api/common.gypi +0 -21
  88. package/novac/node_modules/node-addon-api/except.gypi +0 -25
  89. package/novac/node_modules/node-addon-api/index.js +0 -14
  90. package/novac/node_modules/node-addon-api/napi-inl.deprecated.h +0 -186
  91. package/novac/node_modules/node-addon-api/napi-inl.h +0 -7165
  92. package/novac/node_modules/node-addon-api/napi.h +0 -3364
  93. package/novac/node_modules/node-addon-api/node_addon_api.gyp +0 -42
  94. package/novac/node_modules/node-addon-api/node_api.gyp +0 -9
  95. package/novac/node_modules/node-addon-api/noexcept.gypi +0 -26
  96. package/novac/node_modules/node-addon-api/nothing.c +0 -0
  97. package/novac/node_modules/node-addon-api/package-support.json +0 -21
  98. package/novac/node_modules/node-addon-api/package.json +0 -480
  99. package/novac/node_modules/node-addon-api/tools/README.md +0 -73
  100. package/novac/node_modules/node-addon-api/tools/check-napi.js +0 -99
  101. package/novac/node_modules/node-addon-api/tools/clang-format.js +0 -71
  102. package/novac/node_modules/node-addon-api/tools/conversion.js +0 -301
  103. package/novac/node_modules/serialize-javascript/LICENSE +0 -27
  104. package/novac/node_modules/serialize-javascript/README.md +0 -149
  105. package/novac/node_modules/serialize-javascript/index.js +0 -297
  106. package/novac/node_modules/serialize-javascript/package.json +0 -33
  107. package/novac/package.json +0 -27
  108. package/novac/scripts/update-bin.js +0 -24
  109. package/novac/src/core/bstd.js +0 -1035
  110. package/novac/src/core/config.js +0 -155
  111. package/novac/src/core/describe.js +0 -187
  112. package/novac/src/core/emitter.js +0 -499
  113. package/novac/src/core/error.js +0 -86
  114. package/novac/src/core/executor.js +0 -5606
  115. package/novac/src/core/formatter.js +0 -686
  116. package/novac/src/core/lexer.js +0 -1026
  117. package/novac/src/core/nova_builtins.js +0 -717
  118. package/novac/src/core/nova_thread_worker.js +0 -166
  119. package/novac/src/core/parser.js +0 -2181
  120. package/novac/src/core/types.js +0 -112
  121. package/novac/src/index.js +0 -28
  122. package/novac/src/runtime/stdlib.js +0 -244
package/novac/bin/nvc DELETED
@@ -1,522 +0,0 @@
1
- #!/usr/bin/env node
2
- // nvc — novac global binary: native addon kit generator
3
- //
4
- // Usage:
5
- // nvc natives --name myaddon --sources win32:src/addon_win.cpp linux-x64:src/addon_lnx.cpp darwin:src/addon_mac.cpp
6
- //
7
- // Output:
8
- // nkitmyaddon/
9
- // bins/ ← compiled .node binaries per platform/arch
10
- // src/ ← copied source files
11
- // CMakeLists.txt ← auto-generated (no binding.gyp — node-gyp is never used)
12
- // kitdef.js ← runtime loader (sniffs platform+arch)
13
- // unsupported.cpp ← auto-generated stub for missing targets
14
- // build.js ← the build orchestrator (cmake-js → cmake → manual gcc/clang)
15
-
16
- 'use strict';
17
-
18
- const fs = require('fs');
19
- const path = require('path');
20
- const os = require('os');
21
- const { execSync, spawnSync } = require('child_process');
22
-
23
- // ─── CONSTANTS ────────────────────────────────────────────────────────────────
24
-
25
- const SUPPORTED_PLATFORMS = ['win32', 'linux', 'darwin', 'android', 'freebsd', 'openbsd'];
26
- const SUPPORTED_ARCHS = ['x64', 'x86', 'arm64', 'arm', 'ia32', 'riscv64', 'mips'];
27
-
28
- // Node-API version to target (stable across Node 12+)
29
- const NAPI_VERSION = 6;
30
-
31
- // ─── HELPERS ─────────────────────────────────────────────────────────────────
32
-
33
- function run(cmd, cwd, silent = false) {
34
- const result = spawnSync(cmd, { shell: true, cwd, stdio: silent ? 'pipe' : 'inherit' });
35
- return result.status === 0;
36
- }
37
-
38
- function has(cmd) {
39
- const r = spawnSync(cmd, ['--version'], { shell: true, stdio: 'pipe' });
40
- return r.status === 0;
41
- }
42
-
43
- function mkdir(p) {
44
- fs.mkdirSync(p, { recursive: true });
45
- }
46
-
47
- function write(p, content) {
48
- fs.writeFileSync(p, content, 'utf8');
49
- }
50
-
51
- function copy(src, dest) {
52
- fs.copyFileSync(src, dest);
53
- }
54
-
55
- // Parse "platform-arch:path" or "platform:path" source specs
56
- // e.g. "linux-x64:src/addon.cpp" "win32:src/win.cpp" "darwin-arm64:src/mac.cpp"
57
- function parseSourceSpec(spec) {
58
- const colon = spec.indexOf(':');
59
- if (colon === -1) throw new Error(`Invalid source spec (missing ':'): ${spec}`);
60
- const tag = spec.slice(0, colon).trim();
61
- const file = spec.slice(colon + 1).trim();
62
- const dash = tag.indexOf('-');
63
- let platform, arch;
64
- if (dash === -1) {
65
- platform = tag;
66
- arch = '*'; // any arch for this platform
67
- } else {
68
- platform = tag.slice(0, dash);
69
- arch = tag.slice(dash + 1);
70
- }
71
- return { platform, arch, file };
72
- }
73
-
74
- // Canonical binary name: addon-linux-x64.node
75
- function binName(kitName, platform, arch) {
76
- return `${kitName}-${platform}-${arch}.node`;
77
- }
78
-
79
- // ─── CODE GENERATORS ─────────────────────────────────────────────────────────
80
-
81
- function genCMakeLists(kitName, srcFile, napiVersion) {
82
- // Resolve paths at generation time — avoids CMake execute_process quoting bugs on all platforms
83
- const { execSync: _exec } = require('child_process');
84
- let nodeInclude = '';
85
- let napiInclude = '';
86
- let nodeBinDir = '';
87
-
88
- try {
89
- const _p = require('path');
90
- nodeInclude = _p.join(_p.dirname(process.execPath), '..', 'include', 'node');
91
- } catch(_) {}
92
- // napi include: always use the local node_modules path — node-addon-api isn't
93
- // installed globally, it gets installed by npm install inside the kit folder.
94
- // CMakeLists.txt is generated before that happens, so we hardcode the relative path.
95
- napiInclude = '${CMAKE_SOURCE_DIR}/node_modules/node-addon-api';
96
- try {
97
- nodeBinDir = require('path').dirname(process.execPath);
98
- } catch(_) {}
99
-
100
- return `cmake_minimum_required(VERSION 3.15)
101
- project(${kitName})
102
-
103
- set(CMAKE_CXX_STANDARD 17)
104
-
105
- # Paths baked in at kit-generation time by nvc (no runtime execute_process needed)
106
- set(NODE_INCLUDE_DIR "${nodeInclude}")
107
- set(NAPI_INCLUDE "${napiInclude}")
108
- set(NODE_BIN_DIR "${nodeBinDir}")
109
-
110
- add_library(\${PROJECT_NAME} SHARED ${srcFile})
111
- set_target_properties(\${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
112
-
113
- target_include_directories(\${PROJECT_NAME} PRIVATE
114
- \${NODE_INCLUDE_DIR}
115
- \${NAPI_INCLUDE}
116
- )
117
-
118
- target_compile_definitions(\${PROJECT_NAME} PRIVATE
119
- NAPI_VERSION=${napiVersion}
120
- NAPI_DISABLE_CPP_EXCEPTIONS
121
- )
122
-
123
- if(WIN32)
124
- target_link_libraries(\${PROJECT_NAME} "\${NODE_BIN_DIR}/node.lib")
125
- elseif(APPLE)
126
- set_target_properties(\${PROJECT_NAME} PROPERTIES
127
- LINK_FLAGS "-undefined dynamic_lookup"
128
- )
129
- endif()
130
- `;
131
- }
132
-
133
-
134
- function genUnsupportedStub(kitName) {
135
- return `// Auto-generated unsupported-arch stub for ${kitName}
136
- #include <node_api.h>
137
- #include <stdio.h>
138
-
139
- napi_value Init(napi_env env, napi_value exports) {
140
- const char* arch =
141
- #if defined(__x86_64__) || defined(_M_X64)
142
- "x64";
143
- #elif defined(__i386__) || defined(_M_IX86)
144
- "x86";
145
- #elif defined(__aarch64__) || defined(_M_ARM64)
146
- "arm64";
147
- #elif defined(__arm__) || defined(_M_ARM)
148
- "arm";
149
- #elif defined(__riscv) && __riscv_xlen == 64
150
- "riscv64";
151
- #else
152
- "unknown";
153
- #endif
154
-
155
- const char* plat =
156
- #if defined(_WIN32)
157
- "win32";
158
- #elif defined(__APPLE__)
159
- "darwin";
160
- #elif defined(__ANDROID__)
161
- "android";
162
- #elif defined(__linux__)
163
- "linux";
164
- #elif defined(__FreeBSD__)
165
- "freebsd";
166
- #else
167
- "unknown";
168
- #endif
169
-
170
- fprintf(stderr, "\\n[${kitName}] This native addon does not support your platform: %s-%s\\n", plat, arch);
171
- fprintf(stderr, " Please check https://your-project/nkit${kitName} for supported targets.\\n\\n");
172
-
173
- napi_throw_error(env, "UNSUPPORTED_PLATFORM",
174
- "This native addon does not support your current platform/architecture.");
175
- return exports;
176
- }
177
-
178
- NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
179
- `;
180
- }
181
-
182
- function genKitdef(kitName, sources) {
183
- const entries = sources.map(s => {
184
- const archClause = s.arch === '*'
185
- ? `platform === '${s.platform}'`
186
- : `platform === '${s.platform}' && arch === '${s.arch}'`;
187
- return ` if (${archClause}) return require('./bins/${binName(kitName, s.platform, s.arch === '*' ? 'universal' : s.arch)}');`;
188
- });
189
-
190
- return `// kitdef.js — auto-generated by kitnatives for ${kitName}
191
- // Do not edit manually; re-run kitnatives to regenerate.
192
-
193
- 'use strict';
194
-
195
- const path = require('path');
196
- const platform = process.platform;
197
- const arch = process.arch;
198
-
199
- function loadAddon() {
200
- ${entries.join('\n')}
201
-
202
- // Fallback: unsupported platform/arch
203
- try {
204
- return require('./bins/${kitName}-unsupported.node');
205
- } catch (_) {
206
- throw new Error(
207
- \`[${kitName}] Unsupported platform: \${platform}-\${arch}. \` +
208
- \`No native binary available for this target.\`
209
- );
210
- }
211
- }
212
-
213
- const addon = loadAddon();
214
-
215
- module.exports = {
216
- kitdef: addon
217
- };
218
- `;
219
- }
220
-
221
- function genBuildScript(kitName, sources, outDir) {
222
- const builds = sources.map((s, i) => {
223
- const bname = binName(kitName, s.platform, s.arch === '*' ? 'universal' : s.arch);
224
- const srcRel = path.basename(s.file);
225
- return `
226
- // ── Build ${i + 1}: ${s.platform}-${s.arch} ──────────────────────────────────
227
- {
228
- const srcFile = path.join(__dirname, 'src', '${srcRel}');
229
- const outBin = path.join(__dirname, 'bins', '${bname}');
230
- const cmake = path.join(__dirname, 'cmake_build_${i}');
231
-
232
- console.log('[kitnatives] Building ${s.platform}-${s.arch}...');
233
-
234
- if (fs.existsSync(outBin)) {
235
- console.log(' → Already built, skipping.');
236
- } else {
237
- let built = false;
238
-
239
- // Strategy 1: cmake-js (explicitly told to use CMake, never gyp)
240
- if (!built && hasTool('cmake-js')) {
241
- console.log(' → Trying cmake-js...');
242
- fs.mkdirSync(cmake, { recursive: true });
243
- // Pass --cmake-options to avoid any gyp fallback; point at our CMakeLists.txt
244
- const r = run(
245
- \`cmake-js compile --runtime node --cmake-options="-DCMAKE_BUILD_TYPE=Release" --directory "\${__dirname}" --out "\${cmake}"\`,
246
- __dirname
247
- );
248
- if (r) {
249
- const nodeFile = findNodeFile(cmake);
250
- if (nodeFile) { fs.copyFileSync(nodeFile, outBin); built = true; }
251
- }
252
- }
253
-
254
- // Strategy 2: cmake manually
255
- if (!built && hasTool('cmake')) {
256
- console.log(' → Trying cmake...');
257
- fs.mkdirSync(cmake, { recursive: true });
258
- const r1 = run(\`cmake .. -DSRC_FILE="${srcRel}" -DKIT_NAME="${kitName}"\`, cmake);
259
- const r2 = r1 && run('cmake --build . --config Release', cmake);
260
- if (r2) {
261
- const nodeFile = findNodeFile(cmake);
262
- if (nodeFile) { fs.copyFileSync(nodeFile, outBin); built = true; }
263
- }
264
- }
265
-
266
- // Strategy 3: raw gcc/clang
267
- if (!built) {
268
- console.log(' → Trying manual gcc/clang compile...');
269
- const compiler = hasTool('clang++') ? 'clang++' : hasTool('g++') ? 'g++' : null;
270
- if (compiler) {
271
- // Resolve include paths at build time
272
- let nodeHead = '', napiHead = '';
273
- try { const _p = require('path'); nodeHead = _p.join(_p.dirname(process.execPath), '..', 'include', 'node'); } catch(_) {}
274
- napiHead = require('path').join(__dirname, 'node_modules', 'node-addon-api');
275
- const isAndroid = process.platform === 'android' || process.env.TERMUX_VERSION;
276
- const sharedFlag = isAndroid ? '-shared' : process.platform === 'darwin' ? '-dynamiclib' : '-shared';
277
- const extraFlags = process.platform === 'darwin' ? '-undefined dynamic_lookup' : '';
278
- const flags = [
279
- sharedFlag, '-fPIC', extraFlags,
280
- nodeHead ? \`-I"\${nodeHead}"\` : '',
281
- napiHead ? \`-I"\${napiHead}"\` : '',
282
- \`-DNAPI_VERSION=${NAPI_VERSION}\`,
283
- '-DNAPI_DISABLE_CPP_EXCEPTIONS',
284
- '-std=c++17',
285
- \`"\${srcFile}"\`,
286
- \`-o "\${outBin}"\`
287
- ].filter(Boolean).join(' ');
288
- const r = run(\`\${compiler} \${flags}\`, __dirname);
289
- if (r) built = true;
290
- }
291
- }
292
-
293
- if (!built) {
294
- console.warn(\` ✗ Could not build ${s.platform}-${s.arch}. Skipping.\`);
295
- } else {
296
- console.log(\` ✓ Built → bins/${bname}\`);
297
- }
298
- }
299
- }`;
300
- });
301
-
302
- return `#!/usr/bin/env node
303
- // build.js — auto-generated by kitnatives for ${kitName}
304
- // Run this to compile all native targets.
305
-
306
- 'use strict';
307
-
308
- const fs = require('fs');
309
- const path = require('path');
310
- const { execSync, spawnSync } = require('child_process');
311
-
312
- function run(cmd, cwd) {
313
- const r = spawnSync(cmd, { shell: true, cwd: cwd || __dirname, stdio: 'inherit' });
314
- return r.status === 0;
315
- }
316
-
317
- function hasTool(name) {
318
- const r = spawnSync(name, ['--version'], { shell: true, stdio: 'pipe' });
319
- return r.status === 0;
320
- }
321
-
322
- function findNodeFile(dir) {
323
- if (!fs.existsSync(dir)) return null;
324
- const entries = fs.readdirSync(dir, { withFileTypes: true });
325
- for (const e of entries) {
326
- const full = path.join(dir, e.name);
327
- if (e.isDirectory()) { const r = findNodeFile(full); if (r) return r; }
328
- else if (e.name.endsWith('.node')) return full;
329
- }
330
- return null;
331
- }
332
-
333
- fs.mkdirSync(path.join(__dirname, 'bins'), { recursive: true });
334
-
335
- ${builds.join('\n')}
336
-
337
- // Build unsupported stub
338
- {
339
- const stubSrc = path.join(__dirname, 'src', 'unsupported.cpp');
340
- const stubOut = path.join(__dirname, 'bins', '${kitName}-unsupported.node');
341
- if (!fs.existsSync(stubOut)) {
342
- console.log('[kitnatives] Building unsupported-arch stub...');
343
- const compiler = hasTool('clang++') ? 'clang++' : hasTool('g++') ? 'g++' : null;
344
- if (compiler) {
345
- const _p = require('path');
346
- const nodeHead = _p.join(_p.dirname(process.execPath), '..', 'include', 'node');
347
- const flags = [
348
- '-shared', '-fPIC', '-undefined dynamic_lookup',
349
- \`-I"\${nodeHead}"\`,
350
- \`-DNAPI_VERSION=${NAPI_VERSION}\`,
351
- '-std=c++17',
352
- \`"\${stubSrc}"\`,
353
- \`-o "\${stubOut}"\`
354
- ].join(' ');
355
- if (run(\`\${compiler} \${flags}\`, __dirname)) {
356
- console.log(' ✓ Built unsupported stub');
357
- }
358
- } else {
359
- console.warn(' ✗ No compiler found for stub. Missing-arch errors will throw JS exceptions.');
360
- }
361
- }
362
- }
363
-
364
- console.log('\\n[kitnatives] Build complete.');
365
- `;
366
- }
367
-
368
- // ─── MAIN GENERATOR ──────────────────────────────────────────────────────────
369
-
370
- function generate(opts) {
371
- const { name, sources, outBase } = opts;
372
-
373
- if (!name) throw new Error('--name is required');
374
- if (!sources?.length) throw new Error('--sources is required (at least one platform:file)');
375
-
376
- const kitName = name;
377
- const outDir = path.resolve(outBase ?? '.', `nkit${kitName}`);
378
-
379
- const srcDir = path.join(outDir, 'src');
380
- const binDir = path.join(outDir, 'bins');
381
-
382
- mkdir(outDir);
383
- mkdir(srcDir);
384
- mkdir(binDir);
385
-
386
- const parsedSources = sources.map(parseSourceSpec);
387
-
388
- // Copy source files into src/
389
- for (const s of parsedSources) {
390
- const dest = path.join(srcDir, path.basename(s.file));
391
- if (fs.existsSync(s.file)) {
392
- copy(s.file, dest);
393
- } else {
394
- // Create a placeholder if the file doesn't exist yet
395
- write(dest, `// Placeholder for ${s.file} (file not found during generation)\n`);
396
- console.warn(`[kitnatives] Warning: source file not found: ${s.file} — placeholder written`);
397
- }
398
- }
399
-
400
- // Write unsupported stub
401
- write(path.join(srcDir, 'unsupported.cpp'), genUnsupportedStub(kitName));
402
-
403
- // Write CMakeLists.txt (no binding.gyp — node-gyp is never used)
404
- const primarySrc = path.basename(parsedSources[0].file);
405
- write(path.join(outDir, 'CMakeLists.txt'), genCMakeLists(kitName, `src/${primarySrc}`, NAPI_VERSION));
406
-
407
- // Write kitdef.js
408
- write(path.join(outDir, 'kitdef.js'), genKitdef(kitName, parsedSources));
409
-
410
- // Write build.js
411
- write(path.join(outDir, 'build.js'), genBuildScript(kitName, parsedSources, outDir));
412
- try { fs.chmodSync(path.join(outDir, 'build.js'), 0o755); } catch (_) {}
413
-
414
- // Write package.json
415
- write(path.join(outDir, 'package.json'), JSON.stringify({
416
- name: `nkit${kitName}`,
417
- version: '1.0.0',
418
- main: 'kitdef.js',
419
- scripts: {
420
- build: 'node build.js'
421
- },
422
- dependencies: {
423
- 'node-addon-api': '^7.0.0'
424
- },
425
- description: `Native addon kit for ${kitName} (generated by kitnatives)`
426
- }, null, 2));
427
-
428
- // Write README
429
- write(path.join(outDir, 'README.md'), `# nkit${kitName}
430
-
431
- Native addon kit generated by **kitnatives**.
432
-
433
- ## Building
434
-
435
- \`\`\`sh
436
- npm install # installs node-addon-api headers
437
- node build.js # compiles all targets
438
- \`\`\`
439
-
440
- The build script tries three strategies in order:
441
- 1. **cmake-js** — if available globally
442
- 2. **cmake** — manual configure + build
443
- 3. **gcc/clang** — raw compiler invocation with manual flags
444
-
445
- If none succeed for a target, a warning is printed and that target is skipped.
446
- A fallback \`unsupported.node\` stub is always compiled; it prints a descriptive
447
- error message and throws if loaded on an unsupported platform.
448
-
449
- ## Supported targets
450
-
451
- | Platform | Arch | Source |
452
- |----------|------|--------|
453
- ${parsedSources.map(s => `| ${s.platform} | ${s.arch} | \`src/${path.basename(s.file)}\` |`).join('\n')}
454
-
455
- ## Usage
456
-
457
- \`\`\`js
458
- const { kitdef } = require('./kitdef.js');
459
- // kitdef === your addon's exports for this platform
460
- \`\`\`
461
- `);
462
-
463
- console.log(`\n[nvc] Generated nkit${kitName} at: ${outDir}`);
464
- console.log(` src/ ← your C/C++ sources`);
465
- console.log(` bins/ ← compiled .node binaries (after build.js)`);
466
- console.log(` CMakeLists.txt ← cmake build (no node-gyp, no binding.gyp)`);
467
- console.log(` kitdef.js ← runtime loader`);
468
- console.log(` build.js ← build orchestrator`);
469
- console.log(`\nNext: cd nkit${kitName} && npm install && node build.js\n`);
470
-
471
- return outDir;
472
- }
473
-
474
- // ─── CLI ─────────────────────────────────────────────────────────────────────
475
-
476
- function parseCLI(argv) {
477
- const args = argv.slice(2);
478
- const opts = { sources: [] };
479
-
480
- for (let i = 0; i < args.length; i++) {
481
- if (args[i] === '--name') { opts.name = args[++i]; }
482
- else if (args[i] === '--out') { opts.outBase = args[++i]; }
483
- else if (args[i] === '--sources') {
484
- while (args[i + 1] && !args[i + 1].startsWith('--')) {
485
- opts.sources.push(args[++i]);
486
- }
487
- }
488
- }
489
- return opts;
490
- }
491
-
492
- if (require.main === module) {
493
- const opts = parseCLI(process.argv);
494
- try {
495
- generate(opts);
496
- } catch (e) {
497
- console.error('[nvc] Error:', e.message);
498
- console.error('\nUsage:');
499
- console.error(' nvc natives --name <kitname> --sources <platform[-arch]>:<file> ...\n');
500
- console.error('Examples:');
501
- console.error(' nvc natives --name myaddon --sources linux-x64:src/addon.cpp darwin-arm64:src/addon_mac.cpp win32:src/addon_win.cpp');
502
- console.error(' nvc natives --name myaddon --sources linux:src/addon.cpp # any arch on linux');
503
- process.exit(1);
504
- }
505
- }
506
-
507
- // ─── EXPORTS ─────────────────────────────────────────────────────────────────
508
-
509
- module.exports = {
510
- kitdef: {
511
- generate,
512
- parseSourceSpec,
513
- binName,
514
- genCMakeLists,
515
- genUnsupportedStub,
516
- genKitdef,
517
- genBuildScript,
518
- SUPPORTED_PLATFORMS,
519
- SUPPORTED_ARCHS,
520
- NAPI_VERSION,
521
- }
522
- };