@remix-run/assets 0.2.0 → 0.3.0

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.
@@ -2,10 +2,13 @@ import * as fs from 'node:fs'
2
2
  import * as fsp from 'node:fs/promises'
3
3
  import * as path from 'node:path'
4
4
  import { getTsconfig } from 'get-tsconfig'
5
+ import MagicString from 'magic-string'
5
6
  import { minify } from 'oxc-minify'
7
+ import { parseSync, visitorKeys } from 'oxc-parser'
6
8
  import { transform as oxcTransform } from 'oxc-transform'
7
9
  import { init as esModuleLexerInit, parse as esModuleLexer } from 'es-module-lexer'
8
10
  import type { Cache, TsConfigJsonResolved } from 'get-tsconfig'
11
+ import type { Node, Program } from 'oxc-parser'
9
12
  import type { TransformOptions as OxcTransformOptions } from 'oxc-transform'
10
13
 
11
14
  import { isCommonJS, mayContainCommonJSModuleGlobals } from './cjs-check.ts'
@@ -15,6 +18,11 @@ import {
15
18
  } from '../compilation-error.ts'
16
19
  import type { AssetServerCompilationError } from '../compilation-error.ts'
17
20
  import { generateFingerprint } from '../fingerprint.ts'
21
+ import {
22
+ maskAuthoredInjectedPackageSpecifier,
23
+ mayContainInjectedPackageSpecifier,
24
+ restoreAuthoredInjectedPackageSpecifier,
25
+ } from '../injected-packages.ts'
18
26
  import type { ModuleRecord, ModuleTracking } from '../module-store.ts'
19
27
  import { normalizeFilePath } from '../paths.ts'
20
28
  import type { CompiledRoutes } from '../routes.ts'
@@ -205,7 +213,7 @@ export async function transformModule(
205
213
  })
206
214
 
207
215
  analysis.unresolvedImports = analysis.unresolvedImports.filter(
208
- (unresolved) => !args.externalSet.has(unresolved.specifier),
216
+ (unresolved) => !args.externalSet.has(getDisplayImportSpecifier(unresolved.specifier)),
209
217
  )
210
218
 
211
219
  if (mayContainCommonJSModuleGlobals(sourceText) && isCommonJS(analysis.rawCode)) {
@@ -306,11 +314,12 @@ async function analyzeModuleSource(
306
314
  target?: ResolvedScriptTarget
307
315
  },
308
316
  ) {
317
+ let maskedSourceText = maskAuthoredInjectedPackageImports(sourceText, resolvedPath)
309
318
  let transformResult: { code: string; errors?: Array<{ message?: string }>; map?: unknown }
310
319
  try {
311
320
  transformResult = await oxcTransform(
312
321
  resolvedPath,
313
- sourceText,
322
+ maskedSourceText,
314
323
  getTransformOptions(resolvedPath, transformOptions, options),
315
324
  )
316
325
  assertNoCompilerErrors(transformResult.errors, resolvedPath, 'transform')
@@ -541,6 +550,99 @@ async function getUnresolvedImportsFromLexer(rawCode: string): Promise<Unresolve
541
550
  return unresolvedImports
542
551
  }
543
552
 
553
+ function getDisplayImportSpecifier(specifier: string): string {
554
+ return restoreAuthoredInjectedPackageSpecifier(specifier) ?? specifier
555
+ }
556
+
557
+ function maskAuthoredInjectedPackageImports(sourceText: string, resolvedPath: string): string {
558
+ if (!mayContainInjectedPackageSpecifier(sourceText)) {
559
+ return sourceText
560
+ }
561
+
562
+ let parseResult = parseSync(resolvedPath, sourceText, {
563
+ lang: getSourceLanguageForPath(resolvedPath),
564
+ sourceType: 'module',
565
+ })
566
+ if (parseResult.errors.length > 0) {
567
+ return sourceText
568
+ }
569
+
570
+ let replacements: Array<{ end: number; specifier: string; start: number }> = []
571
+
572
+ walkAst(parseResult.program, (node) => {
573
+ if (
574
+ node.type !== 'ImportDeclaration' &&
575
+ node.type !== 'ExportAllDeclaration' &&
576
+ node.type !== 'ExportNamedDeclaration' &&
577
+ node.type !== 'ImportExpression'
578
+ ) {
579
+ return
580
+ }
581
+
582
+ let source = 'source' in node ? node.source : null
583
+ if (!isStringLiteralNode(source)) return
584
+
585
+ let maskedSpecifier = maskAuthoredInjectedPackageSpecifier(source.value)
586
+ if (maskedSpecifier == null) return
587
+
588
+ replacements.push({
589
+ end: source.end - 1,
590
+ specifier: maskedSpecifier,
591
+ start: source.start + 1,
592
+ })
593
+ })
594
+
595
+ if (replacements.length === 0) return sourceText
596
+
597
+ let rewrittenSource = new MagicString(sourceText)
598
+ for (let replacement of replacements) {
599
+ rewrittenSource.overwrite(replacement.start, replacement.end, replacement.specifier)
600
+ }
601
+
602
+ return rewrittenSource.toString()
603
+ }
604
+
605
+ function walkAst(node: Program | Node, visit: (node: Program | Node) => void): void {
606
+ visit(node)
607
+
608
+ let keys = visitorKeys[node.type]
609
+ if (!keys) return
610
+
611
+ let walkableNode = node as unknown as Record<string, unknown>
612
+ for (let key of keys) {
613
+ let value = walkableNode[key]
614
+ if (Array.isArray(value)) {
615
+ for (let child of value) {
616
+ if (isAstNode(child)) {
617
+ walkAst(child, visit)
618
+ }
619
+ }
620
+ continue
621
+ }
622
+
623
+ if (isAstNode(value)) {
624
+ walkAst(value, visit)
625
+ }
626
+ }
627
+ }
628
+
629
+ function isAstNode(value: unknown): value is Node {
630
+ return typeof value === 'object' && value !== null && 'type' in value
631
+ }
632
+
633
+ function isStringLiteralNode(node: Node | null | undefined): node is Node & {
634
+ end: number
635
+ start: number
636
+ value: string
637
+ } {
638
+ return (
639
+ node?.type === 'Literal' &&
640
+ typeof node.start === 'number' &&
641
+ typeof node.end === 'number' &&
642
+ typeof node.value === 'string'
643
+ )
644
+ }
645
+
544
646
  function getStaticImportSpecifier(
545
647
  source: string,
546
648
  imported: ReturnType<typeof esModuleLexer>[0][number],