Skip to content
This repository was archived by the owner on Jul 6, 2025. It is now read-only.

Commit ed82da4

Browse files
committed
Improve cli read/write permissions
1 parent fe871de commit ed82da4

File tree

10 files changed

+62
-89
lines changed

10 files changed

+62
-89
lines changed

cli.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { writeAll } from "https://deno.land/[email protected]/streams/conversion.ts";
44
import { basename, resolve } from "https://deno.land/[email protected]/path/mod.ts";
55
import { readImportMap } from "./server/config.ts";
66
import { parse } from "./lib/flags.ts";
7-
import { existsDir, findFile } from "./lib/fs.ts";
7+
import { findFile } from "./lib/fs.ts";
88
import log, { stripColor } from "./lib/log.ts";
99
import { serveDir } from "./lib/serve.ts";
1010
import util from "./lib/util.ts";
@@ -24,7 +24,7 @@ Docs: https://alephjs.org/docs
2424
Bugs: https://github.com/alephjs/aleph.js/issues
2525
2626
Usage:
27-
aleph <command> [...options]
27+
deno run -A https://deno.land/x/aleph/cli.ts <command> [...options]
2828
2929
Commands:
3030
${
@@ -83,16 +83,16 @@ async function main() {
8383
return;
8484
}
8585

86-
// get denoDir
86+
// get moudle cache directory
8787
const p = Deno.run({
8888
cmd: [Deno.execPath(), "info", "--json"],
8989
stdout: "piped",
9090
stderr: "null",
9191
});
9292
const output = (new TextDecoder()).decode(await p.output());
93-
const { denoDir } = JSON.parse(output);
94-
if (util.isFilledString(denoDir)) {
95-
Deno.env.set("DENO_DIR", denoDir);
93+
const { modulesCache } = JSON.parse(output);
94+
if (util.isFilledString(modulesCache)) {
95+
Deno.env.set("MODULES_CACHE_DIR", modulesCache);
9696
}
9797
p.close();
9898

@@ -106,13 +106,8 @@ async function main() {
106106
serveDir({ cwd: Deno.cwd(), port: 2020 });
107107
log.debug(`Proxy https://deno.land/x/aleph on http://localhost:2020`);
108108
} else {
109-
const workingDir = resolve(String(args[0] || "."));
110-
if (!(await existsDir(workingDir))) {
111-
log.fatal("No such directory:", workingDir);
112-
}
113-
runOptions.denoConfigFile = await findFile(workingDir, ["deno.jsonc", "deno.json", "tsconfig.json"]);
109+
runOptions.denoConfigFile = await findFile(["deno.jsonc", "deno.json", "tsconfig.json"]);
114110
runOptions.importMapFile = await findFile(
115-
workingDir,
116111
["import_map", "import-map", "importmap", "importMap"].map((name) => `${name}.json`),
117112
);
118113
if (runOptions.importMapFile) {
@@ -158,6 +153,9 @@ async function main() {
158153
}
159154
}
160155

156+
if (args.length > 0) {
157+
Deno.chdir(String(args[0]));
158+
}
161159
await run(command, runOptions);
162160
}
163161

@@ -170,14 +168,15 @@ type RunOptions = {
170168

171169
async function run(command: string, options: RunOptions) {
172170
const { version, isCanary, denoConfigFile, importMapFile } = options;
171+
const rwDirs = [".", Deno.env.get("MODULES_CACHE_DIR"), Deno.env.get("ALEPH_DEV_ROOT")].filter(Boolean);
173172
const cmd: string[] = [
174173
Deno.execPath(),
175174
"run",
176175
"--allow-env",
177176
"--allow-net",
178-
"--allow-read",
179-
"--allow-write",
180-
"--allow-run",
177+
"--allow-read=" + rwDirs.join(","),
178+
"--allow-write=" + rwDirs.join(","),
179+
"--allow-hrtime",
181180
"--location=http://localhost",
182181
"--no-check",
183182
];

commands/build.ts

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { basename, resolve } from "https://deno.land/[email protected]/path/mod.ts";
1+
import { basename } from "https://deno.land/[email protected]/path/mod.ts";
22
import { getFlag, parse } from "../lib/flags.ts";
3-
import { existsDir, findFile } from "../lib/fs.ts";
3+
import { findFile } from "../lib/fs.ts";
44
import { builtinModuleExts } from "../lib/helpers.ts";
55
import log, { blue } from "../lib/log.ts";
66
import util from "../lib/util.ts";
@@ -11,10 +11,7 @@ import { serveAppModules } from "../server/serve_modules.ts";
1111

1212
export const helpMessage = `
1313
Usage:
14-
aleph build <dir> [...options]
15-
16-
<dir> represents the directory of Aleph.js app,
17-
if the <dir> is empty, the current directory will be used.
14+
deno run -A https://deno.land/x/aleph/cli.ts build [...options]
1815
1916
Options:
2017
-P, --platform <platform> Set deploy platform [possible values: deno, cf-worker, vercel]
@@ -23,7 +20,7 @@ Options:
2320
`;
2421

2522
if (import.meta.main) {
26-
const { args, options } = parse();
23+
const { options } = parse();
2724

2825
let platform = getFlag(options, ["P", "platform"])?.toLowerCase() as BuildPlatform | undefined;
2926
if (platform) {
@@ -51,20 +48,12 @@ if (import.meta.main) {
5148
}
5249
}
5350

54-
const start = performance.now();
55-
56-
// check working dir
57-
const workingDir = resolve(String(args[0] || "."));
58-
if (!await existsDir(workingDir)) {
59-
log.fatal("No such directory:", workingDir);
60-
}
61-
Deno.chdir(workingDir);
62-
51+
// serve app modules
6352
const importMap = await loadImportMap();
6453
const moduleLoaders = await initModuleLoaders(importMap);
6554
serveAppModules(6060, { importMap, moduleLoaders });
6655

67-
let serverEntry = await findFile(workingDir, builtinModuleExts.map((ext) => `server.${ext}`));
56+
let serverEntry = await findFile(builtinModuleExts.map((ext) => `server.${ext}`));
6857
if (serverEntry) {
6958
await import(
7059
`http://localhost:${Deno.env.get("ALEPH_APP_MODULES_PORT")}/${basename(serverEntry)}?t=${Date.now().toString(16)}`
@@ -79,9 +68,11 @@ if (import.meta.main) {
7968
}
8069

8170
log.info(`Building for ${supportedPlatforms[platform]}...`);
82-
const { clientModules } = await build(workingDir, platform as unknown as "deno-deploy", serverEntry);
83-
log.info(`${clientModules.size} client modules built`);
8471

72+
const start = performance.now();
73+
const { clientModules } = await build(platform as unknown as "deno-deploy", serverEntry);
74+
75+
log.info(`${clientModules.size} client modules built`);
8576
log.info(`Done in ${(performance.now() - start)}ms`);
8677
Deno.exit(0);
8778
}

commands/dev.ts

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { basename, relative, resolve } from "https://deno.land/[email protected]/path/mod.ts";
1+
import { basename, relative } from "https://deno.land/[email protected]/path/mod.ts";
22
import { serve as stdServe, serveTls } from "https://deno.land/[email protected]/http/server.ts";
33
import mitt, { Emitter } from "https://esm.sh/[email protected]";
44
import { getFlag, parse, parsePortNumber } from "../lib/flags.ts";
5-
import { existsDir, findFile, watchFs } from "../lib/fs.ts";
5+
import { findFile, watchFs } from "../lib/fs.ts";
66
import { builtinModuleExts } from "../lib/helpers.ts";
77
import log, { blue } from "../lib/log.ts";
88
import util from "../lib/util.ts";
@@ -15,10 +15,7 @@ import type { AlephConfig } from "../server/types.ts";
1515

1616
export const helpMessage = `
1717
Usage:
18-
aleph dev <dir> [...options]
19-
20-
<dir> represents the directory of Aleph.js app,
21-
if the <dir> is empty, the current directory will be used.
18+
deno run -A https://deno.land/x/aleph/cli.ts dev [...options]
2219
2320
Options:
2421
-p, --port <port> A port number to start the Aleph.js app, default is 8080
@@ -90,16 +87,7 @@ const handleHMRSocket = (req: Request): Response => {
9087
};
9188

9289
if (import.meta.main) {
93-
const { args, options } = parse();
94-
95-
// check working dir
96-
const workingDir = resolve(String(args[0] || "."));
97-
if (!await existsDir(workingDir)) {
98-
log.fatal("No such directory:", workingDir);
99-
}
100-
Deno.chdir(workingDir);
101-
Deno.env.set("ALEPH_ENV", "development");
102-
90+
const { options } = parse();
10391
const port = parsePortNumber(getFlag(options, ["p", "port"], "8080"));
10492
const hostname = getFlag(options, ["hostname"]);
10593
const certFile = getFlag(options, ["tls-cert"]);
@@ -111,13 +99,18 @@ if (import.meta.main) {
11199
log.fatal("missing `--tls-key` option");
112100
}
113101

102+
// development mode
103+
Deno.env.set("ALEPH_ENV", "development");
104+
105+
// serve app modules
114106
const importMap = await loadImportMap();
115107
const moduleLoaders = await initModuleLoaders(importMap);
116108
serveAppModules(6060, { importMap, moduleLoaders });
117109

118110
log.info(`Watching files for changes...`);
119-
watchFs(workingDir, (kind, path) => {
120-
const specifier = "./" + relative(workingDir, path);
111+
const cwd = Deno.cwd();
112+
watchFs(cwd, (kind, path) => {
113+
const specifier = "./" + relative(cwd, path);
121114
const clientDependencyGraph: DependencyGraph | undefined = Reflect.get(globalThis, "clientDependencyGraph");
122115
const serverDependencyGraph: DependencyGraph | undefined = Reflect.get(globalThis, "serverDependencyGraph");
123116
if (kind === "remove") {
@@ -151,9 +144,9 @@ if (import.meta.main) {
151144

152145
const emitter = createEmitter();
153146
const [denoConfigFile, importMapFile, serverEntry] = await Promise.all([
154-
findFile(workingDir, ["deno.jsonc", "deno.json", "tsconfig.json"]),
155-
findFile(workingDir, ["import_map", "import-map", "importmap", "importMap"].map((v) => `${v}.json`)),
156-
findFile(workingDir, builtinModuleExts.map((ext) => `server.${ext}`)),
147+
findFile(["deno.jsonc", "deno.json", "tsconfig.json"]),
148+
findFile(["import_map", "import-map", "importmap", "importMap"].map((v) => `${v}.json`)),
149+
findFile(builtinModuleExts.map((ext) => `server.${ext}`)),
157150
]);
158151
const importServerHandler = async (): Promise<void> => {
159152
if (serverEntry) {

commands/init.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const versions = {
1818

1919
export const helpMessage = `
2020
Usage:
21-
aleph init <name> [...options]
21+
deno run -A https://deno.land/x/aleph/cli.ts init <name> [...options]
2222
2323
<name> represents the name of new app.
2424

commands/start.ts

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { basename, resolve } from "https://deno.land/[email protected]/path/mod.ts";
1+
import { basename } from "https://deno.land/[email protected]/path/mod.ts";
22
import { serve as stdServe, serveTls } from "https://deno.land/[email protected]/http/server.ts";
33
import { getFlag, parse, parsePortNumber } from "../lib/flags.ts";
4-
import { existsDir, findFile } from "../lib/fs.ts";
4+
import { findFile } from "../lib/fs.ts";
55
import { builtinModuleExts } from "../lib/helpers.ts";
66
import log, { blue } from "../lib/log.ts";
77
import { initModuleLoaders, loadImportMap } from "../server/config.ts";
@@ -11,10 +11,7 @@ import { serveAppModules } from "../server/serve_modules.ts";
1111

1212
export const helpMessage = `
1313
Usage:
14-
aleph start <dir> [...options]
15-
16-
<dir> represents the directory of Aleph.js app,
17-
if the <dir> is empty, the current directory will be used.
14+
deno run -A https://deno.land/x/aleph/cli.ts start [...options]
1815
1916
Options:
2017
-p, --port <port> A port number to start the aleph.js app, default is 8080
@@ -26,15 +23,7 @@ Options:
2623
`;
2724

2825
if (import.meta.main) {
29-
const { args, options } = parse();
30-
31-
// check working dir
32-
const workingDir = resolve(String(args[0] || "."));
33-
if (!await existsDir(workingDir)) {
34-
log.fatal("No such directory:", workingDir);
35-
}
36-
Deno.chdir(workingDir);
37-
26+
const { options } = parse();
3827
const port = parsePortNumber(getFlag(options, ["p", "port"], "8080"));
3928
const hostname = getFlag(options, ["hostname"]);
4029
const certFile = getFlag(options, ["tls-cert"]);
@@ -46,12 +35,13 @@ if (import.meta.main) {
4635
log.fatal("missing `--tls-key` option");
4736
}
4837

38+
// serve app modules
4939
const ac = new AbortController();
5040
const importMap = await loadImportMap();
5141
const moduleLoaders = await initModuleLoaders(importMap);
5242
serveAppModules(6060, { importMap, moduleLoaders, signal: ac.signal });
5343

54-
let serverEntry = await findFile(workingDir, builtinModuleExts.map((ext) => `server.${ext}`));
44+
let serverEntry = await findFile(builtinModuleExts.map((ext) => `server.${ext}`));
5545
if (serverEntry) {
5646
await import(
5747
`http://localhost:${Deno.env.get("ALEPH_APP_MODULES_PORT")}/${basename(serverEntry)}?t=${Date.now().toString(16)}`
@@ -65,13 +55,13 @@ if (import.meta.main) {
6555
}
6656

6757
log.info("Building...");
68-
const { clientModules } = await build(workingDir, "deno-deploy", serverEntry);
58+
const { clientModules } = await build("deno-deploy", serverEntry);
6959
log.info(`${clientModules.size} client modules built`);
7060

7161
// close the app modules server
7262
ac.abort();
7363

74-
await import(`file://${workingDir}/dist/server.js`);
64+
await import(`./dist/server.js`);
7565
log.info(`Server handler imported from ${blue("dist/server.js")}`);
7666

7767
const handler = (req: Request) => {

compiler/mod.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ async function checkWasmReady() {
3030
}
3131

3232
async function initWasm() {
33-
const denoDir = Deno.env.get("DENO_DIR");
34-
if (denoDir && !Deno.env.get("ALEPH_DEV")) {
33+
const mcdir = Deno.env.get("MODULES_CACHE_DIR");
34+
if (mcdir && !Deno.env.get("ALEPH_DEV")) {
3535
const pkgName = isCanary ? "aleph_canary" : "aleph";
36-
const cacheDir = join(denoDir, `deps/https/deno.land/x/${pkgName}`);
36+
const cacheDir = join(mcdir, `https/deno.land/x/${pkgName}`);
3737
const cachePath = `${cacheDir}/compiler.${VERSION}.wasm`;
3838
if (await existsFile(cachePath)) {
3939
const wasmData = await Deno.readFile(cachePath);

lib/cache.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,20 @@ export default async function cache(
1212
): Promise<Response> {
1313
const { protocol, hostname, port, pathname, search } = new URL(url);
1414
const isLocalhost = ["localhost", "0.0.0.0", "127.0.0.1"].includes(hostname);
15-
const denoDir = Deno.env.get("DENO_DIR");
15+
const modulesCacheDir = Deno.env.get("MODULES_CACHE_DIR");
1616
const hashname = isLocalhost ? "" : await util.computeHash("sha-256", pathname + search + (options?.userAgent || ""));
1717

1818
let cacheDir = "";
1919
let metaFilepath = "";
2020
let contentFilepath = "";
21-
if (denoDir) {
22-
cacheDir = join(denoDir, "deps", util.trimSuffix(protocol, ":"), hostname + (port ? "_PORT" + port : ""));
21+
if (modulesCacheDir) {
22+
cacheDir = join(modulesCacheDir, util.trimSuffix(protocol, ":"), hostname + (port ? "_PORT" + port : ""));
2323
contentFilepath = join(cacheDir, hashname);
2424
metaFilepath = join(cacheDir, hashname + ".metadata.json");
2525
}
2626

2727
if (!options?.forceRefresh && !isLocalhost) {
28-
if (denoDir) {
28+
if (modulesCacheDir) {
2929
if (await existsFile(contentFilepath) && await existsFile(metaFilepath)) {
3030
const [content, meta] = await Promise.all([
3131
Deno.readFile(contentFilepath),
@@ -68,7 +68,7 @@ export default async function cache(
6868
res.headers.forEach((val, key) => {
6969
headers[key] = val;
7070
});
71-
if (denoDir) {
71+
if (modulesCacheDir) {
7272
if (!(await existsDir(cacheDir))) {
7373
await Deno.mkdir(cacheDir, { recursive: true });
7474
}

lib/fs.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ export async function existsFile(path: string): Promise<boolean> {
3030
}
3131

3232
/* find file in the directory */
33-
export async function findFile(dir: string, filenames: string[]): Promise<string | undefined> {
33+
export async function findFile(filenames: string[]): Promise<string | undefined> {
34+
const cwd = Deno.cwd();
3435
for (const filename of filenames) {
35-
const fullPath = join(dir, filename);
36+
const fullPath = join(cwd, filename);
3637
if (await existsFile(fullPath)) {
3738
return fullPath;
3839
}
@@ -71,9 +72,9 @@ export async function readCode(
7172
if (url.hostname === "esm.sh" && !url.searchParams.has("target")) {
7273
url.searchParams.set("target", "esnext");
7374
}
74-
const res = await cache(url.toString());
75+
const res = await cache(url.href);
7576
if (res.status >= 400) {
76-
throw new Error(`fetch ${url} ${specifier}: ${res.status} - ${res.statusText}`);
77+
throw new Error(`fetch ${url.href}: ${res.status} - ${res.statusText}`);
7778
}
7879
const val = res.headers.get("Last-Modified");
7980
const mtime = val ? new Date(val).getTime() : undefined;

server/build.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ export const supportedPlatforms: Record<BuildPlatform, string> = {
2222
};
2323

2424
export async function build(
25-
workingDir: string,
2625
platform: BuildPlatform,
2726
serverEntry?: string,
2827
): Promise<{ clientModules: Set<string> }> {
2928
if (platform === "cf-worker" || platform === "vercel") {
3029
log.fatal(`Deploy to ${supportedPlatforms[platform]} is not supported yet`);
3130
}
3231

32+
const workingDir = Deno.cwd();
3333
const tmpDir = await Deno.makeTempDir();
3434
const alephPkgUri = getAlephPkgUri();
3535
const importMap = await loadImportMap();

0 commit comments

Comments
 (0)