@antelopejs/dms-frontend 0.2.2 → 0.2.3

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/README.md CHANGED
@@ -94,9 +94,11 @@ URL, either through `-b` or through the enclosing antelope project's
94
94
  `.antelope/dev.json`, and say so on exit 1 when they have neither;
95
95
  `verify-source` needs `--layer` instead.
96
96
 
97
- The CLI checks npm for a newer release at most once a day a failed lookup
98
- counts as the day's attempt and prints a one-line notice on stderr. The
99
- throttle stamp lives at `~/.antelopejs/dms-frontend/update-check.json`. Set
97
+ The CLI checks npm for a newer release at most once a day and prints a one-line
98
+ notice on stderr. A lookup that comes back empty offline, throttled, or simply
99
+ raced by a command that blocked the event loop past the deadline — is retried
100
+ after an hour instead of counting as the day's attempt. The throttle stamp lives
101
+ at `~/.antelopejs/dms-frontend/update-check.json`. Set
100
102
  `NO_UPDATE_NOTIFIER=1`, pass `--no-update-check`, or run under `CI` to turn the
101
103
  check off.
102
104
 
package/dist/fs-sync.js CHANGED
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.stripExtendedLengthPrefix = stripExtendedLengthPrefix;
7
+ exports.toPosixPath = toPosixPath;
7
8
  exports.isBlocklistedCopyPath = isBlocklistedCopyPath;
8
9
  exports.sanitizedPackageContent = sanitizedPackageContent;
9
10
  exports.filesIdentical = filesIdentical;
@@ -18,11 +19,14 @@ const config_1 = require("./config");
18
19
  function stripExtendedLengthPrefix(p) {
19
20
  return p.replace(/^\\\\\?\\/, "");
20
21
  }
22
+ function toPosixPath(path, separator = node_path_1.sep) {
23
+ return separator === "/" ? path : path.split(separator).join("/");
24
+ }
21
25
  function isBlocklistedCopyPath(src, srcPath) {
22
26
  const rel = (0, node_path_1.relative)((0, node_path_1.resolve)(stripExtendedLengthPrefix(src)), (0, node_path_1.resolve)(stripExtendedLengthPrefix(srcPath)));
23
27
  if (!rel || rel.startsWith(".."))
24
28
  return false;
25
- return config_1.layerCopyIgnore.ignores(rel.split(node_path_1.sep).join("/"));
29
+ return config_1.layerCopyIgnore.ignores(toPosixPath(rel));
26
30
  }
27
31
  function sanitizedPackageContent(raw) {
28
32
  const pkg = JSON.parse(raw);
@@ -198,7 +198,7 @@ function discoverAssets(registry, directory, extensions) {
198
198
  .sort()
199
199
  .map((relativePath) => ({
200
200
  moduleId: module.id,
201
- relativePath: `${assetRoot.relativePrefix}${(0, node_path_1.join)(directory, relativePath).split(node_path_1.sep).join("/")}`,
201
+ relativePath: `${assetRoot.relativePrefix}${(0, fs_sync_1.toPosixPath)((0, node_path_1.join)(directory, relativePath))}`,
202
202
  }));
203
203
  });
204
204
  });
@@ -259,7 +259,7 @@ function writeShortcutExports(workspaceDir, registry) {
259
259
  }
260
260
  function writeDmsMainCss(workspaceDir, layers) {
261
261
  const sources = layers
262
- .map((layer) => `@source "${(0, layers_1.getLayerWorkspacePath)(workspaceDir, layer)}/${config_1.TAILWIND_SOURCE_GLOB}";`)
262
+ .map((layer) => `@source "${(0, fs_sync_1.toPosixPath)((0, layers_1.getLayerWorkspacePath)(workspaceDir, layer))}/${config_1.TAILWIND_SOURCE_GLOB}";`)
263
263
  .join("\n");
264
264
  const content = `@import "tailwindcss";
265
265
  @import "@nuxt/ui";
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.NO_UPDATE_CHECK_FLAG = exports.UPDATE_CHECK_TIMEOUT_MS = exports.UPDATE_CHECK_INTERVAL_MS = exports.UPDATE_CHECK_PACKAGE = void 0;
6
+ exports.NO_UPDATE_CHECK_FLAG = exports.UPDATE_CHECK_TIMEOUT_MS = exports.UPDATE_CHECK_RETRY_INTERVAL_MS = exports.UPDATE_CHECK_INTERVAL_MS = exports.UPDATE_CHECK_PACKAGE = void 0;
7
7
  exports.stripUpdateCheckFlag = stripUpdateCheckFlag;
8
8
  exports.isUpdateCheckEnabled = isUpdateCheckEnabled;
9
9
  exports.updateCheckCacheFile = updateCheckCacheFile;
@@ -18,6 +18,7 @@ const config_1 = require("./config");
18
18
  exports.UPDATE_CHECK_PACKAGE = "@antelopejs/dms-frontend";
19
19
  const DEFAULT_REGISTRY_URL = "https://registry.npmjs.org/";
20
20
  exports.UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
21
+ exports.UPDATE_CHECK_RETRY_INTERVAL_MS = 60 * 60 * 1000;
21
22
  exports.UPDATE_CHECK_TIMEOUT_MS = 3000;
22
23
  exports.NO_UPDATE_CHECK_FLAG = "--no-update-check";
23
24
  const HELP_OR_VERSION_FLAGS = ["--help", "-h", "--version", "-v"];
@@ -73,7 +74,11 @@ function readCache(file) {
73
74
  if (latestVersion !== undefined && typeof latestVersion !== "string") {
74
75
  return undefined;
75
76
  }
76
- return { checkedAt: parsed.checkedAt, latestVersion };
77
+ const succeeded = parsed.succeeded;
78
+ if (succeeded !== undefined && typeof succeeded !== "boolean") {
79
+ return undefined;
80
+ }
81
+ return { checkedAt: parsed.checkedAt, latestVersion, succeeded };
77
82
  }
78
83
  catch {
79
84
  return undefined;
@@ -156,13 +161,20 @@ async function checkForUpdate(options) {
156
161
  return;
157
162
  const cached = readCache(cacheFile);
158
163
  const checkedAt = now();
159
- const withinInterval = cached !== undefined &&
160
- checkedAt - cached.checkedAt < exports.UPDATE_CHECK_INTERVAL_MS;
164
+ const lastAttemptAnswered = cached?.succeeded ?? cached?.latestVersion !== undefined;
165
+ const interval = lastAttemptAnswered
166
+ ? exports.UPDATE_CHECK_INTERVAL_MS
167
+ : exports.UPDATE_CHECK_RETRY_INTERVAL_MS;
168
+ const withinInterval = cached !== undefined && checkedAt - cached.checkedAt < interval;
161
169
  let latestVersion = cached?.latestVersion;
162
170
  if (!withinInterval) {
163
- latestVersion =
164
- (await fetchLatestVersion(exports.UPDATE_CHECK_PACKAGE)) ?? latestVersion;
165
- writeCache(cacheFile, { checkedAt, latestVersion });
171
+ const published = await fetchLatestVersion(exports.UPDATE_CHECK_PACKAGE);
172
+ latestVersion = published ?? latestVersion;
173
+ writeCache(cacheFile, {
174
+ checkedAt,
175
+ latestVersion,
176
+ succeeded: published !== undefined,
177
+ });
166
178
  }
167
179
  if (latestVersion && isNewer(currentVersion, latestVersion)) {
168
180
  write(formatNotice(currentVersion, latestVersion));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antelopejs/dms-frontend",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Frontend-agnostic loader for AntelopeJS DMS, shipping the Vue 3 renderer (Vite, Inertia, SSR)",
5
5
  "keywords": [
6
6
  "antelope",
@@ -16,7 +16,7 @@
16
16
  // any pre-existing link with that attribute and then skips `updateStyle` for
17
17
  // it, which would leave CSS edits stranded.
18
18
 
19
- import { join } from "node:path";
19
+ import { join, sep } from "node:path";
20
20
  import { fileURLToPath } from "node:url";
21
21
  import { pageModulePreloads } from "./client-manifest.mjs";
22
22
 
@@ -32,8 +32,16 @@ const STYLE_EXTENSION =
32
32
  * one `@source` per materialized module — nearly every rule a page needs.
33
33
  * Naming it is the one enumeration this module accepts, and the comment is the
34
34
  * reason why.
35
+ *
36
+ * `ENTRY_STYLESHEET_ID` is matched against the `data-vite-dev-id` Vite puts on
37
+ * its own copy, and Vite normalizes every module id onto POSIX separators — so
38
+ * the native path `join` returns has to be normalized too, or the handover
39
+ * never happens on Windows and both copies stay in the document.
35
40
  */
36
41
  const ENTRY_STYLESHEET = "/dms-main.css";
42
+ const ENTRY_STYLESHEET_ID = join(PROJECT_ROOT, "dms-main.css")
43
+ .split(sep)
44
+ .join("/");
37
45
 
38
46
  function ssrModuleGraph(devServer) {
39
47
  return devServer.environments?.ssr?.moduleGraph ?? devServer.moduleGraph;
@@ -75,7 +83,7 @@ async function inlineTag(devServer, { url, id }) {
75
83
  export async function developmentStyleTags(devServer) {
76
84
  const modules = styleModules(devServer);
77
85
  const links = [
78
- { url: ENTRY_STYLESHEET, id: join(PROJECT_ROOT, "dms-main.css") },
86
+ { url: ENTRY_STYLESHEET, id: ENTRY_STYLESHEET_ID },
79
87
  ...modules.filter(({ url }) => !SFC_STYLE.test(url)),
80
88
  ].map(linkTag);
81
89
  const inlined = await Promise.all(
@@ -1,6 +1,6 @@
1
1
  import { createReadStream, existsSync, readFileSync, statSync } from "node:fs";
2
2
  import { createServer } from "node:http";
3
- import { extname, join, resolve } from "node:path";
3
+ import { extname, join, resolve, sep } from "node:path";
4
4
  import { Readable } from "node:stream";
5
5
  import { pipeline } from "node:stream/promises";
6
6
  import { fileURLToPath } from "node:url";
@@ -254,7 +254,9 @@ function acceptedAsset(pathname, request) {
254
254
 
255
255
  function serveAsset(pathname, request, response) {
256
256
  const selected = acceptedAsset(pathname, request);
257
- const assetRoot = `${resolve(PROJECT_ROOT, "dist/client")}/`;
257
+ // Native separator: `selected.source` comes from `resolve`, so a hardcoded
258
+ // `/` here would make the containment check fail for every asset on Windows.
259
+ const assetRoot = `${resolve(PROJECT_ROOT, "dist/client")}${sep}`;
258
260
  if (
259
261
  !selected.source.startsWith(assetRoot) ||
260
262
  !existsSync(selected.file) ||
@@ -2,7 +2,7 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
2
  import { basename, resolve } from "node:path";
3
3
  import ui from "@nuxt/ui/vite";
4
4
  import vue from "@vitejs/plugin-vue";
5
- import { defineConfig, type Plugin } from "vite";
5
+ import { defineConfig, normalizePath, type Plugin } from "vite";
6
6
  import { orderHeadForFirstPaint } from "./head-order.mjs";
7
7
 
8
8
  interface FrontendModuleRegistryEntry {
@@ -38,6 +38,14 @@ const stableModuleAliases = Object.fromEntries(
38
38
  return [[`#${moduleName}`, module.root]];
39
39
  }),
40
40
  );
41
+ /**
42
+ * Globs are POSIX, always.
43
+ *
44
+ * `resolve` returns a native path, so on Windows every pattern below would
45
+ * carry backslashes — which a glob matcher reads as escape characters, not as
46
+ * separators, and which therefore match nothing at all. `normalizePath` is
47
+ * Vite's own answer to this and is the identity function on POSIX.
48
+ */
41
49
  const importDirectories = frontendSourceRoots.flatMap((root) =>
42
50
  [
43
51
  "app/composables/**/*",
@@ -45,7 +53,7 @@ const importDirectories = frontendSourceRoots.flatMap((root) =>
45
53
  "app/utils/**/*",
46
54
  "app/build/composables/**/*",
47
55
  "app/build/types/**/*",
48
- ].map((glob) => ({ glob: resolve(root, glob), types: true })),
56
+ ].map((glob) => ({ glob: normalizePath(resolve(root, glob)), types: true })),
49
57
  );
50
58
  const optimizedDependencies = [
51
59
  "vue",
@@ -80,6 +88,9 @@ const optimizedDependencies = [
80
88
  * told to reload the whole document. Crawling the module sources once, at
81
89
  * startup, pays that cost a single time and in a place where it reads as
82
90
  * startup rather than as a crash.
91
+ *
92
+ * Normalized for the same reason as `importDirectories`: Vite hands these
93
+ * patterns straight to its glob matcher without touching the separators.
83
94
  */
84
95
  const optimizerEntries = [
85
96
  resolve(__dirname, "main.ts"),
@@ -88,7 +99,7 @@ const optimizerEntries = [
88
99
  resolve(root, "app/**/*.vue"),
89
100
  resolve(root, "app/**/*.ts"),
90
101
  ]),
91
- ];
102
+ ].map(normalizePath);
92
103
 
93
104
  function paintBeforeHydrate(): Plugin {
94
105
  return {
@@ -125,7 +136,13 @@ export default defineConfig({
125
136
  imports: [
126
137
  "vue",
127
138
  {
128
- [resolve(__dirname, "frontend-module.ts")]: [
139
+ // This key is inlined verbatim as the module specifier of the
140
+ // import the auto-importer prepends to each file. A native Windows
141
+ // path would land inside a single-quoted JavaScript string with its
142
+ // backslashes intact, where `\U`, `\M` and `\f` are read as escape
143
+ // sequences: the specifier the bundler then resolves is a mangled
144
+ // path that cannot exist. Keep it POSIX.
145
+ [normalizePath(resolve(__dirname, "frontend-module.ts"))]: [
129
146
  "$fetch",
130
147
  "abortNavigation",
131
148
  "clearError",
@@ -2,7 +2,7 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
2
  import { basename, resolve } from "node:path";
3
3
  import vue from "@vitejs/plugin-vue";
4
4
  import AutoImport from "unplugin-auto-import/vite";
5
- import { defineConfig } from "vite";
5
+ import { defineConfig, normalizePath } from "vite";
6
6
 
7
7
  interface FrontendModuleRegistryEntry {
8
8
  id: string;
@@ -55,7 +55,10 @@ export default defineConfig({
55
55
  dts: false,
56
56
  imports: [
57
57
  {
58
- [resolve(__dirname, "email-runtime.ts")]: [
58
+ // Inlined verbatim as a module specifier in the generated import, so
59
+ // it has to be POSIX: a native Windows path would reach the parser
60
+ // with its backslashes read as string escapes. See vite.config.ts.
61
+ [normalizePath(resolve(__dirname, "email-runtime.ts"))]: [
59
62
  "useDmsAppConfig",
60
63
  "useDmsRuntimeConfig",
61
64
  "defineAppConfig",