aboutsummaryrefslogtreecommitdiffstats
path: root/config/srcPlugin.js
diff options
context:
space:
mode:
Diffstat (limited to 'config/srcPlugin.js')
-rw-r--r--config/srcPlugin.js85
1 files changed, 85 insertions, 0 deletions
diff --git a/config/srcPlugin.js b/config/srcPlugin.js
new file mode 100644
index 0000000..13bee7b
--- /dev/null
+++ b/config/srcPlugin.js
@@ -0,0 +1,85 @@
1/*
2 * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com>
3 *
4 * This file is part of Sophie.
5 *
6 * Sophie is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: AGPL-3.0-only
19 */
20
21import { readFile } from 'node:fs/promises';
22
23/** @type {string} */
24const PLUGIN_NAMESPACE = 'sophie-src';
25
26/** @type {RegExp} */
27// eslint-disable-next-line security/detect-non-literal-regexp -- Argument is const.
28const FILTER_REGEXP = new RegExp(`^${PLUGIN_NAMESPACE}:(.+)$`);
29
30/**
31 * An esbuild plugin that import the source of referenced file or package as a string.
32 *
33 * Prefix the imported file name with `sophie-src:` to import its source instead.
34 *
35 * @type { import('esbuild').Plugin }
36 */
37const srcPlugin = {
38 name: 'sophie-inline-service-inject-plugin',
39 setup(build) {
40 build.onResolve(
41 {
42 filter: FILTER_REGEXP,
43 },
44 async ({ path: pathToResolve, importer, resolveDir }) => {
45 const match = FILTER_REGEXP.exec(pathToResolve);
46 if (match === null) {
47 return {
48 path: '',
49 namespace: PLUGIN_NAMESPACE,
50 errors: [
51 {
52 text: `Could not resolve ${pathToResolve}`,
53 },
54 ],
55 };
56 }
57 const { path, errors, warnings } = await build.resolve(match[1], {
58 importer,
59 resolveDir,
60 kind: 'import-statement',
61 });
62 return {
63 path,
64 namespace: PLUGIN_NAMESPACE,
65 errors,
66 warnings,
67 };
68 },
69 );
70 build.onLoad(
71 {
72 filter: /./,
73 namespace: PLUGIN_NAMESPACE,
74 },
75 async ({ path }) => {
76 const src = await readFile(path, 'utf8');
77 return {
78 contents: `export default ${JSON.stringify(src)};`,
79 };
80 },
81 );
82 },
83};
84
85export default srcPlugin;