@netlify/edge-bundler 1.13.0 → 2.0.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.
- package/deno/bundle.ts +3 -3
- package/deno/lib/common.ts +47 -0
- package/deno/lib/consts.ts +4 -0
- package/deno/lib/stage2.ts +66 -0
- package/dist/common/stage2.d.ts +10 -0
- package/dist/{bundle.js → common/stage2.js} +0 -0
- package/dist/{bridge.d.ts → src/bridge.d.ts} +0 -0
- package/dist/{bridge.js → src/bridge.js} +0 -0
- package/dist/{bundle.d.ts → src/bundle.d.ts} +0 -0
- package/dist/{declaration.js → src/bundle.js} +0 -0
- package/dist/{bundle_error.d.ts → src/bundle_error.d.ts} +0 -0
- package/dist/{bundle_error.js → src/bundle_error.js} +0 -0
- package/dist/{bundler.d.ts → src/bundler.d.ts} +1 -1
- package/dist/{bundler.js → src/bundler.js} +0 -0
- package/dist/{declaration.d.ts → src/declaration.d.ts} +0 -0
- package/dist/{edge_function.js → src/declaration.js} +0 -0
- package/dist/src/downloader.d.ts +3 -0
- package/dist/{downloader.js → src/downloader.js} +32 -24
- package/dist/{edge_function.d.ts → src/edge_function.d.ts} +0 -0
- package/dist/src/edge_function.js +1 -0
- package/dist/{feature_flags.d.ts → src/feature_flags.d.ts} +0 -0
- package/dist/{feature_flags.js → src/feature_flags.js} +0 -0
- package/dist/{finder.d.ts → src/finder.d.ts} +0 -0
- package/dist/{finder.js → src/finder.js} +0 -0
- package/dist/{formats → src/formats}/eszip.d.ts +0 -0
- package/dist/{formats → src/formats}/eszip.js +1 -1
- package/dist/{formats → src/formats}/javascript.d.ts +0 -0
- package/dist/{formats → src/formats}/javascript.js +0 -0
- package/dist/{home_path.d.ts → src/home_path.d.ts} +0 -0
- package/dist/{home_path.js → src/home_path.js} +0 -0
- package/dist/src/import_map.d.ts +15 -0
- package/dist/src/import_map.js +44 -0
- package/dist/{index.d.ts → src/index.d.ts} +0 -0
- package/dist/{index.js → src/index.js} +0 -0
- package/dist/{logger.d.ts → src/logger.d.ts} +0 -0
- package/dist/{logger.js → src/logger.js} +0 -0
- package/dist/{manifest.d.ts → src/manifest.d.ts} +0 -0
- package/dist/{manifest.js → src/manifest.js} +0 -0
- package/dist/{package_json.d.ts → src/package_json.d.ts} +0 -0
- package/dist/{package_json.js → src/package_json.js} +0 -0
- package/dist/{platform.d.ts → src/platform.d.ts} +0 -0
- package/dist/{platform.js → src/platform.js} +0 -0
- package/dist/{server → src/server}/server.d.ts +0 -0
- package/dist/{server → src/server}/server.js +0 -0
- package/dist/{server → src/server}/util.d.ts +0 -0
- package/dist/{server → src/server}/util.js +0 -0
- package/dist/{types.d.ts → src/types.d.ts} +0 -0
- package/dist/{types.js → src/types.js} +0 -0
- package/dist/{utils → src/utils}/non_nullable.d.ts +0 -0
- package/dist/{utils → src/utils}/non_nullable.js +0 -0
- package/dist/{utils → src/utils}/sha256.d.ts +0 -0
- package/dist/{utils → src/utils}/sha256.js +0 -0
- package/package.json +2 -1
- package/dist/downloader.d.ts +0 -3
- package/dist/import_map.d.ts +0 -13
- package/dist/import_map.js +0 -30
package/deno/bundle.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { writeStage2 } from '
|
|
1
|
+
import { writeStage2 } from './lib/stage2.ts'
|
|
2
2
|
|
|
3
3
|
const [payload] = Deno.args
|
|
4
|
-
const { basePath, destPath, functions,
|
|
4
|
+
const { basePath, destPath, functions, importMapURL } = JSON.parse(payload)
|
|
5
5
|
|
|
6
|
-
await writeStage2({ basePath, destPath, functions,
|
|
6
|
+
await writeStage2({ basePath, destPath, functions, importMapURL })
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { load } from "https://deno.land/x/eszip@v0.18.0/loader.ts";
|
|
2
|
+
import { LoadResponse } from "https://deno.land/x/eszip@v0.18.0/mod.ts";
|
|
3
|
+
import * as path from "https://deno.land/std@0.127.0/path/mod.ts";
|
|
4
|
+
import { retryAsync } from "https://deno.land/x/retry@v2.0.0/mod.ts";
|
|
5
|
+
|
|
6
|
+
const inlineModule = (
|
|
7
|
+
specifier: string,
|
|
8
|
+
content: string,
|
|
9
|
+
): LoadResponse => {
|
|
10
|
+
return {
|
|
11
|
+
content,
|
|
12
|
+
headers: {
|
|
13
|
+
"content-type": "application/typescript",
|
|
14
|
+
},
|
|
15
|
+
kind: "module",
|
|
16
|
+
specifier,
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const loadFromVirtualRoot = async (
|
|
21
|
+
specifier: string,
|
|
22
|
+
virtualRoot: string,
|
|
23
|
+
basePath: string,
|
|
24
|
+
) => {
|
|
25
|
+
const basePathURL = path.toFileUrl(basePath).toString();
|
|
26
|
+
const filePath = specifier.replace(virtualRoot.slice(0, -1), basePathURL);
|
|
27
|
+
const file = await load(filePath);
|
|
28
|
+
|
|
29
|
+
if (file === undefined) {
|
|
30
|
+
throw new Error(`Could not find file: ${filePath}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return { ...file, specifier };
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const loadWithRetry = (specifier: string, delay = 1000, maxTry = 3) => {
|
|
37
|
+
if (!specifier.startsWith("https://")) {
|
|
38
|
+
return load(specifier);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return retryAsync(() => load(specifier), {
|
|
42
|
+
delay,
|
|
43
|
+
maxTry,
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export { inlineModule, loadFromVirtualRoot, loadWithRetry };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { build, LoadResponse } from 'https://deno.land/x/eszip@v0.28.0/mod.ts'
|
|
2
|
+
|
|
3
|
+
import * as path from 'https://deno.land/std@0.127.0/path/mod.ts'
|
|
4
|
+
|
|
5
|
+
import type { InputFunction, WriteStage2Options } from '../../common/stage2.ts'
|
|
6
|
+
import { PUBLIC_SPECIFIER, STAGE2_SPECIFIER, virtualRoot } from './consts.ts'
|
|
7
|
+
import { inlineModule, loadFromVirtualRoot, loadWithRetry } from './common.ts'
|
|
8
|
+
|
|
9
|
+
const getFunctionReference = (basePath: string, func: InputFunction, index: number) => {
|
|
10
|
+
const importName = `func${index}`
|
|
11
|
+
const exportLine = `"${func.name}": ${importName}`
|
|
12
|
+
const url = getVirtualPath(basePath, func.path)
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
exportLine,
|
|
16
|
+
importLine: `import ${importName} from "${url}";`,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getStage2Entry = (basePath: string, functions: InputFunction[]) => {
|
|
21
|
+
const lines = functions.map((func, index) => getFunctionReference(basePath, func, index))
|
|
22
|
+
const importLines = lines.map(({ importLine }) => importLine).join('\n')
|
|
23
|
+
const exportLines = lines.map(({ exportLine }) => exportLine).join(', ')
|
|
24
|
+
const exportDeclaration = `export const functions = {${exportLines}};`
|
|
25
|
+
|
|
26
|
+
return [importLines, exportDeclaration].join('\n\n')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const getVirtualPath = (basePath: string, filePath: string) => {
|
|
30
|
+
const relativePath = path.relative(basePath, filePath)
|
|
31
|
+
const url = new URL(relativePath, virtualRoot)
|
|
32
|
+
|
|
33
|
+
return url
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const stage2Loader = (basePath: string, functions: InputFunction[]) => {
|
|
37
|
+
return async (specifier: string): Promise<LoadResponse | undefined> => {
|
|
38
|
+
if (specifier === STAGE2_SPECIFIER) {
|
|
39
|
+
const stage2Entry = getStage2Entry(basePath, functions)
|
|
40
|
+
|
|
41
|
+
return inlineModule(specifier, stage2Entry)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (specifier === PUBLIC_SPECIFIER) {
|
|
45
|
+
return {
|
|
46
|
+
kind: 'external',
|
|
47
|
+
specifier,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (specifier.startsWith(virtualRoot)) {
|
|
52
|
+
return loadFromVirtualRoot(specifier, virtualRoot, basePath)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return await loadWithRetry(specifier)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const writeStage2 = async ({ basePath, destPath, functions, importMapURL }: WriteStage2Options) => {
|
|
60
|
+
const loader = stage2Loader(basePath, functions)
|
|
61
|
+
const bytes = await build([STAGE2_SPECIFIER], loader, importMapURL)
|
|
62
|
+
|
|
63
|
+
return await Deno.writeFile(destPath, bytes)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { writeStage2 }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -15,7 +15,7 @@ interface BundleOptions {
|
|
|
15
15
|
onBeforeDownload?: OnBeforeDownloadHook;
|
|
16
16
|
systemLogger?: LogFunction;
|
|
17
17
|
}
|
|
18
|
-
declare const bundle: (sourceDirectories: string[], distDirectory: string, declarations?: Declaration[], { basePath
|
|
18
|
+
declare const bundle: (sourceDirectories: string[], distDirectory: string, declarations?: Declaration[], { basePath, cacheDirectory, debug, distImportMapPath, featureFlags, importMaps, onAfterDownload, onBeforeDownload, systemLogger, }?: BundleOptions) => Promise<{
|
|
19
19
|
functions: EdgeFunction[];
|
|
20
20
|
manifest: import("./manifest.js").Manifest;
|
|
21
21
|
}>;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,51 +1,59 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
1
|
+
import { createWriteStream, promises as fs } from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { promisify } from 'util';
|
|
3
4
|
import fetch from 'node-fetch';
|
|
4
5
|
import StreamZip from 'node-stream-zip';
|
|
5
6
|
import pRetry from 'p-retry';
|
|
6
7
|
import semver from 'semver';
|
|
7
8
|
import { getBinaryExtension, getPlatformTarget } from './platform.js';
|
|
8
|
-
const
|
|
9
|
+
const downloadWithRetry = async (targetDirectory, versionRange, logger) => await pRetry(async () => await download(targetDirectory, versionRange), {
|
|
10
|
+
retries: 3,
|
|
11
|
+
onFailedAttempt: (error) => {
|
|
12
|
+
logger.system('Deno download with retry failed', error);
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
const download = async (targetDirectory, versionRange) => {
|
|
9
16
|
const zipPath = path.join(targetDirectory, 'deno-cli-latest.zip');
|
|
10
|
-
const data = await
|
|
17
|
+
const data = await downloadVersion(versionRange);
|
|
11
18
|
const binaryName = `deno${getBinaryExtension()}`;
|
|
12
19
|
const binaryPath = path.join(targetDirectory, binaryName);
|
|
13
|
-
const file =
|
|
14
|
-
await new Promise((resolve, reject) => {
|
|
15
|
-
data.pipe(file);
|
|
16
|
-
data.on('error', reject);
|
|
17
|
-
file.on('finish', resolve);
|
|
18
|
-
});
|
|
19
|
-
await extractBinaryFromZip(zipPath, binaryPath, binaryName);
|
|
20
|
+
const file = createWriteStream(zipPath);
|
|
20
21
|
try {
|
|
21
|
-
await
|
|
22
|
+
await new Promise((resolve, reject) => {
|
|
23
|
+
data.pipe(file);
|
|
24
|
+
data.on('error', reject);
|
|
25
|
+
file.on('finish', resolve);
|
|
26
|
+
});
|
|
27
|
+
await extractBinaryFromZip(zipPath, binaryPath, binaryName);
|
|
28
|
+
return binaryPath;
|
|
22
29
|
}
|
|
23
|
-
|
|
24
|
-
//
|
|
30
|
+
finally {
|
|
31
|
+
// Try closing and deleting the zip file in any case, error or not
|
|
32
|
+
await promisify(file.close.bind(file))();
|
|
33
|
+
try {
|
|
34
|
+
await fs.unlink(zipPath);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// no-op
|
|
38
|
+
}
|
|
25
39
|
}
|
|
26
|
-
return binaryPath;
|
|
27
40
|
};
|
|
28
41
|
const downloadVersion = async (versionRange) => {
|
|
29
42
|
const version = await getLatestVersionForRange(versionRange);
|
|
30
43
|
const url = getReleaseURL(version);
|
|
31
44
|
const res = await fetch(url);
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
// eslint-disable-next-line no-magic-numbers
|
|
46
|
+
if (res.body === null || res.status < 200 || res.status > 299) {
|
|
47
|
+
throw new Error(`Download failed with status code ${res.status}`);
|
|
34
48
|
}
|
|
35
49
|
return res.body;
|
|
36
50
|
};
|
|
37
|
-
const downloadVersionWithRetry = async (versionRange, logger) => await pRetry(async () => await downloadVersion(versionRange), {
|
|
38
|
-
retries: 3,
|
|
39
|
-
onFailedAttempt: (error) => {
|
|
40
|
-
logger.system('Deno CLI download retry attempt error', error);
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
51
|
const extractBinaryFromZip = async (zipPath, binaryPath, binaryName) => {
|
|
44
52
|
const { async: StreamZipAsync } = StreamZip;
|
|
45
53
|
const zip = new StreamZipAsync({ file: zipPath });
|
|
46
54
|
await zip.extract(binaryName, binaryPath);
|
|
47
55
|
await zip.close();
|
|
48
|
-
await fs.
|
|
56
|
+
await fs.chmod(binaryPath, '755');
|
|
49
57
|
};
|
|
50
58
|
const getLatestVersion = async () => {
|
|
51
59
|
try {
|
|
@@ -82,4 +90,4 @@ const getReleaseURL = (version) => {
|
|
|
82
90
|
const target = getPlatformTarget();
|
|
83
91
|
return `https://dl.deno.land/release/v${version}/deno-${target}.zip`;
|
|
84
92
|
};
|
|
85
|
-
export { download };
|
|
93
|
+
export { downloadWithRetry as download };
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface ImportMapFile {
|
|
2
|
+
baseURL: URL;
|
|
3
|
+
imports: Record<string, string>;
|
|
4
|
+
scopes?: Record<string, Record<string, string>>;
|
|
5
|
+
}
|
|
6
|
+
declare class ImportMap {
|
|
7
|
+
imports: Record<string, URL | null>;
|
|
8
|
+
constructor(files?: ImportMapFile[]);
|
|
9
|
+
static resolve(importMapFile: ImportMapFile): import("@import-maps/resolve/types/src/types").ParsedImportMap;
|
|
10
|
+
getContents(): string;
|
|
11
|
+
toDataURL(): string;
|
|
12
|
+
writeToFile(path: string): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export { ImportMap };
|
|
15
|
+
export type { ImportMapFile };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
import { parse } from '@import-maps/resolve';
|
|
5
|
+
const INTERNAL_IMPORTS = {
|
|
6
|
+
'netlify:edge': new URL('https://edge.netlify.com/v1/index.ts'),
|
|
7
|
+
};
|
|
8
|
+
class ImportMap {
|
|
9
|
+
constructor(files = []) {
|
|
10
|
+
let imports = {};
|
|
11
|
+
files.forEach((file) => {
|
|
12
|
+
const importMap = ImportMap.resolve(file);
|
|
13
|
+
imports = { ...imports, ...importMap.imports };
|
|
14
|
+
});
|
|
15
|
+
// Internal imports must come last, because we need to guarantee that
|
|
16
|
+
// `netlify:edge` isn't user-defined.
|
|
17
|
+
Object.entries(INTERNAL_IMPORTS).forEach((internalImport) => {
|
|
18
|
+
const [specifier, url] = internalImport;
|
|
19
|
+
imports[specifier] = url;
|
|
20
|
+
});
|
|
21
|
+
this.imports = imports;
|
|
22
|
+
}
|
|
23
|
+
static resolve(importMapFile) {
|
|
24
|
+
const { baseURL, ...importMap } = importMapFile;
|
|
25
|
+
const parsedImportMap = parse(importMap, baseURL);
|
|
26
|
+
return parsedImportMap;
|
|
27
|
+
}
|
|
28
|
+
getContents() {
|
|
29
|
+
const contents = {
|
|
30
|
+
imports: this.imports,
|
|
31
|
+
};
|
|
32
|
+
return JSON.stringify(contents);
|
|
33
|
+
}
|
|
34
|
+
toDataURL() {
|
|
35
|
+
const encodedImportMap = Buffer.from(this.getContents()).toString('base64');
|
|
36
|
+
return `data:application/json;base64,${encodedImportMap}`;
|
|
37
|
+
}
|
|
38
|
+
async writeToFile(path) {
|
|
39
|
+
await fs.mkdir(dirname(path), { recursive: true });
|
|
40
|
+
const contents = this.getContents();
|
|
41
|
+
await fs.writeFile(path, contents);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export { ImportMap };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/edge-bundler",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Intelligently prepare Netlify Edge Functions for deployment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
"node": "^12.20.0 || ^14.14.0 || >=16.0.0"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
|
+
"@import-maps/resolve": "^1.0.1",
|
|
82
83
|
"common-path-prefix": "^3.0.0",
|
|
83
84
|
"del": "^6.0.0",
|
|
84
85
|
"env-paths": "^3.0.0",
|
package/dist/downloader.d.ts
DELETED
package/dist/import_map.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
interface ImportMapFile {
|
|
2
|
-
imports: Record<string, string>;
|
|
3
|
-
scopes?: Record<string, string>;
|
|
4
|
-
}
|
|
5
|
-
declare class ImportMap {
|
|
6
|
-
imports: Record<string, string>;
|
|
7
|
-
constructor(input?: ImportMapFile[]);
|
|
8
|
-
getContents(): string;
|
|
9
|
-
toDataURL(): string;
|
|
10
|
-
writeToFile(path: string): Promise<void>;
|
|
11
|
-
}
|
|
12
|
-
export { ImportMap };
|
|
13
|
-
export type { ImportMapFile };
|
package/dist/import_map.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Buffer } from 'buffer';
|
|
2
|
-
import { promises as fs } from 'fs';
|
|
3
|
-
import { dirname } from 'path';
|
|
4
|
-
const INTERNAL_IMPORTS = {
|
|
5
|
-
'netlify:edge': 'https://edge.netlify.com/v1/index.ts',
|
|
6
|
-
};
|
|
7
|
-
class ImportMap {
|
|
8
|
-
constructor(input = []) {
|
|
9
|
-
const inputImports = input.reduce((acc, { imports }) => ({ ...acc, ...imports }), {});
|
|
10
|
-
// `INTERNAL_IMPORTS` must come last,
|
|
11
|
-
// because we need to guarantee `netlify:edge` isn't user-defined.
|
|
12
|
-
this.imports = { ...inputImports, ...INTERNAL_IMPORTS };
|
|
13
|
-
}
|
|
14
|
-
getContents() {
|
|
15
|
-
const contents = {
|
|
16
|
-
imports: this.imports,
|
|
17
|
-
};
|
|
18
|
-
return JSON.stringify(contents);
|
|
19
|
-
}
|
|
20
|
-
toDataURL() {
|
|
21
|
-
const encodedImportMap = Buffer.from(this.getContents()).toString('base64');
|
|
22
|
-
return `data:application/json;base64,${encodedImportMap}`;
|
|
23
|
-
}
|
|
24
|
-
async writeToFile(path) {
|
|
25
|
-
await fs.mkdir(dirname(path), { recursive: true });
|
|
26
|
-
const contents = this.getContents();
|
|
27
|
-
await fs.writeFile(path, contents);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
export { ImportMap };
|