@jsenv/core 40.12.12 → 40.12.14

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.
@@ -1,20 +1,49 @@
1
1
  const installImportMetaCssBuild = (importMeta) => {
2
- const stylesheet = new CSSStyleSheet({ baseUrl: importMeta.url });
2
+ const IMPORT_META_CSS_BUILD = "jsenv_import_meta_css_build";
3
3
 
4
- let called = false;
5
- // eslint-disable-next-line accessor-pairs
4
+ if (importMeta.css === IMPORT_META_CSS_BUILD) {
5
+ return;
6
+ }
7
+
8
+ const stylesheetMap = new Map();
9
+ const adopt = (url, value) => {
10
+ const stylesheet = new CSSStyleSheet({ baseUrl: importMeta.url });
11
+ stylesheet.replaceSync(value);
12
+ stylesheetMap.set(url, stylesheet);
13
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
14
+ };
15
+ const update = (url, value) => {
16
+ stylesheetMap.get(url).replaceSync(value);
17
+ };
18
+ const remove = (url) => {
19
+ const stylesheet = stylesheetMap.get(url);
20
+ document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
21
+ (s) => s !== stylesheet,
22
+ );
23
+ stylesheetMap.delete(url);
24
+ };
25
+
26
+ const currentCssSourceMap = new Map();
6
27
  Object.defineProperty(importMeta, "css", {
7
28
  configurable: true,
8
- set(value) {
9
- if (called) {
10
- throw new Error("import.meta.css setter can only be called once");
29
+ get() {
30
+ return IMPORT_META_CSS_BUILD;
31
+ },
32
+ set([value, url]) {
33
+ if (value === undefined) {
34
+ if (stylesheetMap.has(url)) {
35
+ remove(url);
36
+ currentCssSourceMap.delete(url);
37
+ }
38
+ return;
39
+ }
40
+ if (!stylesheetMap.has(url)) {
41
+ adopt(url, value);
42
+ currentCssSourceMap.set(url, value);
43
+ } else if (currentCssSourceMap.get(url) !== value) {
44
+ update(url, value);
45
+ currentCssSourceMap.set(url, value);
11
46
  }
12
- called = true;
13
- stylesheet.replaceSync(value);
14
- document.adoptedStyleSheets = [
15
- ...document.adoptedStyleSheets,
16
- stylesheet,
17
- ];
18
47
  },
19
48
  });
20
49
  };
@@ -1,48 +1,60 @@
1
1
  const installImportMetaCssDev = (importMeta) => {
2
- let cssText = "";
3
- let stylesheet = new CSSStyleSheet({ baseUrl: importMeta.url });
4
- let adopted = false;
2
+ const IMPORT_META_CSS_DEV = "jsenv_import_meta_css_dev";
5
3
 
6
- const css = {
7
- toString: () => cssText,
8
- update: (value) => {
9
- cssText = value;
10
- cssText += `
4
+ // useless today but browser might catch up to display it in devtools
5
+ const addUrlInfo = (cssText) => {
6
+ let cssTextWithUrlInfo = cssText;
7
+ cssTextWithUrlInfo += `
11
8
  /* sourceURL=${importMeta.url} */
12
9
  /* inlined from ${importMeta.url} */`;
13
- stylesheet.replaceSync(cssText);
14
- },
15
- inject: () => {
16
- if (!adopted) {
17
- document.adoptedStyleSheets = [
18
- ...document.adoptedStyleSheets,
19
- stylesheet,
20
- ];
21
- adopted = true;
22
- }
23
- },
24
- remove: () => {
25
- if (adopted) {
26
- document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
27
- (s) => s !== stylesheet,
28
- );
29
- adopted = false;
30
- }
31
- },
10
+ return cssTextWithUrlInfo;
11
+ };
12
+
13
+ let stylesheet;
14
+ const adopt = (value) => {
15
+ stylesheet = new CSSStyleSheet({ baseUrl: importMeta.url });
16
+ stylesheet.replaceSync(addUrlInfo(value));
17
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
18
+ };
19
+ const update = (value) => {
20
+ stylesheet.replaceSync(addUrlInfo(value));
21
+ };
22
+ const remove = () => {
23
+ document.adoptedStyleSheets = document.adoptedStyleSheets.filter(
24
+ (s) => s !== stylesheet,
25
+ );
32
26
  };
33
27
 
28
+ let currentCssSource;
34
29
  Object.defineProperty(importMeta, "css", {
35
30
  configurable: true,
36
31
  get() {
37
- return css;
32
+ return IMPORT_META_CSS_DEV;
38
33
  },
39
34
  set(value) {
40
- css.update(value);
41
- css.inject();
35
+ if (value === undefined) {
36
+ if (stylesheet) {
37
+ remove();
38
+ stylesheet = undefined;
39
+ currentCssSource = undefined;
40
+ }
41
+ return;
42
+ }
43
+ if (!stylesheet) {
44
+ adopt(value);
45
+ currentCssSource = value;
46
+ } else if (currentCssSource !== value) {
47
+ update(value);
48
+ currentCssSource = value;
49
+ }
42
50
  },
43
51
  });
44
52
 
45
- return css.remove;
53
+ return () => {
54
+ remove();
55
+ stylesheet = undefined;
56
+ currentCssSource = undefined;
57
+ };
46
58
  };
47
59
 
48
60
  export { installImportMetaCssDev };
@@ -1394,76 +1394,6 @@ const createTaskLog = (
1394
1394
  };
1395
1395
  };
1396
1396
 
1397
- const pathnameToExtension = (pathname) => {
1398
- const slashLastIndex = pathname.lastIndexOf("/");
1399
- const filename =
1400
- slashLastIndex === -1 ? pathname : pathname.slice(slashLastIndex + 1);
1401
- if (filename.match(/@([0-9])+(\.[0-9]+)?(\.[0-9]+)?$/)) {
1402
- return "";
1403
- }
1404
- const dotLastIndex = filename.lastIndexOf(".");
1405
- if (dotLastIndex === -1) {
1406
- return "";
1407
- }
1408
- // if (dotLastIndex === pathname.length - 1) return ""
1409
- const extension = filename.slice(dotLastIndex);
1410
- return extension;
1411
- };
1412
-
1413
- const resourceToPathname = (resource) => {
1414
- const searchSeparatorIndex = resource.indexOf("?");
1415
- if (searchSeparatorIndex > -1) {
1416
- return resource.slice(0, searchSeparatorIndex);
1417
- }
1418
- const hashIndex = resource.indexOf("#");
1419
- if (hashIndex > -1) {
1420
- return resource.slice(0, hashIndex);
1421
- }
1422
- return resource;
1423
- };
1424
-
1425
- const urlToScheme = (url) => {
1426
- const urlString = String(url);
1427
- const colonIndex = urlString.indexOf(":");
1428
- if (colonIndex === -1) {
1429
- return "";
1430
- }
1431
-
1432
- const scheme = urlString.slice(0, colonIndex);
1433
- return scheme;
1434
- };
1435
-
1436
- const urlToResource = (url) => {
1437
- const scheme = urlToScheme(url);
1438
-
1439
- if (scheme === "file") {
1440
- const urlAsStringWithoutFileProtocol = String(url).slice("file://".length);
1441
- return urlAsStringWithoutFileProtocol;
1442
- }
1443
-
1444
- if (scheme === "https" || scheme === "http") {
1445
- // remove origin
1446
- const afterProtocol = String(url).slice(scheme.length + "://".length);
1447
- const pathnameSlashIndex = afterProtocol.indexOf("/", "://".length);
1448
- const urlAsStringWithoutOrigin = afterProtocol.slice(pathnameSlashIndex);
1449
- return urlAsStringWithoutOrigin;
1450
- }
1451
-
1452
- const urlAsStringWithoutProtocol = String(url).slice(scheme.length + 1);
1453
- return urlAsStringWithoutProtocol;
1454
- };
1455
-
1456
- const urlToPathname = (url) => {
1457
- const resource = urlToResource(url);
1458
- const pathname = resourceToPathname(resource);
1459
- return pathname;
1460
- };
1461
-
1462
- const urlToExtension = (url) => {
1463
- const pathname = urlToPathname(url);
1464
- return pathnameToExtension(pathname);
1465
- };
1466
-
1467
1397
  const transformUrlPathname = (url, transformer) => {
1468
1398
  if (typeof url === "string") {
1469
1399
  const urlObject = new URL(url);
@@ -1576,4 +1506,4 @@ const assertAndNormalizeDirectoryUrl = (
1576
1506
  return value;
1577
1507
  };
1578
1508
 
1579
- export { Abort, assertAndNormalizeDirectoryUrl, createLogger, createTaskLog, raceProcessTeardownEvents, urlToExtension, urlToPathname };
1509
+ export { Abort, assertAndNormalizeDirectoryUrl, createLogger, createTaskLog, raceProcessTeardownEvents };
@@ -1,6 +1,6 @@
1
- import { startServer, jsenvServiceCORS, jsenvAccessControlAllowedHeaders, jsenvServiceErrorHandler, createFileSystemFetch } from "@jsenv/server";
1
+ import { startServer, serverPluginCORS, jsenvAccessControlAllowedHeaders, serverPluginStaticFiles, serverPluginErrorHandler } from "@jsenv/server";
2
2
  import { existsSync } from "node:fs";
3
- import { assertAndNormalizeDirectoryUrl, createLogger, Abort, raceProcessTeardownEvents, createTaskLog, urlToExtension, urlToPathname } from "./jsenv_core_packages.js";
3
+ import { assertAndNormalizeDirectoryUrl, createLogger, Abort, raceProcessTeardownEvents, createTaskLog } from "./jsenv_core_packages.js";
4
4
  import "./jsenv_core_node_modules.js";
5
5
  import "node:process";
6
6
  import "node:os";
@@ -35,7 +35,7 @@ const startBuildServer = async ({
35
35
  buildMainFilePath = "index.html",
36
36
  port = 9779,
37
37
  routes,
38
- services = [],
38
+ serverPlugins = [],
39
39
  acceptAnyIp,
40
40
  hostname,
41
41
  https,
@@ -119,8 +119,8 @@ const startBuildServer = async ({
119
119
  serverTiming: true,
120
120
  requestWaitingMs: 60_000,
121
121
  routes,
122
- services: [
123
- jsenvServiceCORS({
122
+ plugins: [
123
+ serverPluginCORS({
124
124
  accessControlAllowRequestOrigin: true,
125
125
  accessControlAllowRequestMethod: true,
126
126
  accessControlAllowRequestHeaders: true,
@@ -128,13 +128,13 @@ const startBuildServer = async ({
128
128
  accessControlAllowCredentials: true,
129
129
  timingAllowOrigin: true,
130
130
  }),
131
- ...services,
132
- jsenvBuildFileService({
133
- buildDirectoryUrl,
134
- buildMainFilePath,
131
+ ...serverPlugins,
132
+ serverPluginStaticFiles({
133
+ directoryUrl: buildDirectoryUrl,
134
+ mainFilePath: buildMainFilePath,
135
135
  }),
136
- jsenvServiceErrorHandler({
137
- sendErrorDetails: true,
136
+ serverPluginErrorHandler({
137
+ sendErrorDetails: false,
138
138
  }),
139
139
  ],
140
140
  });
@@ -156,49 +156,4 @@ const startBuildServer = async ({
156
156
  };
157
157
  };
158
158
 
159
- const jsenvBuildFileService = ({ buildDirectoryUrl, buildMainFilePath }) => {
160
- return {
161
- name: "jsenv:build_files",
162
- routes: [
163
- {
164
- endpoint: "GET *",
165
- description: "Serve static files.",
166
- fetch: (request, helpers) => {
167
- const urlIsVersioned = new URL(request.url).searchParams.has("v");
168
- if (buildMainFilePath && request.resource === "/") {
169
- request = {
170
- ...request,
171
- resource: `/${buildMainFilePath}`,
172
- };
173
- }
174
- const urlObject = new URL(
175
- request.resource.slice(1),
176
- buildDirectoryUrl,
177
- );
178
- return createFileSystemFetch(buildDirectoryUrl, {
179
- cacheControl: urlIsVersioned
180
- ? `private,max-age=${SECONDS_IN_30_DAYS},immutable`
181
- : "private,max-age=0,must-revalidate",
182
- etagEnabled: true,
183
- compressionEnabled: true,
184
- rootDirectoryUrl: buildDirectoryUrl,
185
- canReadDirectory: true,
186
- ENOENTFallback: () => {
187
- if (
188
- !urlToExtension(urlObject) &&
189
- !urlToPathname(urlObject).endsWith("/")
190
- ) {
191
- return new URL(buildMainFilePath, buildDirectoryUrl);
192
- }
193
- return null;
194
- },
195
- })(request, helpers);
196
- },
197
- },
198
- ],
199
- };
200
- };
201
-
202
- const SECONDS_IN_30_DAYS = 60 * 60 * 24 * 30;
203
-
204
159
  export { startBuildServer };