@steambrew/ttc 3.2.2 → 3.2.3

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/bun.lock CHANGED
@@ -32,6 +32,7 @@
32
32
  "sass": "^1.89.1",
33
33
  "terser": "^5.43.1",
34
34
  "tslib": "^2.8.1",
35
+ "typescript": ">=5.0.0",
35
36
  },
36
37
  "devDependencies": {
37
38
  "@types/babel__traverse": "^7.20.7",
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ import replace from '@rollup/plugin-replace';
12
12
  import terser from '@rollup/plugin-terser';
13
13
  import typescript from '@rollup/plugin-typescript';
14
14
  import esbuild from 'rollup-plugin-esbuild';
15
+ import ts from 'typescript';
15
16
  import url from '@rollup/plugin-url';
16
17
  import nodePolyfills from 'rollup-plugin-polyfill-node';
17
18
  import { watch, rollup } from 'rollup';
@@ -55,7 +56,7 @@ const Logger = {
55
56
  if (buildType === 'dev')
56
57
  meta.push('no type checking');
57
58
  if (sysfsCount)
58
- meta.push(`${sysfsCount} constSysfsExpr`);
59
+ meta.push(`${sysfsCount} bundled file${sysfsCount > 1 ? 's' : ''}`);
59
60
  if (envCount)
60
61
  meta.push(`${envCount} env var${envCount > 1 ? 's' : ''}`);
61
62
  console.log(`${chalk.green('Finished')} ${buildType} in ${elapsed} ` + chalk.dim('(' + meta.join(', ') + ')'));
@@ -605,99 +606,16 @@ function stripPluginPrefix(message) {
605
606
  }
606
607
  class BuildFailedError extends Error {
607
608
  }
608
- /**
609
- * tsconfig.json files use JSONC, not regular JSON.
610
- * JSONC supports comments and trailing commas, while JSON does not.
611
- * This function sanitizes JSONC into JSON.parse()-able content.
612
- *
613
- * @param text input text
614
- * @returns object
615
- */
616
- function parseJsonc(text) {
617
- let out = '';
618
- let i = 0;
619
- const n = text.length;
620
- while (i < n) {
621
- const ch = text[i];
622
- if (ch === '"') {
623
- out += ch;
624
- i++;
625
- while (i < n) {
626
- const c = text[i];
627
- out += c;
628
- if (c === '\\') {
629
- i++;
630
- if (i < n) {
631
- out += text[i];
632
- i++;
633
- }
634
- }
635
- else if (c === '"') {
636
- i++;
637
- break;
638
- }
639
- else
640
- i++;
641
- }
642
- }
643
- else if (ch === '/' && i + 1 < n && text[i + 1] === '/') {
644
- i += 2;
645
- while (i < n && text[i] !== '\n')
646
- i++;
647
- }
648
- else if (ch === '/' && i + 1 < n && text[i + 1] === '*') {
649
- i += 2;
650
- while (i < n - 1 && !(text[i] === '*' && text[i + 1] === '/'))
651
- i++;
652
- i += 2;
653
- }
654
- else if (ch === ',') {
655
- let j = i + 1;
656
- while (j < n && (text[j] === ' ' || text[j] === '\t' || text[j] === '\n' || text[j] === '\r'))
657
- j++;
658
- if (j < n && (text[j] === '}' || text[j] === ']')) {
659
- i++;
660
- }
661
- else {
662
- out += ch;
663
- i++;
664
- }
665
- }
666
- else {
667
- out += ch;
668
- i++;
669
- }
670
- }
671
- return JSON.parse(out);
672
- }
673
609
  function tsconfigPathsPlugin(tsconfigPath) {
674
- function readConfig(cfgPath) {
675
- const dir = path.dirname(path.resolve(cfgPath));
676
- let raw;
677
- try {
678
- raw = parseJsonc(fs.readFileSync(cfgPath, 'utf8'));
679
- }
680
- catch {
681
- return { baseUrl: null, entries: [] };
682
- }
683
- let parentResult = { baseUrl: null, entries: [] };
684
- if (raw.extends) {
685
- const ext = raw.extends;
686
- const parentPath = path.resolve(dir, ext.endsWith('.json') ? ext : `${ext}.json`);
687
- parentResult = readConfig(parentPath);
688
- }
689
- const opts = raw.compilerOptions ?? {};
690
- const baseUrl = opts.baseUrl ? path.resolve(dir, opts.baseUrl) : parentResult.baseUrl;
691
- const ownEntries = Object.entries(opts.paths ?? {}).map(([pattern, targets]) => ({
692
- pattern,
693
- targets: targets,
694
- configDir: dir,
695
- }));
696
- const ownPatterns = new Set(ownEntries.map((e) => e.pattern));
697
- const parentEntries = parentResult.entries.filter((e) => !ownPatterns.has(e.pattern));
698
- return { baseUrl, entries: [...ownEntries, ...parentEntries] };
699
- }
700
- const { baseUrl, entries } = readConfig(tsconfigPath);
610
+ const absPath = path.resolve(tsconfigPath);
611
+ const configDir = path.dirname(absPath);
612
+ const { config, error } = ts.readConfigFile(absPath, ts.sys.readFile);
613
+ if (error)
614
+ return { name: 'tsconfig-paths' };
615
+ const { options } = ts.parseJsonConfigFileContent(config, ts.sys, configDir);
616
+ const baseUrl = options.baseUrl ?? null;
617
+ const pathsBase = options.pathsBasePath ?? configDir;
618
+ const paths = options.paths ?? {};
701
619
  function resolveWithExtensions(base) {
702
620
  for (const ext of ['', '.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.tsx']) {
703
621
  if (fs.existsSync(base + ext))
@@ -708,7 +626,7 @@ function tsconfigPathsPlugin(tsconfigPath) {
708
626
  return {
709
627
  name: 'tsconfig-paths',
710
628
  async resolveId(source, importer) {
711
- for (const { pattern, targets, configDir } of entries) {
629
+ for (const [pattern, targets] of Object.entries(paths)) {
712
630
  if (!targets.length)
713
631
  continue;
714
632
  const isWild = pattern.endsWith('/*');
@@ -716,7 +634,7 @@ function tsconfigPathsPlugin(tsconfigPath) {
716
634
  const prefix = pattern.slice(0, -2);
717
635
  if (source === prefix || source.startsWith(prefix + '/')) {
718
636
  const rest = source.startsWith(prefix + '/') ? source.slice(prefix.length + 1) : '';
719
- const targetBase = path.resolve(configDir, targets[0].replace('*', rest));
637
+ const targetBase = path.resolve(pathsBase, targets[0].replace('*', rest));
720
638
  const resolved = resolveWithExtensions(targetBase);
721
639
  if (resolved) {
722
640
  const result = await this.resolve(resolved, importer, { skipSelf: true });
@@ -726,7 +644,7 @@ function tsconfigPathsPlugin(tsconfigPath) {
726
644
  }
727
645
  }
728
646
  else if (source === pattern) {
729
- const targetBase = path.resolve(configDir, targets[0]);
647
+ const targetBase = path.resolve(pathsBase, targets[0]);
730
648
  const resolved = resolveWithExtensions(targetBase);
731
649
  if (resolved) {
732
650
  const result = await this.resolve(resolved, importer, { skipSelf: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steambrew/ttc",
3
- "version": "3.2.2",
3
+ "version": "3.2.3",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -32,6 +32,7 @@
32
32
  "@rollup/plugin-replace": "^6.0.2",
33
33
  "@rollup/plugin-terser": "^0.4.4",
34
34
  "@rollup/plugin-typescript": "^12.1.2",
35
+ "typescript": ">=5.0.0",
35
36
  "@rollup/plugin-url": "^8.0.2",
36
37
  "@rollup/pluginutils": "^5.1.4",
37
38
  "chalk": "^5.4.1",
package/src/logger.ts CHANGED
@@ -3,9 +3,7 @@ import { readFileSync } from 'fs';
3
3
  import path, { dirname } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
5
 
6
- const version: string = JSON.parse(
7
- readFileSync(path.resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf8'),
8
- ).version;
6
+ const version: string = JSON.parse(readFileSync(path.resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf8')).version;
9
7
 
10
8
  interface DoneOptions {
11
9
  elapsedMs: number;
@@ -40,7 +38,7 @@ const Logger = {
40
38
  const elapsed = `${(elapsedMs / 1000).toFixed(2)}s`;
41
39
  const meta: string[] = [`ttc v${version}`];
42
40
  if (buildType === 'dev') meta.push('no type checking');
43
- if (sysfsCount) meta.push(`${sysfsCount} constSysfsExpr`);
41
+ if (sysfsCount) meta.push(`${sysfsCount} bundled file${sysfsCount > 1 ? 's' : ''}`);
44
42
  if (envCount) meta.push(`${envCount} env var${envCount > 1 ? 's' : ''}`);
45
43
  console.log(`${chalk.green('Finished')} ${buildType} in ${elapsed} ` + chalk.dim('(' + meta.join(', ') + ')'));
46
44
  },
package/src/transpiler.ts CHANGED
@@ -6,6 +6,7 @@ import replace from '@rollup/plugin-replace';
6
6
  import terser from '@rollup/plugin-terser';
7
7
  import typescript from '@rollup/plugin-typescript';
8
8
  import esbuild from 'rollup-plugin-esbuild';
9
+ import ts from 'typescript';
9
10
  import url from '@rollup/plugin-url';
10
11
  import nodePolyfills from 'rollup-plugin-polyfill-node';
11
12
  import chalk from 'chalk';
@@ -137,100 +138,17 @@ function stripPluginPrefix(message: string): string {
137
138
 
138
139
  class BuildFailedError extends Error {}
139
140
 
140
- interface PathEntry {
141
- pattern: string;
142
- targets: string[];
143
- configDir: string;
144
- }
145
-
146
- /**
147
- * tsconfig.json files use JSONC, not regular JSON.
148
- * JSONC supports comments and trailing commas, while JSON does not.
149
- * This function sanitizes JSONC into JSON.parse()-able content.
150
- *
151
- * @param text input text
152
- * @returns object
153
- */
154
- function parseJsonc(text: string): any {
155
- let out = '';
156
- let i = 0;
157
- const n = text.length;
158
- while (i < n) {
159
- const ch = text[i];
160
- if (ch === '"') {
161
- out += ch;
162
- i++;
163
- while (i < n) {
164
- const c = text[i];
165
- out += c;
166
- if (c === '\\') {
167
- i++;
168
- if (i < n) {
169
- out += text[i];
170
- i++;
171
- }
172
- } else if (c === '"') {
173
- i++;
174
- break;
175
- } else i++;
176
- }
177
- } else if (ch === '/' && i + 1 < n && text[i + 1] === '/') {
178
- i += 2;
179
- while (i < n && text[i] !== '\n') i++;
180
- } else if (ch === '/' && i + 1 < n && text[i + 1] === '*') {
181
- i += 2;
182
- while (i < n - 1 && !(text[i] === '*' && text[i + 1] === '/')) i++;
183
- i += 2;
184
- } else if (ch === ',') {
185
- let j = i + 1;
186
- while (j < n && (text[j] === ' ' || text[j] === '\t' || text[j] === '\n' || text[j] === '\r')) j++;
187
- if (j < n && (text[j] === '}' || text[j] === ']')) {
188
- i++;
189
- } else {
190
- out += ch;
191
- i++;
192
- }
193
- } else {
194
- out += ch;
195
- i++;
196
- }
197
- }
198
- return JSON.parse(out);
199
- }
200
-
201
141
  function tsconfigPathsPlugin(tsconfigPath: string): InputPluginOption {
202
- function readConfig(cfgPath: string): { baseUrl: string | null; entries: PathEntry[] } {
203
- const dir = path.dirname(path.resolve(cfgPath));
204
- let raw: any;
205
- try {
206
- raw = parseJsonc(fs.readFileSync(cfgPath, 'utf8'));
207
- } catch {
208
- return { baseUrl: null, entries: [] };
209
- }
210
-
211
- let parentResult: { baseUrl: string | null; entries: PathEntry[] } = { baseUrl: null, entries: [] };
212
- if (raw.extends) {
213
- const ext = raw.extends as string;
214
- const parentPath = path.resolve(dir, ext.endsWith('.json') ? ext : `${ext}.json`);
215
- parentResult = readConfig(parentPath);
216
- }
142
+ const absPath = path.resolve(tsconfigPath);
143
+ const configDir = path.dirname(absPath);
217
144
 
218
- const opts = raw.compilerOptions ?? {};
219
- const baseUrl = opts.baseUrl ? path.resolve(dir, opts.baseUrl as string) : parentResult.baseUrl;
220
-
221
- const ownEntries: PathEntry[] = Object.entries(opts.paths ?? {}).map(([pattern, targets]) => ({
222
- pattern,
223
- targets: targets as string[],
224
- configDir: dir,
225
- }));
226
-
227
- const ownPatterns = new Set(ownEntries.map((e) => e.pattern));
228
- const parentEntries = parentResult.entries.filter((e) => !ownPatterns.has(e.pattern));
229
-
230
- return { baseUrl, entries: [...ownEntries, ...parentEntries] };
231
- }
145
+ const { config, error } = ts.readConfigFile(absPath, ts.sys.readFile);
146
+ if (error) return { name: 'tsconfig-paths' };
232
147
 
233
- const { baseUrl, entries } = readConfig(tsconfigPath);
148
+ const { options } = ts.parseJsonConfigFileContent(config, ts.sys, configDir);
149
+ const baseUrl = options.baseUrl ?? null;
150
+ const pathsBase = (options.pathsBasePath as string | undefined) ?? configDir;
151
+ const paths = options.paths ?? {};
234
152
 
235
153
  function resolveWithExtensions(base: string): string | null {
236
154
  for (const ext of ['', '.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.tsx']) {
@@ -242,14 +160,14 @@ function tsconfigPathsPlugin(tsconfigPath: string): InputPluginOption {
242
160
  return {
243
161
  name: 'tsconfig-paths',
244
162
  async resolveId(source: string, importer: string | undefined) {
245
- for (const { pattern, targets, configDir } of entries) {
163
+ for (const [pattern, targets] of Object.entries(paths)) {
246
164
  if (!targets.length) continue;
247
165
  const isWild = pattern.endsWith('/*');
248
166
  if (isWild) {
249
167
  const prefix = pattern.slice(0, -2);
250
168
  if (source === prefix || source.startsWith(prefix + '/')) {
251
169
  const rest = source.startsWith(prefix + '/') ? source.slice(prefix.length + 1) : '';
252
- const targetBase = path.resolve(configDir, targets[0].replace('*', rest));
170
+ const targetBase = path.resolve(pathsBase, targets[0].replace('*', rest));
253
171
  const resolved = resolveWithExtensions(targetBase);
254
172
  if (resolved) {
255
173
  const result = await this.resolve(resolved, importer, { skipSelf: true });
@@ -257,7 +175,7 @@ function tsconfigPathsPlugin(tsconfigPath: string): InputPluginOption {
257
175
  }
258
176
  }
259
177
  } else if (source === pattern) {
260
- const targetBase = path.resolve(configDir, targets[0]);
178
+ const targetBase = path.resolve(pathsBase, targets[0]);
261
179
  const resolved = resolveWithExtensions(targetBase);
262
180
  if (resolved) {
263
181
  const result = await this.resolve(resolved, importer, { skipSelf: true });