@napi-rs/cli 3.8.6 → 3.9.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.
Files changed (34) hide show
  1. package/dist/cli.js +9085 -8737
  2. package/dist/index.cjs +9092 -8744
  3. package/dist/index.d.cts +37 -17
  4. package/dist/index.d.ts +37 -17
  5. package/dist/index.js +9085 -8737
  6. package/docs/build.md +36 -34
  7. package/package.json +4 -5
  8. package/src/api/__tests__/__snapshots__/templates.spec.ts.md +9 -13
  9. package/src/api/__tests__/__snapshots__/templates.spec.ts.snap +0 -0
  10. package/src/api/__tests__/build.spec.ts +284 -0
  11. package/src/api/__tests__/create-npm-dirs.spec.ts +4 -3
  12. package/src/api/__tests__/templates.spec.ts +84 -1
  13. package/src/api/build.ts +181 -7
  14. package/src/api/create-npm-dirs.ts +2 -1
  15. package/src/api/new.ts +13 -18
  16. package/src/api/pre-publish.ts +5 -10
  17. package/src/api/rename.ts +10 -21
  18. package/src/api/templates/js-binding.ts +7 -9
  19. package/src/api/templates/load-wasi-template.ts +20 -17
  20. package/src/api/templates/wasi-worker-template.ts +36 -31
  21. package/src/commands/__tests__/build.spec.ts +24 -0
  22. package/src/commands/build.ts +1 -1
  23. package/src/def/build.ts +30 -4
  24. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +18 -28
  25. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
  26. package/src/utils/__tests__/misc.spec.ts +4 -0
  27. package/src/utils/__tests__/serialize.spec.ts +55 -0
  28. package/src/utils/__tests__/target.spec.ts +221 -0
  29. package/src/utils/__tests__/typegen.spec.ts +115 -0
  30. package/src/utils/index.ts +1 -0
  31. package/src/utils/misc.ts +4 -5
  32. package/src/utils/serialize.ts +47 -0
  33. package/src/utils/target.ts +150 -1
  34. package/src/utils/typegen.ts +241 -30
@@ -206,23 +206,28 @@ function prettyPrint(
206
206
  s += `export interface ${line.name} {\n${line.def}\n}`
207
207
  break
208
208
 
209
- case TypeDefKind.Type:
210
- s += `export type ${line.name} = \n${line.def}`
209
+ case TypeDefKind.Type: {
210
+ const def = line.def.trim()
211
+ s +=
212
+ def.startsWith('|') || def.includes('\n')
213
+ ? `export type ${line.name} =\n${line.def}`
214
+ : `export type ${line.name} = ${def}`
211
215
  break
216
+ }
212
217
 
213
218
  case TypeDefKind.Enum: {
214
219
  const enumName = constEnum ? 'const enum' : 'enum'
215
- s += `${exportDeclare(ambient)} ${enumName} ${line.name} {\n${line.def}\n}`
220
+ s += `${exportDeclare(ambient)} ${enumName} ${line.name} ${enumBody(line.def)}`
216
221
  break
217
222
  }
218
223
 
219
224
  case TypeDefKind.StringEnum: {
220
225
  if (constEnum) {
221
- s += `${exportDeclare(ambient)} const enum ${line.name} {\n${line.def}\n}`
226
+ s += `${exportDeclare(ambient)} const enum ${line.name} ${enumBody(line.def)}`
222
227
  } else if (runtimeStringEnum) {
223
- s += `${exportDeclare(ambient)} enum ${line.name} {\n${line.def}\n}`
228
+ s += `${exportDeclare(ambient)} enum ${line.name} ${enumBody(line.def)}`
224
229
  } else {
225
- s += `export type ${line.name} = ${line.def.replaceAll(/.*=/g, '').replaceAll(',', '|')};`
230
+ s += `export type ${line.name} = ${stringEnumToUnion(line.def)}`
226
231
  }
227
232
  break
228
233
  }
@@ -238,7 +243,7 @@ function prettyPrint(
238
243
  // Runtime instances inherit from Iterator.prototype when it exists,
239
244
  // but the generated constructor does not extend the global Iterator.
240
245
  const [T, TResult, TNext] = iteratorTypes
241
- const resultType = `(${TResult}) | undefined`
246
+ const resultType = `${unionPart(TResult)} | undefined`
242
247
  classDef +=
243
248
  `\n[globalThis.Symbol.iterator](): this` +
244
249
  `\nnext(...[value]: [] | [${TNext}]): globalThis.IteratorResult<${T}, ${resultType}>` +
@@ -256,7 +261,7 @@ function prettyPrint(
256
261
  const [T, TResult, TNext] = line.asyncIterator
257
262
  classDef += `\n[globalThis.Symbol.asyncIterator](): globalThis.${asyncGeneratorHelperName}<${line.name}, ${T}, ${TResult}, ${TNext}>`
258
263
  }
259
- s += `${exportDeclare(ambient)} class ${line.name}${extendsDef} {\n${classDef}\n}`
264
+ s += `${exportDeclare(ambient)} class ${line.name}${extendsDef} ${blockBody(classDef)}`
260
265
  s += iteratorInterface
261
266
  if (line.original_name && line.original_name !== line.name) {
262
267
  s += `\nexport type ${line.original_name} = ${line.name}`
@@ -268,6 +273,10 @@ function prettyPrint(
268
273
  s += `${exportDeclare(ambient)} ${line.def}`
269
274
  break
270
275
 
276
+ case TypeDefKind.Const:
277
+ s += ambient ? line.def : declareExportedConst(line.def)
278
+ break
279
+
271
280
  default:
272
281
  s += line.def
273
282
  }
@@ -283,6 +292,185 @@ function exportDeclare(ambient: boolean): string {
283
292
  return 'export declare'
284
293
  }
285
294
 
295
+ function blockBody(def: string): string {
296
+ const body = def.trim()
297
+ return body ? `{\n${def}\n}` : '{}'
298
+ }
299
+
300
+ function enumBody(def: string): string {
301
+ const body = def.trim()
302
+ if (!body) {
303
+ return '{}'
304
+ }
305
+ const withTrailingComma = body.endsWith(',') ? def : `${def},`
306
+ return `{\n${withTrailingComma}\n}`
307
+ }
308
+
309
+ function unionPart(type: string): string {
310
+ return type.includes('|') || type.includes('&') || type.includes('=>')
311
+ ? `(${type})`
312
+ : type
313
+ }
314
+
315
+ const EXPORT_CONST_PREFIX = 'export const '
316
+
317
+ function declareExportedConst(def: string): string {
318
+ return def.startsWith(EXPORT_CONST_PREFIX)
319
+ ? `export declare const ${def.slice(EXPORT_CONST_PREFIX.length)}`
320
+ : def
321
+ }
322
+
323
+ function isWhitespace(character: string): boolean {
324
+ return (
325
+ character === ' ' ||
326
+ character === '\t' ||
327
+ character === '\n' ||
328
+ character === '\r'
329
+ )
330
+ }
331
+
332
+ /**
333
+ * Walk a rust-emitted string-enum body (`Name = 'value', ...`) and collect
334
+ * the initializer literals. Comments and commas inside quotes are skipped
335
+ * by scanning rather than by splitting on `,`.
336
+ */
337
+ function stringEnumToUnion(def: string): string {
338
+ const values: string[] = []
339
+ let index = 0
340
+
341
+ const eof = () => index >= def.length
342
+ const peek = (offset = 0) => def[index + offset]
343
+
344
+ const skipTrivia = () => {
345
+ while (!eof()) {
346
+ const character = peek()
347
+ if (character !== undefined && isWhitespace(character)) {
348
+ index += 1
349
+ continue
350
+ }
351
+ if (character === '/' && peek(1) === '/') {
352
+ index += 2
353
+ while (!eof() && peek() !== '\n') {
354
+ index += 1
355
+ }
356
+ continue
357
+ }
358
+ if (character === '/' && peek(1) === '*') {
359
+ index += 2
360
+ while (!eof() && !(peek() === '*' && peek(1) === '/')) {
361
+ index += 1
362
+ }
363
+ if (!eof()) {
364
+ index += 2
365
+ }
366
+ continue
367
+ }
368
+ return
369
+ }
370
+ }
371
+
372
+ const isNameTerminator = (character: string) =>
373
+ isWhitespace(character) ||
374
+ character === '=' ||
375
+ character === ',' ||
376
+ character === "'" ||
377
+ character === '"' ||
378
+ character === '/'
379
+
380
+ const parseName = () => {
381
+ if (peek() === "'" || peek() === '"') {
382
+ return parseString() !== undefined
383
+ }
384
+ const character = peek()
385
+ if (
386
+ character === undefined ||
387
+ isNameTerminator(character) ||
388
+ (character >= '0' && character <= '9')
389
+ ) {
390
+ return false
391
+ }
392
+ index += 1
393
+ while (!eof()) {
394
+ const next = peek()
395
+ if (next === undefined || isNameTerminator(next)) {
396
+ break
397
+ }
398
+ index += 1
399
+ }
400
+ return true
401
+ }
402
+
403
+ const parseString = () => {
404
+ const quote = peek()
405
+ if (quote !== "'" && quote !== '"') {
406
+ return
407
+ }
408
+ let end = index + 1
409
+ while (end < def.length) {
410
+ if (def[end] === '\\') {
411
+ end += 2
412
+ continue
413
+ }
414
+ if (def[end] === quote) {
415
+ const literal = def.slice(index, end + 1)
416
+ index = end + 1
417
+ return literal
418
+ }
419
+ end += 1
420
+ }
421
+ return
422
+ }
423
+
424
+ const parseNumber = () => {
425
+ let end = index
426
+ if (def[end] === '-') {
427
+ end += 1
428
+ }
429
+ const firstDigit = def[end]
430
+ if (firstDigit === undefined || firstDigit < '0' || firstDigit > '9') {
431
+ return
432
+ }
433
+ end += 1
434
+ while (end < def.length) {
435
+ const digit = def[end]
436
+ if (digit === undefined || digit < '0' || digit > '9') {
437
+ break
438
+ }
439
+ end += 1
440
+ }
441
+ const literal = def.slice(index, end)
442
+ index = end
443
+ return literal
444
+ }
445
+
446
+ while (!eof()) {
447
+ skipTrivia()
448
+ if (eof()) {
449
+ break
450
+ }
451
+ if (peek() === ',') {
452
+ index += 1
453
+ continue
454
+ }
455
+ if (!parseName()) {
456
+ index += 1
457
+ continue
458
+ }
459
+ skipTrivia()
460
+ if (peek() !== '=') {
461
+ continue
462
+ }
463
+ index += 1
464
+ skipTrivia()
465
+ const value = parseString() ?? parseNumber()
466
+ if (value !== undefined) {
467
+ values.push(value)
468
+ }
469
+ }
470
+
471
+ return values.join(' | ')
472
+ }
473
+
286
474
  /**
287
475
  * Read the napi-derive-emitted intermediate type-def file and render its
288
476
  * entries into the `index.d.ts` source string plus the list of names to
@@ -452,7 +640,7 @@ function renderTypeDefs(
452
640
  })
453
641
  .join('\n\n'),
454
642
  )
455
- .join('\n')
643
+ .join('\n\n')
456
644
  const globalDeclarations = []
457
645
  if (hasIteratorClass) {
458
646
  globalDeclarations.push(ITERATOR_OBJECT_COMPATIBILITY_DECLARATION)
@@ -1424,43 +1612,66 @@ export function correctStringIdent(src: string, ident: number): string {
1424
1612
  let bracketDepth = 0
1425
1613
  const result = src
1426
1614
  .split('\n')
1427
- .map((line) => {
1428
- line = line.trim()
1615
+ .map((rawLine) => {
1616
+ const line = rawLine.trim()
1429
1617
  if (line === '') {
1430
1618
  return ''
1431
1619
  }
1432
1620
 
1433
1621
  const isInMultilineComment = line.startsWith('*')
1434
- const isClosingBracket = line.endsWith('}')
1435
- const isOpeningBracket = line.endsWith('{')
1436
1622
  const isTypeDeclaration = line.endsWith('=')
1437
- const isTypeVariant = line.startsWith('|')
1623
+ const netBraces = isInMultilineComment ? 0 : netUnquotedBraces(line)
1438
1624
 
1439
- let rightIndent = ident
1440
- if ((isOpeningBracket || isTypeDeclaration) && !isInMultilineComment) {
1441
- bracketDepth += 1
1442
- rightIndent += (bracketDepth - 1) * 2
1443
- } else {
1444
- if (
1445
- isClosingBracket &&
1446
- bracketDepth > 0 &&
1447
- !isInMultilineComment &&
1448
- !isTypeVariant
1449
- ) {
1450
- bracketDepth -= 1
1451
- }
1452
- rightIndent += bracketDepth * 2
1625
+ if (netBraces < 0 && !line.startsWith('|')) {
1626
+ bracketDepth = Math.max(0, bracketDepth + netBraces)
1453
1627
  }
1454
1628
 
1629
+ let rightIndent = ident + bracketDepth * 2
1455
1630
  if (isInMultilineComment) {
1456
1631
  rightIndent += 1
1457
1632
  }
1458
1633
 
1459
- const s = `${' '.repeat(rightIndent)}${line}`
1634
+ if (netBraces > 0) {
1635
+ bracketDepth += netBraces
1636
+ } else if (
1637
+ isTypeDeclaration &&
1638
+ !isInMultilineComment &&
1639
+ netBraces === 0
1640
+ ) {
1641
+ bracketDepth += 1
1642
+ }
1460
1643
 
1461
- return s
1644
+ return `${' '.repeat(rightIndent)}${line}`
1462
1645
  })
1463
1646
  .join('\n')
1464
1647
 
1465
1648
  return result
1466
1649
  }
1650
+
1651
+ function netUnquotedBraces(line: string): number {
1652
+ let net = 0
1653
+ let quote: "'" | '"' | '`' | undefined
1654
+ let escaped = false
1655
+ for (const character of line) {
1656
+ if (quote) {
1657
+ if (escaped) {
1658
+ escaped = false
1659
+ } else if (character === '\\') {
1660
+ escaped = true
1661
+ } else if (character === quote) {
1662
+ quote = undefined
1663
+ }
1664
+ continue
1665
+ }
1666
+ if (character === "'" || character === '"' || character === '`') {
1667
+ quote = character
1668
+ continue
1669
+ }
1670
+ if (character === '{') {
1671
+ net += 1
1672
+ } else if (character === '}') {
1673
+ net -= 1
1674
+ }
1675
+ }
1676
+ return net
1677
+ }