@prairielearn/compiled-assets 2.0.17 → 3.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/.mocharc.cjs +3 -0
- package/CHANGELOG.md +11 -0
- package/dist/cli.js +19 -24
- package/dist/cli.js.map +1 -1
- package/dist/index.js +33 -48
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +35 -40
- package/dist/index.test.js.map +1 -1
- package/package.json +5 -4
- package/src/index.test.ts +1 -1
package/.mocharc.cjs
ADDED
package/CHANGELOG.md
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const zlib_1 = __importDefault(require("zlib"));
|
|
12
|
-
const commander_1 = require("commander");
|
|
13
|
-
const index_js_1 = require("./index.js");
|
|
14
|
-
const gzip = (0, util_1.promisify)(zlib_1.default.gzip);
|
|
15
|
-
const brotli = (0, util_1.promisify)(zlib_1.default.brotliCompress);
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import prettyBytes from 'pretty-bytes';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
import zlib from 'zlib';
|
|
7
|
+
import { program } from 'commander';
|
|
8
|
+
import { build } from './index.js';
|
|
9
|
+
const gzip = promisify(zlib.gzip);
|
|
10
|
+
const brotli = promisify(zlib.brotliCompress);
|
|
16
11
|
async function writeCompressedAssets(destination, manifest) {
|
|
17
12
|
const compressedSizes = {};
|
|
18
13
|
await Promise.all(Object.values(manifest).map(async (filePath) => {
|
|
19
|
-
const destinationFilePath =
|
|
20
|
-
const contents = await
|
|
14
|
+
const destinationFilePath = path.resolve(destination, filePath);
|
|
15
|
+
const contents = await fs.readFile(destinationFilePath);
|
|
21
16
|
const gzipCompressed = await gzip(contents);
|
|
22
17
|
const brotliCompressed = await brotli(contents);
|
|
23
|
-
await
|
|
24
|
-
await
|
|
18
|
+
await fs.writeFile(`${destinationFilePath}.gz`, gzipCompressed);
|
|
19
|
+
await fs.writeFile(`${destinationFilePath}.br`, brotliCompressed);
|
|
25
20
|
compressedSizes[filePath] = {
|
|
26
21
|
raw: contents.length,
|
|
27
22
|
gzip: gzipCompressed.length,
|
|
@@ -30,8 +25,8 @@ async function writeCompressedAssets(destination, manifest) {
|
|
|
30
25
|
}));
|
|
31
26
|
return compressedSizes;
|
|
32
27
|
}
|
|
33
|
-
|
|
34
|
-
const manifest = await
|
|
28
|
+
program.command('build <source> <destination>').action(async (source, destination) => {
|
|
29
|
+
const manifest = await build(source, destination);
|
|
35
30
|
// Write gzip and brotli versions of the output files. Record size information
|
|
36
31
|
// so we can show it to the user.
|
|
37
32
|
const compressedSizes = await writeCompressedAssets(destination, manifest);
|
|
@@ -41,14 +36,14 @@ commander_1.program.command('build <source> <destination>').action(async (source
|
|
|
41
36
|
const sizes = compressedSizes[assetPath];
|
|
42
37
|
results[entryPoint] = {
|
|
43
38
|
'Output file': assetPath,
|
|
44
|
-
Size: (
|
|
45
|
-
'Size (gzip)': (
|
|
46
|
-
'Size (brotli)': (
|
|
39
|
+
Size: prettyBytes(sizes.raw),
|
|
40
|
+
'Size (gzip)': prettyBytes(sizes.gzip),
|
|
41
|
+
'Size (brotli)': prettyBytes(sizes.brotli),
|
|
47
42
|
};
|
|
48
43
|
});
|
|
49
44
|
console.table(results);
|
|
50
45
|
});
|
|
51
|
-
|
|
46
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
52
47
|
console.error(err);
|
|
53
48
|
process.exit(1);
|
|
54
49
|
});
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClC,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAI9C,KAAK,UAAU,qBAAqB,CAClC,WAAmB,EACnB,QAAgC;IAEhC,MAAM,eAAe,GAAoB,EAAE,CAAC;IAC5C,MAAM,OAAO,CAAC,GAAG,CACf,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC7C,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAChE,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QACxD,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,gBAAgB,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,mBAAmB,KAAK,EAAE,cAAc,CAAC,CAAC;QAChE,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,mBAAmB,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAClE,eAAe,CAAC,QAAQ,CAAC,GAAG;YAC1B,GAAG,EAAE,QAAQ,CAAC,MAAM;YACpB,IAAI,EAAE,cAAc,CAAC,MAAM;YAC3B,MAAM,EAAE,gBAAgB,CAAC,MAAM;SAChC,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;IACF,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,OAAO,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE;IACnF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAElD,8EAA8E;IAC9E,iCAAiC;IACjC,MAAM,eAAe,GAAG,MAAM,qBAAqB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE3E,wEAAwE;IACxE,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,EAAE;QAC3D,MAAM,KAAK,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QACzC,OAAO,CAAC,UAAU,CAAC,GAAG;YACpB,aAAa,EAAE,SAAS;YACxB,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC;YAC5B,aAAa,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC;YACtC,eAAe,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC;SAC3C,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport fs from 'fs-extra';\nimport prettyBytes from 'pretty-bytes';\nimport path from 'path';\nimport { promisify } from 'util';\nimport zlib from 'zlib';\nimport { program } from 'commander';\n\nimport { build } from './index.js';\n\nconst gzip = promisify(zlib.gzip);\nconst brotli = promisify(zlib.brotliCompress);\n\ntype CompressedSizes = Record<string, Record<string, number>>;\n\nasync function writeCompressedAssets(\n destination: string,\n manifest: Record<string, string>,\n): Promise<CompressedSizes> {\n const compressedSizes: CompressedSizes = {};\n await Promise.all(\n Object.values(manifest).map(async (filePath) => {\n const destinationFilePath = path.resolve(destination, filePath);\n const contents = await fs.readFile(destinationFilePath);\n const gzipCompressed = await gzip(contents);\n const brotliCompressed = await brotli(contents);\n await fs.writeFile(`${destinationFilePath}.gz`, gzipCompressed);\n await fs.writeFile(`${destinationFilePath}.br`, brotliCompressed);\n compressedSizes[filePath] = {\n raw: contents.length,\n gzip: gzipCompressed.length,\n brotli: brotliCompressed.length,\n };\n }),\n );\n return compressedSizes;\n}\n\nprogram.command('build <source> <destination>').action(async (source, destination) => {\n const manifest = await build(source, destination);\n\n // Write gzip and brotli versions of the output files. Record size information\n // so we can show it to the user.\n const compressedSizes = await writeCompressedAssets(destination, manifest);\n\n // Format the output into an object that we can pass to `console.table`.\n const results: Record<string, any> = {};\n Object.entries(manifest).forEach(([entryPoint, assetPath]) => {\n const sizes = compressedSizes[assetPath];\n results[entryPoint] = {\n 'Output file': assetPath,\n Size: prettyBytes(sizes.raw),\n 'Size (gzip)': prettyBytes(sizes.gzip),\n 'Size (brotli)': prettyBytes(sizes.brotli),\n };\n });\n console.table(results);\n});\n\nprogram.parseAsync(process.argv).catch((err) => {\n console.error(err);\n process.exit(1);\n});\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const esbuild_1 = __importDefault(require("esbuild"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const globby_1 = __importDefault(require("globby"));
|
|
11
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
12
|
-
const node_http_1 = __importDefault(require("node:http"));
|
|
13
|
-
const html_1 = require("@prairielearn/html");
|
|
1
|
+
import expressStaticGzip from 'express-static-gzip';
|
|
2
|
+
import esbuild from 'esbuild';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import globby from 'globby';
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import http from 'node:http';
|
|
7
|
+
import { html } from '@prairielearn/html';
|
|
14
8
|
const DEFAULT_OPTIONS = {
|
|
15
9
|
dev: process.env.NODE_ENV !== 'production',
|
|
16
10
|
sourceDirectory: './assets',
|
|
@@ -20,7 +14,7 @@ const DEFAULT_OPTIONS = {
|
|
|
20
14
|
let options = { ...DEFAULT_OPTIONS };
|
|
21
15
|
let esbuildContext = null;
|
|
22
16
|
let esbuildServer = null;
|
|
23
|
-
async function init(newOptions) {
|
|
17
|
+
export async function init(newOptions) {
|
|
24
18
|
options = {
|
|
25
19
|
...DEFAULT_OPTIONS,
|
|
26
20
|
...newOptions,
|
|
@@ -33,9 +27,9 @@ async function init(newOptions) {
|
|
|
33
27
|
//
|
|
34
28
|
// Note that esbuild doesn't support globs, so the server will not pick up
|
|
35
29
|
// new entrypoints that are added while the server is running.
|
|
36
|
-
const sourceGlob =
|
|
37
|
-
const sourcePaths = await (
|
|
38
|
-
esbuildContext = await
|
|
30
|
+
const sourceGlob = path.join(options.sourceDirectory, '*', '*.{js,ts,css}');
|
|
31
|
+
const sourcePaths = await globby(sourceGlob);
|
|
32
|
+
esbuildContext = await esbuild.context({
|
|
39
33
|
entryPoints: sourcePaths,
|
|
40
34
|
target: 'es6',
|
|
41
35
|
format: 'iife',
|
|
@@ -53,27 +47,24 @@ async function init(newOptions) {
|
|
|
53
47
|
esbuildServer = await esbuildContext.serve();
|
|
54
48
|
}
|
|
55
49
|
}
|
|
56
|
-
exports.init = init;
|
|
57
50
|
/**
|
|
58
51
|
* Shuts down the development assets compiler if it is running.
|
|
59
52
|
*/
|
|
60
|
-
async function close() {
|
|
53
|
+
export async function close() {
|
|
61
54
|
esbuildContext?.dispose();
|
|
62
55
|
}
|
|
63
|
-
|
|
64
|
-
function assertConfigured() {
|
|
56
|
+
export function assertConfigured() {
|
|
65
57
|
if (!options) {
|
|
66
58
|
throw new Error('@prairielearn/compiled-assets was not configured');
|
|
67
59
|
}
|
|
68
60
|
}
|
|
69
|
-
|
|
70
|
-
function handler() {
|
|
61
|
+
export function handler() {
|
|
71
62
|
assertConfigured();
|
|
72
63
|
if (!options?.dev) {
|
|
73
64
|
// We're running in production: serve all assets from the build directory.
|
|
74
65
|
// Set headers to cache for as long as possible, since the assets will
|
|
75
66
|
// include content hashes in their filenames.
|
|
76
|
-
return (
|
|
67
|
+
return expressStaticGzip(options?.buildDirectory, {
|
|
77
68
|
enableBrotli: true,
|
|
78
69
|
// Prefer Brotli if the client supports it.
|
|
79
70
|
orderPreference: ['br'],
|
|
@@ -90,7 +81,7 @@ function handler() {
|
|
|
90
81
|
// We're running in dev mode, so we need to boot up ESBuild to start building
|
|
91
82
|
// and watching our assets.
|
|
92
83
|
return function (req, res) {
|
|
93
|
-
const proxyReq =
|
|
84
|
+
const proxyReq = http.request({
|
|
94
85
|
hostname: host,
|
|
95
86
|
port,
|
|
96
87
|
path: req.url,
|
|
@@ -103,13 +94,12 @@ function handler() {
|
|
|
103
94
|
req.pipe(proxyReq, { end: true });
|
|
104
95
|
};
|
|
105
96
|
}
|
|
106
|
-
exports.handler = handler;
|
|
107
97
|
let cachedManifest = null;
|
|
108
98
|
function readManifest() {
|
|
109
99
|
assertConfigured();
|
|
110
100
|
if (!cachedManifest) {
|
|
111
|
-
const manifestPath =
|
|
112
|
-
cachedManifest =
|
|
101
|
+
const manifestPath = path.join(options.buildDirectory, 'manifest.json');
|
|
102
|
+
cachedManifest = fs.readJSONSync(manifestPath);
|
|
113
103
|
}
|
|
114
104
|
return cachedManifest;
|
|
115
105
|
}
|
|
@@ -126,26 +116,22 @@ function compiledPath(type, sourceFile) {
|
|
|
126
116
|
}
|
|
127
117
|
return `${options.publicPath}/${assetPath}`;
|
|
128
118
|
}
|
|
129
|
-
function compiledScriptPath(sourceFile) {
|
|
119
|
+
export function compiledScriptPath(sourceFile) {
|
|
130
120
|
return compiledPath('scripts', sourceFile);
|
|
131
121
|
}
|
|
132
|
-
|
|
133
|
-
function compiledStylesheetPath(sourceFile) {
|
|
122
|
+
export function compiledStylesheetPath(sourceFile) {
|
|
134
123
|
return compiledPath('stylesheets', sourceFile);
|
|
135
124
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return (0, html_1.html) `<script src="${compiledScriptPath(sourceFile)}"></script>`;
|
|
125
|
+
export function compiledScriptTag(sourceFile) {
|
|
126
|
+
return html `<script src="${compiledScriptPath(sourceFile)}"></script>`;
|
|
139
127
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return (0, html_1.html) `<link rel="stylesheet" href="${compiledStylesheetPath(sourceFile)}" />`;
|
|
128
|
+
export function compiledStylesheetTag(sourceFile) {
|
|
129
|
+
return html `<link rel="stylesheet" href="${compiledStylesheetPath(sourceFile)}" />`;
|
|
143
130
|
}
|
|
144
|
-
exports.compiledStylesheetTag = compiledStylesheetTag;
|
|
145
131
|
async function buildAssets(sourceDirectory, buildDirectory) {
|
|
146
|
-
await
|
|
147
|
-
const files = await (
|
|
148
|
-
const buildResult = await
|
|
132
|
+
await fs.ensureDir(buildDirectory);
|
|
133
|
+
const files = await globby(path.join(sourceDirectory, '*/*.{js,jsx,ts,tsx,css}'));
|
|
134
|
+
const buildResult = await esbuild.build({
|
|
149
135
|
entryPoints: files,
|
|
150
136
|
target: 'es6',
|
|
151
137
|
format: 'iife',
|
|
@@ -168,20 +154,19 @@ function makeManifest(metafile, sourceDirectory, buildDirectory) {
|
|
|
168
154
|
Object.entries(metafile.outputs).forEach(([outputPath, meta]) => {
|
|
169
155
|
if (!meta.entryPoint)
|
|
170
156
|
return;
|
|
171
|
-
const entryPath =
|
|
172
|
-
const assetPath =
|
|
157
|
+
const entryPath = path.relative(sourceDirectory, meta.entryPoint);
|
|
158
|
+
const assetPath = path.relative(buildDirectory, outputPath);
|
|
173
159
|
manifest[entryPath] = assetPath;
|
|
174
160
|
});
|
|
175
161
|
return manifest;
|
|
176
162
|
}
|
|
177
|
-
async function build(sourceDirectory, buildDirectory) {
|
|
163
|
+
export async function build(sourceDirectory, buildDirectory) {
|
|
178
164
|
// Remove existing assets to ensure that no stale assets are left behind.
|
|
179
|
-
await
|
|
165
|
+
await fs.remove(buildDirectory);
|
|
180
166
|
const metafile = await buildAssets(sourceDirectory, buildDirectory);
|
|
181
167
|
const manifest = makeManifest(metafile, sourceDirectory, buildDirectory);
|
|
182
|
-
const manifestPath =
|
|
183
|
-
await
|
|
168
|
+
const manifestPath = path.join(buildDirectory, 'manifest.json');
|
|
169
|
+
await fs.writeJSON(manifestPath, manifest);
|
|
184
170
|
return manifest;
|
|
185
171
|
}
|
|
186
|
-
exports.build = build;
|
|
187
172
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RequestHandler } from 'express';\nimport expressStaticGzip from 'express-static-gzip';\nimport esbuild, { Metafile } from 'esbuild';\nimport path from 'path';\nimport globby from 'globby';\nimport fs from 'fs-extra';\nimport http from 'node:http';\nimport { html, HtmlSafeString } from '@prairielearn/html';\n\nconst DEFAULT_OPTIONS = {\n dev: process.env.NODE_ENV !== 'production',\n sourceDirectory: './assets',\n buildDirectory: './public/build',\n publicPath: '/build/',\n};\n\ntype AssetsManifest = Record<string, string>;\n\nexport interface CompiledAssetsOptions {\n /**\n * Whether the app is running in dev mode. If dev mode is enabled, then\n * assets will be built on the fly as they're requested. Otherwise, assets\n * should have been pre-compiled to the `buildDirectory` directory.\n */\n dev?: boolean;\n /** Root directory of assets. */\n sourceDirectory?: string;\n /** Directory where the built assets will be output to. */\n buildDirectory?: string;\n /** The path that assets will be served from, e.g. `/build/`. */\n publicPath?: string;\n}\n\nlet options: Required<CompiledAssetsOptions> = { ...DEFAULT_OPTIONS };\nlet esbuildContext: esbuild.BuildContext | null = null;\nlet esbuildServer: esbuild.ServeResult | null = null;\n\nexport async function init(newOptions: Partial<CompiledAssetsOptions>): Promise<void> {\n options = {\n ...DEFAULT_OPTIONS,\n ...newOptions,\n };\n\n if (!options.publicPath.endsWith('/')) {\n options.publicPath += '/';\n }\n\n if (options.dev) {\n // Use esbuild's asset server in development.\n //\n // Note that esbuild doesn't support globs, so the server will not pick up\n // new entrypoints that are added while the server is running.\n const sourceGlob = path.join(options.sourceDirectory, '*', '*.{js,ts,css}');\n const sourcePaths = await globby(sourceGlob);\n esbuildContext = await esbuild.context({\n entryPoints: sourcePaths,\n target: 'es6',\n format: 'iife',\n sourcemap: 'inline',\n bundle: true,\n write: false,\n loader: {\n '.woff': 'file',\n '.woff2': 'file',\n },\n outbase: options.sourceDirectory,\n outdir: options.buildDirectory,\n entryNames: '[dir]/[name]',\n });\n\n esbuildServer = await esbuildContext.serve();\n }\n}\n\n/**\n * Shuts down the development assets compiler if it is running.\n */\nexport async function close() {\n esbuildContext?.dispose();\n}\n\nexport function assertConfigured(): void {\n if (!options) {\n throw new Error('@prairielearn/compiled-assets was not configured');\n }\n}\n\nexport function handler(): RequestHandler {\n assertConfigured();\n\n if (!options?.dev) {\n // We're running in production: serve all assets from the build directory.\n // Set headers to cache for as long as possible, since the assets will\n // include content hashes in their filenames.\n return expressStaticGzip(options?.buildDirectory, {\n enableBrotli: true,\n // Prefer Brotli if the client supports it.\n orderPreference: ['br'],\n serveStatic: {\n maxAge: '31557600',\n immutable: true,\n },\n });\n }\n\n if (!esbuildServer) {\n throw new Error('esbuild server not initialized');\n }\n\n const { host, port } = esbuildServer;\n\n // We're running in dev mode, so we need to boot up ESBuild to start building\n // and watching our assets.\n return function (req, res) {\n const proxyReq = http.request(\n {\n hostname: host,\n port,\n path: req.url,\n method: req.method,\n headers: req.headers,\n },\n (proxyRes) => {\n res.writeHead(proxyRes.statusCode ?? 500, proxyRes.headers);\n proxyRes.pipe(res, { end: true });\n },\n );\n req.pipe(proxyReq, { end: true });\n };\n}\n\nlet cachedManifest: AssetsManifest | null = null;\nfunction readManifest(): AssetsManifest {\n assertConfigured();\n\n if (!cachedManifest) {\n const manifestPath = path.join(options.buildDirectory, 'manifest.json');\n cachedManifest = fs.readJSONSync(manifestPath) as AssetsManifest;\n }\n\n return cachedManifest;\n}\n\nfunction compiledPath(type: 'scripts' | 'stylesheets', sourceFile: string): string {\n assertConfigured();\n const sourceFilePath = `${type}/${sourceFile}`;\n\n if (options.dev) {\n return options.publicPath + sourceFilePath.replace(/\\.(js|ts)x?$/, '.js');\n }\n\n const manifest = readManifest();\n const assetPath = manifest[sourceFilePath];\n if (!assetPath) {\n throw new Error(`Unknown ${type} asset: ${sourceFile}`);\n }\n\n return `${options.publicPath}/${assetPath}`;\n}\n\nexport function compiledScriptPath(sourceFile: string): string {\n return compiledPath('scripts', sourceFile);\n}\n\nexport function compiledStylesheetPath(sourceFile: string): string {\n return compiledPath('stylesheets', sourceFile);\n}\n\nexport function compiledScriptTag(sourceFile: string): HtmlSafeString {\n return html`<script src=\"${compiledScriptPath(sourceFile)}\"></script>`;\n}\n\nexport function compiledStylesheetTag(sourceFile: string): HtmlSafeString {\n return html`<link rel=\"stylesheet\" href=\"${compiledStylesheetPath(sourceFile)}\" />`;\n}\n\nasync function buildAssets(sourceDirectory: string, buildDirectory: string) {\n await fs.ensureDir(buildDirectory);\n\n const files = await globby(path.join(sourceDirectory, '*/*.{js,jsx,ts,tsx,css}'));\n const buildResult = await esbuild.build({\n entryPoints: files,\n target: 'es6',\n format: 'iife',\n sourcemap: 'linked',\n bundle: true,\n minify: true,\n loader: {\n '.woff': 'file',\n '.woff2': 'file',\n },\n entryNames: '[dir]/[name]-[hash]',\n outbase: sourceDirectory,\n outdir: buildDirectory,\n metafile: true,\n });\n\n return buildResult.metafile;\n}\n\nfunction makeManifest(\n metafile: Metafile,\n sourceDirectory: string,\n buildDirectory: string,\n): Record<string, string> {\n const manifest: Record<string, string> = {};\n Object.entries(metafile.outputs).forEach(([outputPath, meta]) => {\n if (!meta.entryPoint) return;\n\n const entryPath = path.relative(sourceDirectory, meta.entryPoint);\n const assetPath = path.relative(buildDirectory, outputPath);\n manifest[entryPath] = assetPath;\n });\n return manifest;\n}\n\nexport async function build(\n sourceDirectory: string,\n buildDirectory: string,\n): Promise<AssetsManifest> {\n // Remove existing assets to ensure that no stale assets are left behind.\n await fs.remove(buildDirectory);\n\n const metafile = await buildAssets(sourceDirectory, buildDirectory);\n const manifest = makeManifest(metafile, sourceDirectory, buildDirectory);\n const manifestPath = path.join(buildDirectory, 'manifest.json');\n await fs.writeJSON(manifestPath, manifest);\n\n return manifest;\n}\n"]}
|
package/dist/index.test.js
CHANGED
|
@@ -1,53 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const get_port_1 = __importDefault(require("get-port"));
|
|
10
|
-
const chai_1 = require("chai");
|
|
11
|
-
const express_1 = __importDefault(require("express"));
|
|
12
|
-
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
13
|
-
const index_1 = require("./index");
|
|
1
|
+
import tmp from 'tmp-promise';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import getPort from 'get-port';
|
|
5
|
+
import { assert } from 'chai';
|
|
6
|
+
import express from 'express';
|
|
7
|
+
import fetch from 'node-fetch';
|
|
8
|
+
import { init, close, handler, build, compiledScriptPath, compiledStylesheetPath, } from './index.js';
|
|
14
9
|
async function testProject(options) {
|
|
15
|
-
await
|
|
10
|
+
await tmp.withDir(async (dir) => {
|
|
16
11
|
// macOS does weird things with symlinks in its tmp directories. Resolve
|
|
17
12
|
// the real path so that our asset-building machinery doesn't get confused.
|
|
18
|
-
const tmpDir = await
|
|
19
|
-
const scriptsRoot =
|
|
20
|
-
await
|
|
21
|
-
const stylesRoot =
|
|
22
|
-
await
|
|
23
|
-
const jsScriptPath =
|
|
24
|
-
await
|
|
25
|
-
const tsScriptPath =
|
|
26
|
-
await
|
|
27
|
-
const stylesPath =
|
|
28
|
-
await
|
|
13
|
+
const tmpDir = await fs.realpath(dir.path);
|
|
14
|
+
const scriptsRoot = path.join(tmpDir, 'assets', 'scripts');
|
|
15
|
+
await fs.ensureDir(scriptsRoot);
|
|
16
|
+
const stylesRoot = path.join(tmpDir, 'assets', 'stylesheets');
|
|
17
|
+
await fs.ensureDir(stylesRoot);
|
|
18
|
+
const jsScriptPath = path.join(scriptsRoot, 'foo.js');
|
|
19
|
+
await fs.writeFile(jsScriptPath, 'console.log("foo")');
|
|
20
|
+
const tsScriptPath = path.join(scriptsRoot, 'bar.ts');
|
|
21
|
+
await fs.writeFile(tsScriptPath, 'interface Foo {};\n\nconsole.log("bar")');
|
|
22
|
+
const stylesPath = path.join(stylesRoot, 'baz.css');
|
|
23
|
+
await fs.writeFile(stylesPath, 'body { color: red; }');
|
|
29
24
|
if (!options.dev) {
|
|
30
|
-
await
|
|
25
|
+
await build(path.join(tmpDir, 'assets'), path.join(tmpDir, 'public', 'build'));
|
|
31
26
|
}
|
|
32
|
-
await
|
|
33
|
-
sourceDirectory:
|
|
34
|
-
buildDirectory:
|
|
27
|
+
await init({
|
|
28
|
+
sourceDirectory: path.join(tmpDir, 'assets'),
|
|
29
|
+
buildDirectory: path.join(tmpDir, 'public', 'build'),
|
|
35
30
|
publicPath: '/build',
|
|
36
31
|
...options,
|
|
37
32
|
});
|
|
38
|
-
const port = await (
|
|
39
|
-
const app = (
|
|
40
|
-
app.use('/build',
|
|
33
|
+
const port = await getPort();
|
|
34
|
+
const app = express();
|
|
35
|
+
app.use('/build', handler());
|
|
41
36
|
const server = app.listen(port);
|
|
42
37
|
try {
|
|
43
|
-
const jsRes = await (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const cssRes = await (
|
|
47
|
-
|
|
38
|
+
const jsRes = await fetch(`http://localhost:${port}${compiledScriptPath('foo.js')}`);
|
|
39
|
+
assert.isTrue(jsRes.ok);
|
|
40
|
+
assert.match(await jsRes.text(), /console\.log\("foo"\)/);
|
|
41
|
+
const cssRes = await fetch(`http://localhost:${port}${compiledStylesheetPath('baz.css')}`);
|
|
42
|
+
assert.isTrue(cssRes.ok);
|
|
48
43
|
const cssText = await cssRes.text();
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
assert.match(cssText, /body\s*\{/);
|
|
45
|
+
assert.match(cssText, /color:\s*red/);
|
|
51
46
|
}
|
|
52
47
|
finally {
|
|
53
48
|
server.close();
|
|
@@ -57,7 +52,7 @@ async function testProject(options) {
|
|
|
57
52
|
});
|
|
58
53
|
}
|
|
59
54
|
describe('compiled-assets', () => {
|
|
60
|
-
afterEach(async () =>
|
|
55
|
+
afterEach(async () => close());
|
|
61
56
|
it('works in dev mode', async () => {
|
|
62
57
|
await testProject({ dev: true });
|
|
63
58
|
});
|
package/dist/index.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import tmp from 'tmp-promise';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport getPort from 'get-port';\nimport { assert } from 'chai';\nimport express from 'express';\nimport fetch from 'node-fetch';\n\nimport {\n init,\n close,\n handler,\n build,\n compiledScriptPath,\n compiledStylesheetPath,\n type CompiledAssetsOptions,\n} from './index.js';\n\nasync function testProject(options: CompiledAssetsOptions) {\n await tmp.withDir(\n async (dir) => {\n // macOS does weird things with symlinks in its tmp directories. Resolve\n // the real path so that our asset-building machinery doesn't get confused.\n const tmpDir = await fs.realpath(dir.path);\n\n const scriptsRoot = path.join(tmpDir, 'assets', 'scripts');\n await fs.ensureDir(scriptsRoot);\n\n const stylesRoot = path.join(tmpDir, 'assets', 'stylesheets');\n await fs.ensureDir(stylesRoot);\n\n const jsScriptPath = path.join(scriptsRoot, 'foo.js');\n await fs.writeFile(jsScriptPath, 'console.log(\"foo\")');\n\n const tsScriptPath = path.join(scriptsRoot, 'bar.ts');\n await fs.writeFile(tsScriptPath, 'interface Foo {};\\n\\nconsole.log(\"bar\")');\n\n const stylesPath = path.join(stylesRoot, 'baz.css');\n await fs.writeFile(stylesPath, 'body { color: red; }');\n\n if (!options.dev) {\n await build(path.join(tmpDir, 'assets'), path.join(tmpDir, 'public', 'build'));\n }\n\n await init({\n sourceDirectory: path.join(tmpDir, 'assets'),\n buildDirectory: path.join(tmpDir, 'public', 'build'),\n publicPath: '/build',\n ...options,\n });\n\n const port = await getPort();\n const app = express();\n app.use('/build', handler());\n const server = app.listen(port);\n\n try {\n const jsRes = await fetch(`http://localhost:${port}${compiledScriptPath('foo.js')}`);\n assert.isTrue(jsRes.ok);\n assert.match(await jsRes.text(), /console\\.log\\(\"foo\"\\)/);\n\n const cssRes = await fetch(`http://localhost:${port}${compiledStylesheetPath('baz.css')}`);\n assert.isTrue(cssRes.ok);\n const cssText = await cssRes.text();\n assert.match(cssText, /body\\s*\\{/);\n assert.match(cssText, /color:\\s*red/);\n } finally {\n server.close();\n }\n },\n {\n unsafeCleanup: true,\n },\n );\n}\n\ndescribe('compiled-assets', () => {\n afterEach(async () => close());\n\n it('works in dev mode', async () => {\n await testProject({ dev: true });\n });\n\n it('works in prod mode', async () => {\n await testProject({ dev: false });\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prairielearn/compiled-assets",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"main": "dist/index.js",
|
|
5
6
|
"bin": "dist/cli.js",
|
|
6
7
|
"repository": {
|
|
@@ -11,10 +12,10 @@
|
|
|
11
12
|
"scripts": {
|
|
12
13
|
"build": "tsc",
|
|
13
14
|
"dev": "tsc --watch --preserveWatchOutput",
|
|
14
|
-
"test": "mocha
|
|
15
|
+
"test": "mocha src/**/*.test.ts"
|
|
15
16
|
},
|
|
16
17
|
"dependencies": {
|
|
17
|
-
"@prairielearn/html": "^
|
|
18
|
+
"@prairielearn/html": "^4.0.0",
|
|
18
19
|
"commander": "^12.0.0",
|
|
19
20
|
"esbuild": "^0.19.12",
|
|
20
21
|
"express": "^4.19.2",
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
"get-port": "^5.1.1",
|
|
32
33
|
"mocha": "^10.4.0",
|
|
33
34
|
"node-fetch": "^2.7.0",
|
|
34
|
-
"tsx": "^4.
|
|
35
|
+
"tsx": "^4.9.3",
|
|
35
36
|
"typescript": "^5.4.3"
|
|
36
37
|
}
|
|
37
38
|
}
|