Skip to content

Commit

Permalink
feat: add support for user import maps (#6)
Browse files Browse the repository at this point in the history
* refactor: rename variable

* feat: add support for user import maps
  • Loading branch information
eduardoboucas committed Mar 15, 2022
1 parent c5fa05e commit 9067956
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 14 deletions.
16 changes: 10 additions & 6 deletions src/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { Declaration } from './declaration.js'
import { getESZIPBundler } from './eszip.js'
import { findHandlers } from './finder.js'
import { Handler } from './handler.js'
import { ImportMap } from './import_map.js'
import { ImportMap, ImportMapFile } from './import_map.js'
import { generateManifest } from './manifest.js'
import { getFileHash } from './utils/sha256.js'

Expand All @@ -21,7 +21,8 @@ interface HandlerLine {
}

interface BundleOptions {
importMapPath?: string
distImportMapPath?: string
importMaps?: ImportMapFile[]
onAfterDownload?: LifecycleHook
onBeforeDownload?: LifecycleHook
}
Expand All @@ -38,7 +39,7 @@ const bundle = async (
sourceDirectories: string[],
distDirectory: string,
declarations: Declaration[] = [],
{ importMapPath, onAfterDownload, onBeforeDownload }: BundleOptions = {},
{ distImportMapPath, importMaps, onAfterDownload, onBeforeDownload }: BundleOptions = {},
) => {
const deno = new DenoBridge({
onAfterDownload,
Expand All @@ -49,7 +50,10 @@ const bundle = async (
// compute until we run the bundle process. For now, we'll use a random ID
// to create the bundle artifacts and rename them later.
const buildID = uuidv4()
const importMap = new ImportMap()

// Creating an ImportMap instance with any import maps supplied by the user,
// if any.
const importMap = new ImportMap(importMaps)
const { handlers, preBundlePath } = await preBundle(sourceDirectories, distDirectory, `${buildID}-pre.js`)
const bundleAlternates: BundleAlternate[] = ['js']
const bundleOps = [bundleJS({ buildID, deno, distDirectory, importMap, preBundlePath })]
Expand All @@ -70,8 +74,8 @@ const bundle = async (

await fs.unlink(preBundlePath)

if (importMapPath) {
await importMap.writeToFile(importMapPath)
if (distImportMapPath) {
await importMap.writeToFile(distImportMapPath)
}

return { handlers, manifest, preBundlePath }
Expand Down
14 changes: 12 additions & 2 deletions src/import_map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,20 @@ const DEFAULT_IMPORTS = {
'netlify:edge': 'https://dinosaurs:are-the-future!@edge-bootstrap.netlify.app/v1/index.ts',
}

interface ImportMapFile {
imports: Record<string, string>
scopes?: Record<string, string>
}

class ImportMap {
imports: Record<string, string>

constructor() {
this.imports = DEFAULT_IMPORTS
constructor(input: ImportMapFile[] = []) {
const inputImports = input.reduce((acc, { imports }) => ({ ...acc, ...imports }), {})

// `DEFAULT_IMPORTS` must come last because we want our internal imports to
// take precedence.
this.imports = { ...inputImports, ...DEFAULT_IMPORTS }
}

getContents() {
Expand All @@ -37,3 +46,4 @@ class ImportMap {
}

export { ImportMap }
export type { ImportMapFile }
15 changes: 9 additions & 6 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ import { tmpName } from 'tmp-promise'
import { DenoBridge, LifecycleHook } from './bridge.js'
import { preBundle } from './bundler.js'
import type { Declaration } from './declaration.js'
import { ImportMap } from './import_map.js'
import { ImportMap, ImportMapFile } from './import_map.js'
import { generateManifest } from './manifest.js'

interface ServeOptions {
importMapPath?: string
distImportMapPath?: string
importMaps?: ImportMapFile[]
onAfterDownload?: LifecycleHook
onBeforeDownload?: LifecycleHook
}

const serve = async (
port: number,
sourceDirectories: string[],
{ importMapPath, onAfterDownload, onBeforeDownload }: ServeOptions = {},
{ distImportMapPath, importMaps, onAfterDownload, onBeforeDownload }: ServeOptions = {},
) => {
const deno = new DenoBridge({
onAfterDownload,
Expand All @@ -29,13 +30,15 @@ const serve = async (
// Wait for the binary to be downloaded if needed.
await deno.getBinaryPath()

const importMap = new ImportMap()
// Creating an ImportMap instance with any import maps supplied by the user,
// if any.
const importMap = new ImportMap(importMaps)
const flags = ['-A', '--unstable', '--no-clear-screen', '--watch', `--import-map=${importMap.toDataURL()}`]

deno.run(['run', ...flags, preBundlePath, port.toString()], { wait: false })

if (importMapPath) {
await importMap.writeToFile(importMapPath)
if (distImportMapPath) {
await importMap.writeToFile(distImportMapPath)
}

return {
Expand Down

0 comments on commit 9067956

Please sign in to comment.