@napi-rs/cli 3.9.0 → 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.
- package/dist/cli.js +9087 -8769
- package/dist/index.cjs +9078 -8760
- package/dist/index.d.cts +16 -16
- package/dist/index.d.ts +16 -16
- package/dist/index.js +9087 -8769
- package/package.json +4 -5
- package/src/api/__tests__/__snapshots__/templates.spec.ts.md +9 -13
- package/src/api/__tests__/__snapshots__/templates.spec.ts.snap +0 -0
- package/src/api/__tests__/build.spec.ts +194 -0
- package/src/api/__tests__/create-npm-dirs.spec.ts +4 -3
- package/src/api/__tests__/templates.spec.ts +62 -1
- package/src/api/build.ts +124 -4
- package/src/api/create-npm-dirs.ts +2 -1
- package/src/api/new.ts +13 -18
- package/src/api/pre-publish.ts +5 -10
- package/src/api/rename.ts +10 -21
- package/src/api/templates/js-binding.ts +7 -8
- package/src/api/templates/load-wasi-template.ts +20 -17
- package/src/api/templates/wasi-worker-template.ts +36 -31
- package/src/commands/build.ts +1 -1
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +18 -28
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
- package/src/utils/__tests__/misc.spec.ts +4 -0
- package/src/utils/__tests__/serialize.spec.ts +55 -0
- package/src/utils/__tests__/target.spec.ts +221 -0
- package/src/utils/__tests__/typegen.spec.ts +115 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/misc.ts +4 -5
- package/src/utils/serialize.ts +47 -0
- package/src/utils/target.ts +150 -1
- package/src/utils/typegen.ts +241 -30
package/src/utils/typegen.ts
CHANGED
|
@@ -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
|
-
|
|
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}
|
|
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}
|
|
226
|
+
s += `${exportDeclare(ambient)} const enum ${line.name} ${enumBody(line.def)}`
|
|
222
227
|
} else if (runtimeStringEnum) {
|
|
223
|
-
s += `${exportDeclare(ambient)} enum ${line.name}
|
|
228
|
+
s += `${exportDeclare(ambient)} enum ${line.name} ${enumBody(line.def)}`
|
|
224
229
|
} else {
|
|
225
|
-
s += `export type ${line.name} = ${line.def
|
|
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 =
|
|
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}
|
|
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((
|
|
1428
|
-
line =
|
|
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
|
|
1623
|
+
const netBraces = isInMultilineComment ? 0 : netUnquotedBraces(line)
|
|
1438
1624
|
|
|
1439
|
-
|
|
1440
|
-
|
|
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
|
-
|
|
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
|
|
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
|
+
}
|