rollup-plugin-iife-split 0.0.3 → 0.0.5
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/README.md +23 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +201 -24
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -105,7 +105,8 @@ MyLib.Admin = (function (exports, shared) {
|
|
|
105
105
|
| `secondaryProps` | `Record<string, string>` | Yes | Maps secondary entry names to their property name on the primary global. Example: `{ admin: 'Admin' }` → `window.MyLib.Admin` |
|
|
106
106
|
| `sharedProp` | `string` | Yes | Property name on the global where shared exports are attached. Example: `'Shared'` → `window.MyLib.Shared` |
|
|
107
107
|
| `unshared` | `(id: string) => boolean` | No | Function that returns `true` for modules that should be duplicated instead of shared. See [Excluding Modules from Sharing](#excluding-modules-from-sharing). |
|
|
108
|
-
| `
|
|
108
|
+
| `debugDir` | `string` | No | Directory to write intermediate files for debugging. If set, writes ESM files before IIFE conversion to help diagnose issues. Example: `'./debug-output'` |
|
|
109
|
+
| `skipRequireGlobals` | `boolean` | No | If `true`, don't error when an external module is missing a `globals` mapping. Instead, let Rollup auto-generate a sanitized global name. Default: `false` |
|
|
109
110
|
|
|
110
111
|
## Excluding Modules from Sharing
|
|
111
112
|
|
|
@@ -135,6 +136,27 @@ With this configuration:
|
|
|
135
136
|
- They are **not** merged into the primary/shared chunk
|
|
136
137
|
- Each satellite entry is self-contained with its own copy of the locale data
|
|
137
138
|
|
|
139
|
+
## External Dependencies
|
|
140
|
+
|
|
141
|
+
When using external dependencies with IIFE output, you must specify `globals` in your Rollup output options to map module IDs to global variable names:
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
export default {
|
|
145
|
+
input: { /* ... */ },
|
|
146
|
+
external: ['lodash', '@fullcalendar/core'],
|
|
147
|
+
plugins: [iifeSplit({ /* ... */ })],
|
|
148
|
+
output: {
|
|
149
|
+
dir: 'dist',
|
|
150
|
+
globals: {
|
|
151
|
+
'lodash': '_',
|
|
152
|
+
'@fullcalendar/core': 'FullCalendar'
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
By default, the plugin will error if an external is missing from `globals`—this prevents invalid JavaScript output. If you want Rollup to auto-generate global names instead, set `skipRequireGlobals: true`.
|
|
159
|
+
|
|
138
160
|
## How It Works
|
|
139
161
|
|
|
140
162
|
1. **Build phase**: Rollup builds with ESM format, using `manualChunks` to consolidate all shared modules into one chunk
|
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,12 @@ interface IifeSplitOptions {
|
|
|
44
44
|
* Example: './debug-output'
|
|
45
45
|
*/
|
|
46
46
|
debugDir?: string;
|
|
47
|
+
/**
|
|
48
|
+
* If true, don't error when an external module is missing a global mapping.
|
|
49
|
+
* Instead, let Rollup generate a sanitized global name automatically.
|
|
50
|
+
* Default: false (errors on missing globals)
|
|
51
|
+
*/
|
|
52
|
+
skipRequireGlobals?: boolean;
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
declare function iifeSplit(options: IifeSplitOptions): Plugin;
|
package/dist/index.js
CHANGED
|
@@ -158,9 +158,12 @@ function destructureSharedParameter(code, mappings, parse) {
|
|
|
158
158
|
return ms.toString();
|
|
159
159
|
}
|
|
160
160
|
async function convertToIife(options) {
|
|
161
|
-
const { code, globalName, globals, sharedGlobalPath, sharedChunkFileName, parse } = options;
|
|
161
|
+
const { code, globalName, globals, sharedGlobalPath, sharedChunkFileName, parse, skipRequireGlobals } = options;
|
|
162
162
|
const importMappings = sharedGlobalPath ? extractSharedImportMappings(code, parse) : [];
|
|
163
163
|
const rollupGlobals = (id) => {
|
|
164
|
+
if (globalName && (id === globalName || globalName.startsWith(id + "."))) {
|
|
165
|
+
return id;
|
|
166
|
+
}
|
|
164
167
|
if (sharedGlobalPath) {
|
|
165
168
|
if (id.includes(SHARED_CHUNK_NAME)) {
|
|
166
169
|
return sharedGlobalPath;
|
|
@@ -172,7 +175,16 @@ async function convertToIife(options) {
|
|
|
172
175
|
}
|
|
173
176
|
}
|
|
174
177
|
}
|
|
175
|
-
|
|
178
|
+
const global = globals[id];
|
|
179
|
+
if (global === void 0) {
|
|
180
|
+
if (skipRequireGlobals) {
|
|
181
|
+
return void 0;
|
|
182
|
+
}
|
|
183
|
+
throw new Error(
|
|
184
|
+
`[iife-split] Missing global for external "${id}". IIFE builds require all externals to have a global mapping. Add it to output.globals in your Rollup config, e.g.: globals: { '${id}': 'SomeGlobalName' }`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
return global;
|
|
176
188
|
};
|
|
177
189
|
const bundle = await rollup({
|
|
178
190
|
input: VIRTUAL_ENTRY,
|
|
@@ -184,6 +196,7 @@ async function convertToIife(options) {
|
|
|
184
196
|
const { output } = await bundle.generate({
|
|
185
197
|
format: "iife",
|
|
186
198
|
name: globalName,
|
|
199
|
+
// Cast needed: Rollup's types say string, but it handles undefined by using default name generation
|
|
187
200
|
globals: rollupGlobals,
|
|
188
201
|
exports: "named"
|
|
189
202
|
});
|
|
@@ -242,6 +255,22 @@ function extractTopLevelDeclarations(code, parse) {
|
|
|
242
255
|
}
|
|
243
256
|
return declarations;
|
|
244
257
|
}
|
|
258
|
+
function extractExternalImportBindings(code, parse) {
|
|
259
|
+
const ast = parse(code);
|
|
260
|
+
const bindings = /* @__PURE__ */ new Set();
|
|
261
|
+
for (const node of ast.body) {
|
|
262
|
+
if (node.type === "ImportDeclaration") {
|
|
263
|
+
const importNode = node;
|
|
264
|
+
const source = importNode.source.value;
|
|
265
|
+
if (typeof source === "string" && !source.startsWith(".") && !source.startsWith("/")) {
|
|
266
|
+
for (const spec of importNode.specifiers) {
|
|
267
|
+
bindings.add(spec.local.name);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return bindings;
|
|
273
|
+
}
|
|
245
274
|
function renameIdentifiers(code, renameMap, parse) {
|
|
246
275
|
if (renameMap.size === 0) return code;
|
|
247
276
|
const ast = parse(code);
|
|
@@ -321,6 +350,117 @@ function stripExports(code, parse) {
|
|
|
321
350
|
});
|
|
322
351
|
return s.toString();
|
|
323
352
|
}
|
|
353
|
+
function extractExternalImports(code, parse) {
|
|
354
|
+
const ast = parse(code);
|
|
355
|
+
const imports = [];
|
|
356
|
+
walk2(ast, {
|
|
357
|
+
enter(node) {
|
|
358
|
+
if (node.type === "ImportDeclaration") {
|
|
359
|
+
const importNode = node;
|
|
360
|
+
const source = importNode.source.value;
|
|
361
|
+
if (typeof source === "string" && !source.startsWith(".") && !source.startsWith("/")) {
|
|
362
|
+
const specifiers = [];
|
|
363
|
+
for (const spec of importNode.specifiers) {
|
|
364
|
+
if (spec.type === "ImportDefaultSpecifier") {
|
|
365
|
+
specifiers.push({ type: "default", localName: spec.local.name });
|
|
366
|
+
} else if (spec.type === "ImportNamespaceSpecifier") {
|
|
367
|
+
specifiers.push({ type: "namespace", localName: spec.local.name });
|
|
368
|
+
} else if (spec.type === "ImportSpecifier" && spec.imported) {
|
|
369
|
+
specifiers.push({
|
|
370
|
+
type: "named",
|
|
371
|
+
localName: spec.local.name,
|
|
372
|
+
importedName: spec.imported.name
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
imports.push({
|
|
377
|
+
source,
|
|
378
|
+
specifiers,
|
|
379
|
+
fullStatement: code.slice(importNode.start, importNode.end),
|
|
380
|
+
start: importNode.start,
|
|
381
|
+
end: importNode.end
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
return imports;
|
|
388
|
+
}
|
|
389
|
+
function removeOrRewriteDuplicateExternalImports(sharedCode, primaryImports, parse) {
|
|
390
|
+
const sharedImports = extractExternalImports(sharedCode, parse);
|
|
391
|
+
const s = new MagicString2(sharedCode);
|
|
392
|
+
const renameMap = /* @__PURE__ */ new Map();
|
|
393
|
+
const primaryBySource = /* @__PURE__ */ new Map();
|
|
394
|
+
for (const imp of primaryImports) {
|
|
395
|
+
const existing = primaryBySource.get(imp.source) || [];
|
|
396
|
+
existing.push(imp);
|
|
397
|
+
primaryBySource.set(imp.source, existing);
|
|
398
|
+
}
|
|
399
|
+
for (const sharedImp of sharedImports) {
|
|
400
|
+
const primaryImpsForSource = primaryBySource.get(sharedImp.source);
|
|
401
|
+
if (!primaryImpsForSource) continue;
|
|
402
|
+
const specifiersToKeep = [];
|
|
403
|
+
for (const sharedSpec of sharedImp.specifiers) {
|
|
404
|
+
let foundInPrimary = false;
|
|
405
|
+
for (const primaryImp of primaryImpsForSource) {
|
|
406
|
+
for (const primarySpec of primaryImp.specifiers) {
|
|
407
|
+
if (sharedSpec.type === primarySpec.type) {
|
|
408
|
+
if (sharedSpec.type === "named" && primarySpec.type === "named") {
|
|
409
|
+
if (sharedSpec.importedName === primarySpec.importedName) {
|
|
410
|
+
foundInPrimary = true;
|
|
411
|
+
if (sharedSpec.localName !== primarySpec.localName) {
|
|
412
|
+
renameMap.set(sharedSpec.localName, primarySpec.localName);
|
|
413
|
+
}
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
} else if (sharedSpec.type === "default" && primarySpec.type === "default") {
|
|
417
|
+
foundInPrimary = true;
|
|
418
|
+
if (sharedSpec.localName !== primarySpec.localName) {
|
|
419
|
+
renameMap.set(sharedSpec.localName, primarySpec.localName);
|
|
420
|
+
}
|
|
421
|
+
break;
|
|
422
|
+
} else if (sharedSpec.type === "namespace" && primarySpec.type === "namespace") {
|
|
423
|
+
foundInPrimary = true;
|
|
424
|
+
if (sharedSpec.localName !== primarySpec.localName) {
|
|
425
|
+
renameMap.set(sharedSpec.localName, primarySpec.localName);
|
|
426
|
+
}
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (foundInPrimary) break;
|
|
432
|
+
}
|
|
433
|
+
if (!foundInPrimary) {
|
|
434
|
+
specifiersToKeep.push(sharedSpec);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (specifiersToKeep.length === 0) {
|
|
438
|
+
s.remove(sharedImp.start, sharedImp.end);
|
|
439
|
+
} else if (specifiersToKeep.length < sharedImp.specifiers.length) {
|
|
440
|
+
const parts = [];
|
|
441
|
+
const namedParts = [];
|
|
442
|
+
for (const spec of specifiersToKeep) {
|
|
443
|
+
if (spec.type === "default") {
|
|
444
|
+
parts.unshift(spec.localName);
|
|
445
|
+
} else if (spec.type === "namespace") {
|
|
446
|
+
parts.push(`* as ${spec.localName}`);
|
|
447
|
+
} else if (spec.type === "named") {
|
|
448
|
+
if (spec.importedName === spec.localName) {
|
|
449
|
+
namedParts.push(spec.localName);
|
|
450
|
+
} else {
|
|
451
|
+
namedParts.push(`${spec.importedName} as ${spec.localName}`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
if (namedParts.length > 0) {
|
|
456
|
+
parts.push(`{ ${namedParts.join(", ")} }`);
|
|
457
|
+
}
|
|
458
|
+
const newImport = `import ${parts.join(", ")} from '${sharedImp.source}';`;
|
|
459
|
+
s.overwrite(sharedImp.start, sharedImp.end, newImport);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return { code: s.toString(), renameMap };
|
|
463
|
+
}
|
|
324
464
|
function isSharedChunkSource(source, sharedChunkFileName) {
|
|
325
465
|
return source.includes(SHARED_CHUNK_NAME) || source.includes(sharedChunkFileName.replace(/\.js$/, ""));
|
|
326
466
|
}
|
|
@@ -546,56 +686,63 @@ ${entryWithoutImports.trim()}`;
|
|
|
546
686
|
}
|
|
547
687
|
function mergeSharedIntoPrimary(primaryChunk, sharedChunk, sharedProperty, neededExports, parse) {
|
|
548
688
|
const { exports: sharedExports, hasDefault } = extractExports(sharedChunk.code, parse);
|
|
689
|
+
const sharedExternalImports = extractExternalImports(sharedChunk.code, parse);
|
|
690
|
+
const { code: primaryCodeDeduped, renameMap: externalRenameMap } = removeOrRewriteDuplicateExternalImports(primaryChunk.code, sharedExternalImports, parse);
|
|
549
691
|
const sharedDeclarations = extractTopLevelDeclarations(sharedChunk.code, parse);
|
|
550
|
-
const primaryDeclarations = extractTopLevelDeclarations(
|
|
551
|
-
const
|
|
692
|
+
const primaryDeclarations = extractTopLevelDeclarations(primaryCodeDeduped, parse);
|
|
693
|
+
const primaryExternalBindings = extractExternalImportBindings(primaryCodeDeduped, parse);
|
|
694
|
+
const collisionRenameMap = /* @__PURE__ */ new Map();
|
|
552
695
|
for (const name of sharedDeclarations) {
|
|
553
|
-
if (primaryDeclarations.has(name)) {
|
|
554
|
-
|
|
696
|
+
if (primaryDeclarations.has(name) || primaryExternalBindings.has(name)) {
|
|
697
|
+
collisionRenameMap.set(name, `__shared$${name}`);
|
|
555
698
|
}
|
|
556
699
|
}
|
|
557
700
|
let processedSharedCode = sharedChunk.code;
|
|
558
|
-
if (
|
|
559
|
-
processedSharedCode = renameIdentifiers(processedSharedCode,
|
|
701
|
+
if (collisionRenameMap.size > 0) {
|
|
702
|
+
processedSharedCode = renameIdentifiers(processedSharedCode, collisionRenameMap, parse);
|
|
560
703
|
}
|
|
561
704
|
const strippedSharedCode = stripExports(processedSharedCode, parse);
|
|
562
705
|
const sharedExportToLocal = /* @__PURE__ */ new Map();
|
|
563
706
|
for (const exp of sharedExports) {
|
|
564
|
-
const renamedLocal =
|
|
707
|
+
const renamedLocal = collisionRenameMap.get(exp.localName) ?? exp.localName;
|
|
565
708
|
sharedExportToLocal.set(exp.exportedName, renamedLocal);
|
|
566
709
|
}
|
|
567
710
|
if (hasDefault) {
|
|
568
711
|
sharedExportToLocal.set("default", "__shared_default__");
|
|
569
712
|
}
|
|
570
|
-
|
|
571
|
-
|
|
713
|
+
let primaryWithoutSharedImports = removeSharedImportsAndRewriteRefs(
|
|
714
|
+
primaryCodeDeduped,
|
|
572
715
|
sharedChunk.fileName,
|
|
573
716
|
sharedExportToLocal,
|
|
574
717
|
parse
|
|
575
718
|
);
|
|
719
|
+
if (externalRenameMap.size > 0) {
|
|
720
|
+
primaryWithoutSharedImports = renameIdentifiers(primaryWithoutSharedImports, externalRenameMap, parse);
|
|
721
|
+
}
|
|
576
722
|
const sharedExportEntries = [
|
|
577
723
|
...sharedExports.filter((exp) => neededExports.has(exp.exportedName)).map((exp) => {
|
|
578
|
-
const renamedLocal =
|
|
724
|
+
const renamedLocal = collisionRenameMap.get(exp.localName) ?? exp.localName;
|
|
579
725
|
return exp.exportedName === renamedLocal ? renamedLocal : `${exp.exportedName}: ${renamedLocal}`;
|
|
580
726
|
}),
|
|
581
727
|
...hasDefault && neededExports.has("default") ? ["default: __shared_default__"] : []
|
|
582
728
|
];
|
|
583
|
-
const
|
|
584
|
-
primaryChunk.code = [
|
|
729
|
+
const parts = [
|
|
585
730
|
strippedSharedCode.trim(),
|
|
586
731
|
"",
|
|
587
|
-
primaryWithoutSharedImports.trim()
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
`
|
|
591
|
-
|
|
732
|
+
primaryWithoutSharedImports.trim()
|
|
733
|
+
];
|
|
734
|
+
if (sharedExportEntries.length > 0) {
|
|
735
|
+
const sharedExportObject = `const ${sharedProperty} = { ${sharedExportEntries.join(", ")} };`;
|
|
736
|
+
parts.push("", sharedExportObject, `export { ${sharedProperty} };`);
|
|
737
|
+
}
|
|
738
|
+
primaryChunk.code = parts.join("\n");
|
|
592
739
|
}
|
|
593
740
|
|
|
594
741
|
// src/index.ts
|
|
595
742
|
import { writeFileSync, mkdirSync } from "fs";
|
|
596
743
|
import { join } from "path";
|
|
597
744
|
function iifeSplit(options) {
|
|
598
|
-
const { primary, primaryGlobal, secondaryProps, sharedProp, unshared, debugDir } = options;
|
|
745
|
+
const { primary, primaryGlobal, secondaryProps, sharedProp, unshared, debugDir, skipRequireGlobals } = options;
|
|
599
746
|
const sanitizeName = (name) => name.replace(/[/\\]/g, "-");
|
|
600
747
|
const writeDebugFile = (filename, content) => {
|
|
601
748
|
if (!debugDir) return;
|
|
@@ -607,6 +754,8 @@ function iifeSplit(options) {
|
|
|
607
754
|
}
|
|
608
755
|
};
|
|
609
756
|
let outputGlobals = {};
|
|
757
|
+
let outputBanner;
|
|
758
|
+
let outputFooter;
|
|
610
759
|
const manualChunks = (id, { getModuleInfo }) => {
|
|
611
760
|
const moduleInfo = getModuleInfo(id);
|
|
612
761
|
if (!moduleInfo) return void 0;
|
|
@@ -622,13 +771,18 @@ function iifeSplit(options) {
|
|
|
622
771
|
};
|
|
623
772
|
return {
|
|
624
773
|
name: "iife-split",
|
|
625
|
-
// Hook into outputOptions to capture globals and configure chunking
|
|
774
|
+
// Hook into outputOptions to capture globals/banner/footer and configure chunking
|
|
626
775
|
outputOptions(outputOptions) {
|
|
627
776
|
outputGlobals = outputOptions.globals ?? {};
|
|
777
|
+
outputBanner = outputOptions.banner;
|
|
778
|
+
outputFooter = outputOptions.footer;
|
|
628
779
|
return {
|
|
629
780
|
...outputOptions,
|
|
630
781
|
format: "es",
|
|
631
|
-
manualChunks
|
|
782
|
+
manualChunks,
|
|
783
|
+
// Remove banner/footer so Rollup doesn't embed them in ESM
|
|
784
|
+
banner: void 0,
|
|
785
|
+
footer: void 0
|
|
632
786
|
};
|
|
633
787
|
},
|
|
634
788
|
// Main transformation hook - convert ESM chunks to IIFE
|
|
@@ -691,7 +845,8 @@ function iifeSplit(options) {
|
|
|
691
845
|
sharedGlobalPath: null,
|
|
692
846
|
// Primary doesn't need to import shared
|
|
693
847
|
sharedChunkFileName: null,
|
|
694
|
-
parse
|
|
848
|
+
parse,
|
|
849
|
+
skipRequireGlobals
|
|
695
850
|
}).then((code) => {
|
|
696
851
|
analysis.primaryChunk.code = code;
|
|
697
852
|
})
|
|
@@ -712,13 +867,35 @@ function iifeSplit(options) {
|
|
|
712
867
|
globals: outputGlobals,
|
|
713
868
|
sharedGlobalPath: `${primaryGlobal}.${sharedProp}`,
|
|
714
869
|
sharedChunkFileName,
|
|
715
|
-
parse
|
|
870
|
+
parse,
|
|
871
|
+
skipRequireGlobals
|
|
716
872
|
}).then((code) => {
|
|
717
873
|
satellite.code = code;
|
|
718
874
|
})
|
|
719
875
|
);
|
|
720
876
|
}
|
|
721
877
|
await Promise.all(conversions);
|
|
878
|
+
if (outputBanner || outputFooter) {
|
|
879
|
+
for (const chunk of Object.values(bundle)) {
|
|
880
|
+
if (chunk.type === "chunk") {
|
|
881
|
+
const resolveBannerFooter = async (value) => {
|
|
882
|
+
if (value === void 0) return "";
|
|
883
|
+
if (typeof value === "function") {
|
|
884
|
+
return await value(chunk);
|
|
885
|
+
}
|
|
886
|
+
return value;
|
|
887
|
+
};
|
|
888
|
+
const banner = await resolveBannerFooter(outputBanner);
|
|
889
|
+
const footer = await resolveBannerFooter(outputFooter);
|
|
890
|
+
if (banner) {
|
|
891
|
+
chunk.code = banner + "\n" + chunk.code;
|
|
892
|
+
}
|
|
893
|
+
if (footer) {
|
|
894
|
+
chunk.code = chunk.code + "\n" + footer;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
722
899
|
}
|
|
723
900
|
};
|
|
724
901
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rollup-plugin-iife-split",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Rollup plugin for intelligent IIFE code-splitting",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,15 +12,16 @@
|
|
|
12
12
|
"rollup": "^3.0.0 || ^4.0.0"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"
|
|
16
|
-
"
|
|
15
|
+
"estree-walker": "^3.0.0",
|
|
16
|
+
"magic-string": "^0.30.0"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
+
"@types/node": "^20.0.0",
|
|
20
|
+
"acorn": "^8.15.0",
|
|
19
21
|
"rollup": "^4.0.0",
|
|
20
|
-
"typescript": "^5.0.0",
|
|
21
22
|
"tsup": "^8.0.0",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
23
|
+
"typescript": "^5.0.0",
|
|
24
|
+
"vitest": "^1.0.0"
|
|
24
25
|
},
|
|
25
26
|
"keywords": [
|
|
26
27
|
"rollup",
|