Skip to content

Commit

Permalink
feat: add support for import maps (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucacasonato authored Mar 22, 2022
1 parent a6b66f4 commit 163ba78
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 8 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ jobs:
project: happy-rat-64
root: examples
entrypoint: hello.ts
import-map: ./import_map.json
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ inputs:
entrypoint:
description: The path or URL to the entrypoint file
required: true
import-map:
description: The path or URL to an import map file
required: false
root:
description: The path to the directory containing the code and assets to upload
required: false
Expand Down
8 changes: 4 additions & 4 deletions action/deps.js
Original file line number Diff line number Diff line change
Expand Up @@ -2439,22 +2439,22 @@ new TextEncoder();
white: mod2.white,
gray: mod2.gray
});
async function parseEntrypoint(entrypoint, cwd) {
async function parseEntrypoint(entrypoint, root, diagnosticName = "entrypoint") {
let entrypointSpecifier;
try {
if (entrypoint.startsWith("https://") || entrypoint.startsWith("http://") || entrypoint.startsWith("file://")) {
entrypointSpecifier = new URL(entrypoint);
} else {
entrypointSpecifier = toFileUrl2(resolve2(cwd ?? Deno.cwd(), entrypoint));
entrypointSpecifier = toFileUrl2(resolve2(root ?? Deno.cwd(), entrypoint));
}
} catch (err) {
throw `Failed to parse entrypoint specifier '${entrypoint}': ${err.message}`;
throw `Failed to parse ${diagnosticName} specifier '${entrypoint}': ${err.message}`;
}
if (entrypointSpecifier.protocol == "file:") {
try {
await Deno.lstat(entrypointSpecifier);
} catch (err) {
throw `Failed to open entrypoint file at '${entrypointSpecifier}': ${err.message}`;
throw `Failed to open ${diagnosticName} file at '${entrypointSpecifier}': ${err.message}`;
}
}
return entrypointSpecifier;
Expand Down
18 changes: 17 additions & 1 deletion action/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const ORIGIN = process.env.DEPLOY_API_ENDPOINT ?? "https://dash.deno.com";
async function main() {
const projectId = core.getInput("project", { required: true });
const entrypoint = core.getInput("entrypoint", { required: true });
const importMap = core.getInput("import-map", {});
const cwd = resolve(process.cwd(), core.getInput("root", {}));

if (github.context.eventName === "pull_request") {
Expand Down Expand Up @@ -40,13 +41,27 @@ async function main() {
if (url.protocol === "file:") {
const path = fromFileUrl(url);
if (!path.startsWith(cwd)) {
throw "Entrypoint must be in the current working directory.";
throw "Entrypoint must be in the working directory (cwd, or specified root directory).";
}
const entrypoint = path.slice(cwd.length);
url = new URL(`file:///src${entrypoint}`);
}
core.info(`Entrypoint: ${url.href}`);

let importMapUrl = null;
if (importMap) {
importMapUrl = await parseEntrypoint(importMap, cwd, "import map");
if (importMapUrl.protocol === "file:") {
const path = fromFileUrl(importMapUrl);
if (!path.startsWith(cwd)) {
throw "Import map must be in the working directory (cwd, or specified root directory).";
}
const importMap = path.slice(cwd.length);
importMapUrl = new URL(`file:///src${importMap}`);
}
core.info(`Import map: ${importMapUrl.href}`);
}

core.debug(`Discovering assets in "${cwd}"`);
const assets = new Map();
const entries = await walk(cwd, cwd, assets, {
Expand Down Expand Up @@ -81,6 +96,7 @@ async function main() {

const req = {
url: url.href,
importMapUrl: importMapUrl?.href ?? null,
manifest,
event: github.context.payload,
};
Expand Down
1 change: 1 addition & 0 deletions deployctl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const args = parseArgs(Deno.args, {
"token",
"include",
"exclude",
"import-map",
],
default: {
static: true,
Expand Down
2 changes: 1 addition & 1 deletion examples/hello.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { serve } from "https://deno.land/std@0.114.0/http/server.ts";
import { serve } from "std/http/server.ts";

async function handler(_req: Request) {
const text = await Deno.readTextFile(new URL(import.meta.url));
Expand Down
5 changes: 5 additions & 0 deletions examples/import_map.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"imports": {
"std/": "https://deno.land/[email protected]/"
}
}
18 changes: 18 additions & 0 deletions src/subcommands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ USAGE:
OPTIONS:
--exclude=<PATTERNS> Exclude files that match this pattern
--include=<PATTERNS> Only upload files that match this pattern
--import-map=<FILE> Use import map file
-h, --help Prints help information
--no-static Don't include the files in the CWD as static files
--prod Create a production deployment (default is preview deployment)
Expand All @@ -43,6 +44,7 @@ export interface Args {
include?: string[];
token: string | null;
project: string | null;
importMap: string | null;
}

// deno-lint-ignore no-explicit-any
Expand All @@ -53,6 +55,7 @@ export default async function (rawArgs: Record<string, any>): Promise<void> {
prod: !!rawArgs.prod,
token: rawArgs.token ? String(rawArgs.token) : null,
project: rawArgs.project ? String(rawArgs.project) : null,
importMap: rawArgs["import-map"] ? String(rawArgs["import-map"]) : null,
exclude: rawArgs.exclude?.split(","),
include: rawArgs.include?.split(","),
};
Expand Down Expand Up @@ -83,6 +86,10 @@ export default async function (rawArgs: Record<string, any>): Promise<void> {

const opts = {
entrypoint: await parseEntrypoint(entrypoint).catch((e) => error(e)),
importMapUrl: args.importMap === null
? null
: await parseEntrypoint(args.importMap, undefined, "import map")
.catch((e) => error(e)),
static: args.static,
prod: args.prod,
token,
Expand All @@ -96,6 +103,7 @@ export default async function (rawArgs: Record<string, any>): Promise<void> {

interface DeployOpts {
entrypoint: URL;
importMapUrl: URL | null;
static: boolean;
prod: boolean;
exclude?: string[];
Expand Down Expand Up @@ -124,6 +132,15 @@ async function deploy(opts: DeployOpts): Promise<void> {
const entrypoint = path.slice(cwd.length);
url = new URL(`file:///src${entrypoint}`);
}
let importMapUrl = opts.importMapUrl;
if (importMapUrl && importMapUrl.protocol === "file:") {
const path = fromFileUrl(importMapUrl);
if (!path.startsWith(cwd)) {
error("Import map must be in the current working directory.");
}
const entrypoint = path.slice(cwd.length);
importMapUrl = new URL(`file:///src${entrypoint}`);
}

let uploadSpinner: Spinner | null = null;
const files = [];
Expand Down Expand Up @@ -169,6 +186,7 @@ async function deploy(opts: DeployOpts): Promise<void> {
let deploySpinner: Spinner | null = null;
const req = {
url: url.href,
importMapUrl: importMapUrl ? importMapUrl.href : null,
production: opts.prod,
manifest,
};
Expand Down
2 changes: 2 additions & 0 deletions src/utils/api_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ export type ManifestEntry =

export interface PushDeploymentRequest {
url: string;
importMapUrl: string | null;
production: boolean;
manifest?: { entries: Record<string, ManifestEntry> };
}

export interface GitHubActionsDeploymentRequest {
url: string;
importMapUrl: string | null;
manifest: { entries: Record<string, ManifestEntry> };
event?: unknown;
}
Expand Down
5 changes: 3 additions & 2 deletions src/utils/entrypoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { resolve, toFileUrl } from "../../deps.ts";
export async function parseEntrypoint(
entrypoint: string,
root?: string,
diagnosticName = "entrypoint",
): Promise<URL> {
let entrypointSpecifier: URL;
try {
Expand All @@ -19,14 +20,14 @@ export async function parseEntrypoint(
entrypointSpecifier = toFileUrl(resolve(root ?? Deno.cwd(), entrypoint));
}
} catch (err) {
throw `Failed to parse entrypoint specifier '${entrypoint}': ${err.message}`;
throw `Failed to parse ${diagnosticName} specifier '${entrypoint}': ${err.message}`;
}

if (entrypointSpecifier.protocol == "file:") {
try {
await Deno.lstat(entrypointSpecifier);
} catch (err) {
throw `Failed to open entrypoint file at '${entrypointSpecifier}': ${err.message}`;
throw `Failed to open ${diagnosticName} file at '${entrypointSpecifier}': ${err.message}`;
}
}

Expand Down

0 comments on commit 163ba78

Please sign in to comment.