tsnv 0.0.0-dev.20260119180902 → 0.0.0-dev.20260201114010
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 +6 -7
- package/dist/config.d.cts +66 -50
- package/dist/config.d.ts +66 -50
- package/dist/index.js +140 -60
- package/package.json +14 -9
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
# tsnv
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<img alt="preview" src="./preview.png">
|
|
6
|
+
|
|
7
|
+
Modern build toolkit for React Native libraries<br>
|
|
6
8
|
(powered by [Rolldown](https://rolldown.rs))
|
|
7
9
|
|
|
8
10
|
</div>
|
|
@@ -122,8 +124,7 @@ dist/
|
|
|
122
124
|
├── greeting.ios.js
|
|
123
125
|
└── types/
|
|
124
126
|
├── index.d.ts
|
|
125
|
-
|
|
126
|
-
└── greeting.ios.d.ts
|
|
127
|
+
└── greeting.d.ts
|
|
127
128
|
```
|
|
128
129
|
|
|
129
130
|
### CommonJS only (`format: 'cjs'`)
|
|
@@ -135,8 +136,7 @@ dist/
|
|
|
135
136
|
├── greeting.ios.js
|
|
136
137
|
└── types/
|
|
137
138
|
├── index.d.ts
|
|
138
|
-
|
|
139
|
-
└── greeting.ios.d.ts
|
|
139
|
+
└── greeting.d.ts
|
|
140
140
|
```
|
|
141
141
|
|
|
142
142
|
### Dual format (`format: ['esm', 'cjs']`)
|
|
@@ -153,8 +153,7 @@ dist/
|
|
|
153
153
|
│ └── greeting.ios.js
|
|
154
154
|
└── types/
|
|
155
155
|
├── index.d.ts
|
|
156
|
-
|
|
157
|
-
└── greeting.ios.d.ts
|
|
156
|
+
└── greeting.d.ts
|
|
158
157
|
```
|
|
159
158
|
|
|
160
159
|
## License
|
package/dist/config.d.cts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TsConfigJson } from "get-tsconfig";
|
|
1
2
|
import { OutputOptions } from "rolldown";
|
|
2
3
|
|
|
3
4
|
//#region src/types.d.ts
|
|
@@ -6,88 +7,103 @@ type Format = 'esm' | 'cjs';
|
|
|
6
7
|
//#region src/config/types.d.ts
|
|
7
8
|
interface Config {
|
|
8
9
|
/**
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
* Defaults to `'src'`
|
|
11
|
+
*/
|
|
11
12
|
source?: string;
|
|
12
13
|
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
* The directory where output files will be written.
|
|
15
|
+
*
|
|
16
|
+
* Defaults to `'dist'`
|
|
17
|
+
*/
|
|
17
18
|
outDir?: string;
|
|
18
19
|
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
* Files to exclude from the build.
|
|
21
|
+
*
|
|
22
|
+
* Defaults to `/__(?:tests?|fixtures?|mocks?)__/`
|
|
23
|
+
*/
|
|
23
24
|
exclude?: RegExp;
|
|
24
25
|
/**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
* Expected format of generated code.
|
|
27
|
+
*
|
|
28
|
+
* Defaults to `'esm'`
|
|
29
|
+
*/
|
|
29
30
|
format?: Format | Format[];
|
|
30
31
|
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
* Specifiers to resolve platform specific modules.
|
|
33
|
+
*
|
|
34
|
+
* Defaults to `['android', 'ios', 'native']`
|
|
35
|
+
*/
|
|
35
36
|
specifiers?: string[];
|
|
36
37
|
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
* Source files extensions.
|
|
39
|
+
*
|
|
40
|
+
* Defaults to `['ts', 'tsx', 'js', 'jsx', 'json']`
|
|
41
|
+
*/
|
|
41
42
|
sourceExtensions?: string[];
|
|
42
43
|
/**
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
* Asset files extensions.
|
|
45
|
+
*
|
|
46
|
+
* Default to following extensions: [Metro's default asset extensions](https://github.com/facebook/metro/blob/v0.83.3/packages/metro-config/src/defaults/defaults.js)
|
|
47
|
+
*/
|
|
47
48
|
assetExtensions?: string[];
|
|
48
49
|
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
* Enables generation of TypeScript declaration files (.d.ts).
|
|
51
|
+
*
|
|
52
|
+
* Defaults to `true`
|
|
53
|
+
*/
|
|
53
54
|
dts?: boolean;
|
|
54
55
|
/**
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
* Generate source map files.
|
|
57
|
+
*/
|
|
57
58
|
sourcemap?: OutputOptions['sourcemap'];
|
|
58
59
|
/**
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
* Code to prepend to the beginning of each output chunk.
|
|
61
|
+
*/
|
|
61
62
|
banner?: OutputOptions['banner'];
|
|
62
63
|
/**
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
* Code to append to the end of each output chunk.
|
|
65
|
+
*/
|
|
65
66
|
footer?: OutputOptions['footer'];
|
|
66
67
|
/**
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
* Code to prepend inside the wrapper function (after banner, before actual code).
|
|
69
|
+
*/
|
|
69
70
|
intro?: OutputOptions['intro'];
|
|
70
71
|
/**
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
* Code to append inside the wrapper function (after actual code, before footer).
|
|
73
|
+
*/
|
|
73
74
|
outro?: OutputOptions['outro'];
|
|
74
75
|
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
* Clean output directory before build.
|
|
77
|
+
*
|
|
78
|
+
* Defaults to `true`
|
|
79
|
+
*/
|
|
79
80
|
clean?: boolean;
|
|
80
81
|
/**
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
* The path to the tsconfig.json file.
|
|
83
|
+
*
|
|
84
|
+
* If set to `false`, the plugin will ignore any `tsconfig.json` file.
|
|
85
|
+
* You can still specify `compilerOptions` directly in the options.
|
|
86
|
+
*
|
|
87
|
+
* Defaults to `'tsconfig.json'`
|
|
88
|
+
*/
|
|
89
|
+
tsconfig?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Pass a raw `tsconfig.json` object directly to the plugin.
|
|
92
|
+
*
|
|
93
|
+
* @see https://www.typescriptlang.org/tsconfig
|
|
94
|
+
*/
|
|
95
|
+
tsconfigRaw?: Omit<TsConfigJson, 'compilerOptions'>;
|
|
96
|
+
/**
|
|
97
|
+
* Experimental configuration.
|
|
98
|
+
*/
|
|
83
99
|
experimental?: ExperimentalConfig;
|
|
84
100
|
}
|
|
85
101
|
interface ExperimentalConfig {
|
|
86
102
|
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
103
|
+
* Whether to use the tsgo compiler.
|
|
104
|
+
*
|
|
105
|
+
* To use this option, make sure `@typescript/native-preview` is installed as a dependency.
|
|
106
|
+
*/
|
|
91
107
|
tsgo?: boolean;
|
|
92
108
|
}
|
|
93
109
|
//#endregion
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TsConfigJson } from "get-tsconfig";
|
|
1
2
|
import { OutputOptions } from "rolldown";
|
|
2
3
|
|
|
3
4
|
//#region src/types.d.ts
|
|
@@ -6,88 +7,103 @@ type Format = 'esm' | 'cjs';
|
|
|
6
7
|
//#region src/config/types.d.ts
|
|
7
8
|
interface Config {
|
|
8
9
|
/**
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
* Defaults to `'src'`
|
|
11
|
+
*/
|
|
11
12
|
source?: string;
|
|
12
13
|
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
* The directory where output files will be written.
|
|
15
|
+
*
|
|
16
|
+
* Defaults to `'dist'`
|
|
17
|
+
*/
|
|
17
18
|
outDir?: string;
|
|
18
19
|
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
* Files to exclude from the build.
|
|
21
|
+
*
|
|
22
|
+
* Defaults to `/__(?:tests?|fixtures?|mocks?)__/`
|
|
23
|
+
*/
|
|
23
24
|
exclude?: RegExp;
|
|
24
25
|
/**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
* Expected format of generated code.
|
|
27
|
+
*
|
|
28
|
+
* Defaults to `'esm'`
|
|
29
|
+
*/
|
|
29
30
|
format?: Format | Format[];
|
|
30
31
|
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
* Specifiers to resolve platform specific modules.
|
|
33
|
+
*
|
|
34
|
+
* Defaults to `['android', 'ios', 'native']`
|
|
35
|
+
*/
|
|
35
36
|
specifiers?: string[];
|
|
36
37
|
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
* Source files extensions.
|
|
39
|
+
*
|
|
40
|
+
* Defaults to `['ts', 'tsx', 'js', 'jsx', 'json']`
|
|
41
|
+
*/
|
|
41
42
|
sourceExtensions?: string[];
|
|
42
43
|
/**
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
* Asset files extensions.
|
|
45
|
+
*
|
|
46
|
+
* Default to following extensions: [Metro's default asset extensions](https://github.com/facebook/metro/blob/v0.83.3/packages/metro-config/src/defaults/defaults.js)
|
|
47
|
+
*/
|
|
47
48
|
assetExtensions?: string[];
|
|
48
49
|
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
* Enables generation of TypeScript declaration files (.d.ts).
|
|
51
|
+
*
|
|
52
|
+
* Defaults to `true`
|
|
53
|
+
*/
|
|
53
54
|
dts?: boolean;
|
|
54
55
|
/**
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
* Generate source map files.
|
|
57
|
+
*/
|
|
57
58
|
sourcemap?: OutputOptions['sourcemap'];
|
|
58
59
|
/**
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
* Code to prepend to the beginning of each output chunk.
|
|
61
|
+
*/
|
|
61
62
|
banner?: OutputOptions['banner'];
|
|
62
63
|
/**
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
* Code to append to the end of each output chunk.
|
|
65
|
+
*/
|
|
65
66
|
footer?: OutputOptions['footer'];
|
|
66
67
|
/**
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
* Code to prepend inside the wrapper function (after banner, before actual code).
|
|
69
|
+
*/
|
|
69
70
|
intro?: OutputOptions['intro'];
|
|
70
71
|
/**
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
* Code to append inside the wrapper function (after actual code, before footer).
|
|
73
|
+
*/
|
|
73
74
|
outro?: OutputOptions['outro'];
|
|
74
75
|
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
* Clean output directory before build.
|
|
77
|
+
*
|
|
78
|
+
* Defaults to `true`
|
|
79
|
+
*/
|
|
79
80
|
clean?: boolean;
|
|
80
81
|
/**
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
* The path to the tsconfig.json file.
|
|
83
|
+
*
|
|
84
|
+
* If set to `false`, the plugin will ignore any `tsconfig.json` file.
|
|
85
|
+
* You can still specify `compilerOptions` directly in the options.
|
|
86
|
+
*
|
|
87
|
+
* Defaults to `'tsconfig.json'`
|
|
88
|
+
*/
|
|
89
|
+
tsconfig?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Pass a raw `tsconfig.json` object directly to the plugin.
|
|
92
|
+
*
|
|
93
|
+
* @see https://www.typescriptlang.org/tsconfig
|
|
94
|
+
*/
|
|
95
|
+
tsconfigRaw?: Omit<TsConfigJson, 'compilerOptions'>;
|
|
96
|
+
/**
|
|
97
|
+
* Experimental configuration.
|
|
98
|
+
*/
|
|
83
99
|
experimental?: ExperimentalConfig;
|
|
84
100
|
}
|
|
85
101
|
interface ExperimentalConfig {
|
|
86
102
|
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
103
|
+
* Whether to use the tsgo compiler.
|
|
104
|
+
*
|
|
105
|
+
* To use this option, make sure `@typescript/native-preview` is installed as a dependency.
|
|
106
|
+
*/
|
|
91
107
|
tsgo?: boolean;
|
|
92
108
|
}
|
|
93
109
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import path from "path";
|
|
1
2
|
import { loadConfig } from "c12";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
import { VERSION, build } from "rolldown";
|
|
2
5
|
import { createDebug } from "obug";
|
|
3
6
|
import fs, { globSync } from "node:fs";
|
|
4
7
|
import * as pkg from "empathic/package";
|
|
5
|
-
import {
|
|
6
|
-
import path from "node:path";
|
|
8
|
+
import { assert } from "es-toolkit";
|
|
9
|
+
import path$1 from "node:path";
|
|
7
10
|
import { dts } from "rolldown-plugin-dts";
|
|
11
|
+
import { promisify } from "node:util";
|
|
12
|
+
import { brotliCompress, gzip } from "node:zlib";
|
|
8
13
|
|
|
9
14
|
//#region src/common.ts
|
|
10
15
|
const debug$3 = createDebug("tsnv:common");
|
|
@@ -62,19 +67,11 @@ const DEFAULT_CONFIG = {
|
|
|
62
67
|
clean: true
|
|
63
68
|
};
|
|
64
69
|
|
|
65
|
-
//#endregion
|
|
66
|
-
//#region ../../../.yarn/berry/cache/es-toolkit-npm-1.43.0-b8f13c51d9-10c0.zip/node_modules/es-toolkit/dist/util/invariant.mjs
|
|
67
|
-
function invariant(condition, message) {
|
|
68
|
-
if (condition) return;
|
|
69
|
-
if (typeof message === "string") throw new Error(message);
|
|
70
|
-
throw message;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
70
|
//#endregion
|
|
74
71
|
//#region src/context.ts
|
|
75
72
|
async function resolveContext(cwd) {
|
|
76
73
|
const packageJsonPath = pkg.up({ cwd });
|
|
77
|
-
|
|
74
|
+
assert(packageJsonPath, "could not find package.json");
|
|
78
75
|
const rawPackageJson = await fs.promises.readFile(packageJsonPath, "utf-8");
|
|
79
76
|
const packageJson = JSON.parse(rawPackageJson);
|
|
80
77
|
return {
|
|
@@ -92,9 +89,9 @@ function resolvePackageType(packageJson) {
|
|
|
92
89
|
|
|
93
90
|
//#endregion
|
|
94
91
|
//#region src/utils/path.ts
|
|
95
|
-
async function hasPlatformSpecificModule(id, importer, config
|
|
96
|
-
const specifiers = config
|
|
97
|
-
const resolveDir = path.dirname(importer);
|
|
92
|
+
async function hasPlatformSpecificModule(id, importer, config) {
|
|
93
|
+
const specifiers = config.specifiers;
|
|
94
|
+
const resolveDir = path$1.dirname(importer);
|
|
98
95
|
let fileList = hasPlatformSpecificModule.cache.get(resolveDir);
|
|
99
96
|
if (fileList == null) {
|
|
100
97
|
fileList = (await fs.promises.readdir(resolveDir, {
|
|
@@ -106,7 +103,7 @@ async function hasPlatformSpecificModule(id, importer, config$1) {
|
|
|
106
103
|
return specifiers.some((specifier) => fileList.includes(`${basenameWithoutExtension(id)}.${specifier}`));
|
|
107
104
|
}
|
|
108
105
|
function basenameWithoutExtension(id) {
|
|
109
|
-
return path.basename(id, path.extname(id));
|
|
106
|
+
return path$1.basename(id, path$1.extname(id));
|
|
110
107
|
}
|
|
111
108
|
hasPlatformSpecificModule.cache = /* @__PURE__ */ new Map();
|
|
112
109
|
/**
|
|
@@ -125,15 +122,15 @@ function isDts(filename) {
|
|
|
125
122
|
}
|
|
126
123
|
function removePlatformSpecificExtension(filename, extensions, specifiers) {
|
|
127
124
|
const extPattern = extensions.map((extension) => extension.replace(".", "")).join("|");
|
|
128
|
-
const regex =
|
|
125
|
+
const regex = new RegExp(`\\.(${specifiers.join("|")})\\.(${extPattern})$`);
|
|
129
126
|
return filename.replace(regex, ".$2");
|
|
130
127
|
}
|
|
131
|
-
function getUniquePlatformSpecificFiles(files
|
|
128
|
+
function getUniquePlatformSpecificFiles(files, extensions, specifiers) {
|
|
132
129
|
const extPattern = extensions.map((e) => e.replace(".", "")).join("|");
|
|
133
|
-
const regex =
|
|
130
|
+
const regex = new RegExp(`\\.(${specifiers.join("|")})\\.(${extPattern})$`);
|
|
134
131
|
const seen = /* @__PURE__ */ new Set();
|
|
135
132
|
const result = [];
|
|
136
|
-
for (const file of files
|
|
133
|
+
for (const file of files) {
|
|
137
134
|
const baseName = file.replace(regex, ".$2");
|
|
138
135
|
if (seen.has(baseName)) continue;
|
|
139
136
|
seen.add(baseName);
|
|
@@ -145,12 +142,14 @@ function getUniquePlatformSpecificFiles(files$1, extensions, specifiers) {
|
|
|
145
142
|
//#endregion
|
|
146
143
|
//#region src/rolldown/plugins/dts.ts
|
|
147
144
|
const debug$2 = createDebug("tsnv:dts");
|
|
148
|
-
function dts$1(config
|
|
149
|
-
if (!config
|
|
145
|
+
function dts$1(config) {
|
|
146
|
+
if (!config.dts) return null;
|
|
150
147
|
const dtsExtension = ["d"];
|
|
151
148
|
return [dts({
|
|
152
149
|
emitDtsOnly: true,
|
|
153
|
-
|
|
150
|
+
tsconfig: config.tsconfig,
|
|
151
|
+
tsconfigRaw: config.tsconfigRaw,
|
|
152
|
+
tsgo: config.experimental?.tsgo
|
|
154
153
|
}), {
|
|
155
154
|
name: "tsnv:dts-renamer",
|
|
156
155
|
outputOptions(options) {
|
|
@@ -158,7 +157,7 @@ function dts$1(config$1) {
|
|
|
158
157
|
...options,
|
|
159
158
|
entryFileNames(chunkInfo) {
|
|
160
159
|
if (chunkInfo.name.endsWith(".d")) {
|
|
161
|
-
const newChunkName = `${removePlatformSpecificExtension(chunkInfo.name, dtsExtension, config
|
|
160
|
+
const newChunkName = `${removePlatformSpecificExtension(chunkInfo.name, dtsExtension, config.specifiers)}.ts`;
|
|
162
161
|
debug$2(`renaming ${chunkInfo.name} to ${newChunkName}`);
|
|
163
162
|
return newChunkName;
|
|
164
163
|
} else return chunkInfo.name;
|
|
@@ -172,8 +171,8 @@ function dts$1(config$1) {
|
|
|
172
171
|
//#region src/rolldown/plugins/external.ts
|
|
173
172
|
const PLUGIN_NAME = "tsnv:external";
|
|
174
173
|
const debug$1 = createDebug(PLUGIN_NAME);
|
|
175
|
-
function external(context
|
|
176
|
-
const productionDependencies = Array.from(new Set([...Object.keys(context
|
|
174
|
+
function external(context) {
|
|
175
|
+
const productionDependencies = Array.from(new Set([...Object.keys(context.packageJson.dependencies ?? {}), ...Object.keys(context.packageJson.peerDependencies ?? {})]));
|
|
177
176
|
debug$1("production dependencies", productionDependencies);
|
|
178
177
|
return {
|
|
179
178
|
name: PLUGIN_NAME,
|
|
@@ -183,16 +182,16 @@ function external(context$1) {
|
|
|
183
182
|
id,
|
|
184
183
|
external: true
|
|
185
184
|
};
|
|
186
|
-
const extname = path.extname(id);
|
|
185
|
+
const extname = path$1.extname(id).slice(1);
|
|
187
186
|
if (extname) {
|
|
188
|
-
if (context
|
|
187
|
+
if (context.config.assetExtensions.includes(extname)) return {
|
|
189
188
|
id,
|
|
190
189
|
external: true
|
|
191
190
|
};
|
|
192
|
-
if (!context
|
|
191
|
+
if (!context.config.sourceExtensions.includes(extname)) throw new Error(`Unsupported file extension: ${extname}`);
|
|
193
192
|
}
|
|
194
193
|
const resolved = await this.resolve(id, importer, extraOptions);
|
|
195
|
-
if (resolved == null && await hasPlatformSpecificModule(id, importer, context
|
|
194
|
+
if (resolved == null && await hasPlatformSpecificModule(id, importer, context.config)) return {
|
|
196
195
|
id,
|
|
197
196
|
external: true,
|
|
198
197
|
moduleSideEffects: true
|
|
@@ -205,16 +204,77 @@ function isPackageImportSource(packageName, id) {
|
|
|
205
204
|
return id === packageName || id.startsWith(`${packageName}/`);
|
|
206
205
|
}
|
|
207
206
|
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/utils/fs.ts
|
|
209
|
+
const gzipAsync = promisify(gzip);
|
|
210
|
+
const brotliCompressAsync = promisify(brotliCompress);
|
|
211
|
+
function collectFiles(config) {
|
|
212
|
+
const files = globSync(`**/*.{${config.sourceExtensions.join(",")}}`, {
|
|
213
|
+
cwd: config.source,
|
|
214
|
+
exclude: (filename) => config.exclude.test(filename) || isDts(filename)
|
|
215
|
+
});
|
|
216
|
+
if (files.length === 0) throw new Error(`No files found in ${path$1.resolve(config.source)}`);
|
|
217
|
+
return files.map((file) => path$1.join(config.source, file));
|
|
218
|
+
}
|
|
219
|
+
async function calcSize(chunk) {
|
|
220
|
+
const content = chunk.type === "chunk" ? chunk.code : chunk.source;
|
|
221
|
+
const raw = Buffer.byteLength(content, "utf8");
|
|
222
|
+
const gzip = (await gzipAsync(content)).length;
|
|
223
|
+
return {
|
|
224
|
+
filename: chunk.fileName,
|
|
225
|
+
dts: chunk.fileName.endsWith(".d.ts"),
|
|
226
|
+
raw,
|
|
227
|
+
rawText: formatBytes(raw),
|
|
228
|
+
gzip,
|
|
229
|
+
gzipText: formatBytes(gzip)
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function formatBytes(bytes) {
|
|
233
|
+
return `${(bytes / 1e3).toFixed(2)} kB`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/rolldown/plugins/report.ts
|
|
238
|
+
const noop = (text) => text;
|
|
239
|
+
function report(options) {
|
|
240
|
+
const { cwd, format } = options;
|
|
241
|
+
const formatLabel = (() => {
|
|
242
|
+
switch (format) {
|
|
243
|
+
case "esm": return pc.blue(`[ESM]`);
|
|
244
|
+
case "cjs": return pc.yellow(`[CJS]`);
|
|
245
|
+
case "dts": return pc.green(`[DTS]`);
|
|
246
|
+
}
|
|
247
|
+
})();
|
|
248
|
+
return {
|
|
249
|
+
name: "tsnv:report",
|
|
250
|
+
async writeBundle(outputOptions, bundle) {
|
|
251
|
+
const outDir = path$1.relative(cwd, outputOptions.dir ? path$1.resolve(outputOptions.dir) : path$1.dirname(outputOptions.file));
|
|
252
|
+
const sizes = [];
|
|
253
|
+
for (const chunk of Object.values(bundle)) {
|
|
254
|
+
const size = await calcSize(chunk);
|
|
255
|
+
sizes.push(size);
|
|
256
|
+
}
|
|
257
|
+
let totalRaw = 0;
|
|
258
|
+
for (const size of sizes) totalRaw += size.raw;
|
|
259
|
+
for (const size of sizes) {
|
|
260
|
+
const filenameColor = size.dts ? pc.green : noop;
|
|
261
|
+
const filename = path$1.normalize(size.filename);
|
|
262
|
+
console.log(formatLabel, pc.dim(outDir + path$1.sep) + filenameColor(filename), pc.dim(size.rawText), pc.dim(`(gzip ${size.gzipText})`));
|
|
263
|
+
}
|
|
264
|
+
console.log(formatLabel, `${sizes.length} files, total: ${formatBytes(totalRaw)}`);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
208
269
|
//#endregion
|
|
209
270
|
//#region src/rolldown/build-options.ts
|
|
210
|
-
function resolveBuildOptions(context
|
|
271
|
+
function resolveBuildOptions(context, options) {
|
|
211
272
|
const pluginContext = {
|
|
212
|
-
...context
|
|
273
|
+
...context,
|
|
213
274
|
config: options.config
|
|
214
275
|
};
|
|
215
276
|
const baseOptions = {
|
|
216
277
|
input: options.files,
|
|
217
|
-
plugins: [external(pluginContext)],
|
|
218
278
|
output: {
|
|
219
279
|
banner: options.config.banner,
|
|
220
280
|
footer: options.config.footer,
|
|
@@ -234,9 +294,13 @@ function resolveBuildOptions(context$1, options) {
|
|
|
234
294
|
const resolvedBuildOptions = uniqueFormats.map((format) => {
|
|
235
295
|
return {
|
|
236
296
|
...baseOptions,
|
|
297
|
+
plugins: [external(pluginContext), report({
|
|
298
|
+
cwd: options.cwd,
|
|
299
|
+
format
|
|
300
|
+
})],
|
|
237
301
|
output: {
|
|
238
302
|
...baseOptions.output,
|
|
239
|
-
dir: isSingleFormat ? options.config.outDir : path.join(options.config.outDir, format),
|
|
303
|
+
dir: isSingleFormat ? options.config.outDir : path$1.join(options.config.outDir, format),
|
|
240
304
|
cleanDir: options.config.clean,
|
|
241
305
|
format,
|
|
242
306
|
entryFileNames: filename,
|
|
@@ -247,11 +311,18 @@ function resolveBuildOptions(context$1, options) {
|
|
|
247
311
|
if (options.config.dts) resolvedBuildOptions.push({
|
|
248
312
|
...baseOptions,
|
|
249
313
|
input: getUniquePlatformSpecificFiles(options.files, options.config.sourceExtensions, options.config.specifiers),
|
|
250
|
-
plugins: [
|
|
314
|
+
plugins: [
|
|
315
|
+
external(pluginContext),
|
|
316
|
+
report({
|
|
317
|
+
cwd: options.cwd,
|
|
318
|
+
format: "dts"
|
|
319
|
+
}),
|
|
320
|
+
dts$1(options.config)
|
|
321
|
+
],
|
|
251
322
|
output: {
|
|
252
323
|
...baseOptions.output,
|
|
253
324
|
cleanDir: options.config.clean,
|
|
254
|
-
dir: path.join(options.config.outDir, "types"),
|
|
325
|
+
dir: path$1.join(options.config.outDir, "types"),
|
|
255
326
|
format: "esm",
|
|
256
327
|
entryFileNames: filename,
|
|
257
328
|
chunkFileNames: filename
|
|
@@ -263,38 +334,47 @@ function resolveBuildOptions(context$1, options) {
|
|
|
263
334
|
//#endregion
|
|
264
335
|
//#region src/rolldown/index.ts
|
|
265
336
|
const debug = createDebug("tsnv:build");
|
|
266
|
-
async function build$1(context
|
|
267
|
-
const buildOptions = resolveBuildOptions(context
|
|
337
|
+
async function build$1(context, options) {
|
|
338
|
+
const buildOptions = resolveBuildOptions(context, options);
|
|
268
339
|
debug("Resolved build options", buildOptions);
|
|
269
340
|
for (const buildOption of buildOptions) await build(buildOption);
|
|
270
341
|
}
|
|
271
342
|
|
|
272
343
|
//#endregion
|
|
273
|
-
//#region src/
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
344
|
+
//#region src/index.ts
|
|
345
|
+
const version = `v0.0.0-dev.20260201114010`;
|
|
346
|
+
async function main() {
|
|
347
|
+
console.log(`tsnv ${pc.dim(version)} powered by rolldown ${pc.dim(VERSION)}`);
|
|
348
|
+
debug$3("Loading config...");
|
|
349
|
+
const cwd = process.cwd();
|
|
350
|
+
const { config, configFile } = await loadConfig({
|
|
351
|
+
cwd,
|
|
352
|
+
configFile: "tsnv.config",
|
|
353
|
+
defaultConfig: DEFAULT_CONFIG
|
|
354
|
+
});
|
|
355
|
+
debug$3("Config loaded", config);
|
|
356
|
+
console.log(`Config File: ${pc.underline(configFile)}`);
|
|
357
|
+
console.log(`Source Path: ${pc.blue(path.resolve(config.source))}`);
|
|
358
|
+
const context = await resolveContext(process.cwd());
|
|
359
|
+
debug$3("Resolved context", context);
|
|
360
|
+
const files = await collectFiles(config);
|
|
361
|
+
console.log(`Collected files: ${pc.dim(files.length)}`);
|
|
362
|
+
console.log("Build start");
|
|
363
|
+
const startedAt = performance.now();
|
|
364
|
+
await build$1(context, {
|
|
365
|
+
cwd,
|
|
366
|
+
files,
|
|
367
|
+
config
|
|
278
368
|
});
|
|
279
|
-
|
|
280
|
-
|
|
369
|
+
const endedAt = performance.now();
|
|
370
|
+
const duration = `${Math.floor(endedAt - startedAt)}ms`;
|
|
371
|
+
console.log(`Build completed in ${pc.green(duration)}`);
|
|
281
372
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
configFile: "tsnv.config",
|
|
288
|
-
defaultConfig: DEFAULT_CONFIG
|
|
289
|
-
});
|
|
290
|
-
debug$3("Config loaded", config);
|
|
291
|
-
const context = await resolveContext(process.cwd());
|
|
292
|
-
debug$3("Resolved context", context);
|
|
293
|
-
const files = await collectFiles(config);
|
|
294
|
-
debug$3("Collected files", files);
|
|
295
|
-
await build$1(context, {
|
|
296
|
-
files,
|
|
297
|
-
config
|
|
373
|
+
await main().catch((reason) => {
|
|
374
|
+
console.error(pc.red(`Build failed`));
|
|
375
|
+
console.error();
|
|
376
|
+
console.error(reason);
|
|
377
|
+
process.exit(1);
|
|
298
378
|
});
|
|
299
379
|
|
|
300
380
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsnv",
|
|
3
|
-
"version": "0.0.0-dev.
|
|
3
|
+
"version": "0.0.0-dev.20260201114010",
|
|
4
4
|
"description": "Modern build toolkit for React Native libraries",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Geunhyeok Lee <dev.ghlee@gmail.com>",
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
"directory": "."
|
|
11
11
|
},
|
|
12
12
|
"bin": "bin.js",
|
|
13
|
+
"workspaces": [
|
|
14
|
+
"example"
|
|
15
|
+
],
|
|
13
16
|
"files": [
|
|
14
17
|
"bin.js",
|
|
15
18
|
"dist"
|
|
@@ -40,6 +43,7 @@
|
|
|
40
43
|
"fmt": "oxfmt",
|
|
41
44
|
"test": "vitest --run",
|
|
42
45
|
"test:e2e": "vitest --run --config vitest.e2e.config.ts",
|
|
46
|
+
"test:all": "yarn test && yarn test:e2e",
|
|
43
47
|
"build": "tsdown",
|
|
44
48
|
"scripts:version": ".scripts/version.sh",
|
|
45
49
|
"scripts:publish": ".scripts/publish.sh"
|
|
@@ -47,19 +51,20 @@
|
|
|
47
51
|
"dependencies": {
|
|
48
52
|
"c12": "^3.3.3",
|
|
49
53
|
"empathic": "^2.0.0",
|
|
54
|
+
"es-toolkit": "^1.44.0",
|
|
55
|
+
"get-tsconfig": "^4.13.1",
|
|
50
56
|
"obug": "^2.1.1",
|
|
51
|
-
"
|
|
52
|
-
"rolldown
|
|
53
|
-
"
|
|
57
|
+
"picocolors": "^1.1.1",
|
|
58
|
+
"rolldown": "1.0.0-rc.2",
|
|
59
|
+
"rolldown-plugin-dts": "0.21.8"
|
|
54
60
|
},
|
|
55
61
|
"devDependencies": {
|
|
56
62
|
"@changesets/cli": "^2.29.8",
|
|
57
63
|
"@types/node": "^24.10.1",
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"oxlint": "^
|
|
61
|
-
"
|
|
62
|
-
"picocolors": "^1.1.1",
|
|
64
|
+
"oxfmt": "^0.27.0",
|
|
65
|
+
"oxlint": "^1.42.0",
|
|
66
|
+
"oxlint-tsgolint": "^0.11.4",
|
|
67
|
+
"tsdown": "^0.20.1",
|
|
63
68
|
"tsx": "^4.21.0",
|
|
64
69
|
"typescript": "^5.9.3",
|
|
65
70
|
"vitest": "^4.0.17",
|