@ecopages/core 0.2.0-beta.35 → 0.2.0-beta.37

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecopages/core",
3
- "version": "0.2.0-beta.35",
3
+ "version": "0.2.0-beta.37",
4
4
  "description": "Core package for Ecopages",
5
5
  "keywords": [
6
6
  "ecopages",
@@ -17,14 +17,14 @@
17
17
  "directory": "packages/core"
18
18
  },
19
19
  "dependencies": {
20
- "@ecopages/file-system": "0.2.0-beta.35",
20
+ "@ecopages/file-system": "0.2.0-beta.37",
21
21
  "@ecopages/logger": "^0.2.3",
22
22
  "@ecopages/scripts-injector": "^0.1.5",
23
- "@oxc-project/runtime": "0.134.0",
23
+ "@oxc-project/runtime": "0.141.0",
24
24
  "@worker-tools/html-rewriter": "0.1.0-pre.19",
25
25
  "chokidar": "^5.0.0",
26
26
  "ghtml": "^4.0.2",
27
- "oxc-parser": "^0.124.0",
27
+ "oxc-parser": "^0.141.0",
28
28
  "oxc-resolver": "^11.24.2",
29
29
  "rolldown": "^1.1.0",
30
30
  "ws": "^8.20.1",
@@ -32,7 +32,7 @@
32
32
  "@standard-schema/utils": "^0.3.0"
33
33
  },
34
34
  "peerDependencies": {
35
- "@ecopages/dev-toolbar": "0.2.0-beta.35"
35
+ "@ecopages/dev-toolbar": "0.2.0-beta.37"
36
36
  },
37
37
  "peerDependenciesMeta": {
38
38
  "@ecopages/dev-toolbar": {
@@ -319,6 +319,10 @@
319
319
  "types": "./src/dev-toolbar/define-dev-tool.d.ts",
320
320
  "default": "./src/dev-toolbar/define-dev-tool.js"
321
321
  },
322
+ "./dev-toolbar/dev-toolbar-manifest-contract": {
323
+ "types": "./src/dev-toolbar/dev-toolbar-manifest-contract.d.ts",
324
+ "default": "./src/dev-toolbar/dev-toolbar-manifest-contract.js"
325
+ },
322
326
  "./create-app.ts": {
323
327
  "import": "./src/adapters/create-app.js",
324
328
  "types": "./src/adapters/create-app.d.ts",
@@ -591,6 +595,10 @@
591
595
  "./dev-toolbar/define-dev-tool.ts": {
592
596
  "types": "./src/dev-toolbar/define-dev-tool.d.ts",
593
597
  "default": "./src/dev-toolbar/define-dev-tool.js"
598
+ },
599
+ "./dev-toolbar/dev-toolbar-manifest-contract.ts": {
600
+ "types": "./src/dev-toolbar/dev-toolbar-manifest-contract.d.ts",
601
+ "default": "./src/dev-toolbar/dev-toolbar-manifest-contract.js"
594
602
  }
595
603
  },
596
604
  "types": "./src/index.d.ts"
@@ -1,7 +1,23 @@
1
1
  import path from 'node:path';
2
+ import { fileSystem } from '@ecopages/file-system';
2
3
  import { cachedParseSync } from '../../cache/module-parse-cache.js';
3
4
  import { isBarePackageImportSpecifier, resolveProjectModulePath } from '../../plugins/tsconfig-import-resolver.js';
4
5
  import { resolveDevTransformModuleUrl } from './dev-transform-url.js';
6
+ /**
7
+ * Builds a browser-importable dev-transform URL that changes when the source changes.
8
+ *
9
+ * @remarks
10
+ * Soft HMR reloads cache-bust the active page module, but transitive layout/component
11
+ * imports keep stable pathnames. A content hash query makes the browser ESM module map
12
+ * treat the updated dependency as a new module without a full page reload.
13
+ */
14
+ function resolveVersionedDevTransformModuleUrl(srcDir, resolvedPath) {
15
+ const baseUrl = resolveDevTransformModuleUrl(srcDir, resolvedPath);
16
+ if (!fileSystem.exists(resolvedPath)) {
17
+ return baseUrl;
18
+ }
19
+ return `${baseUrl}?v=${fileSystem.hash(resolvedPath)}`;
20
+ }
5
21
  function isRecord(value) {
6
22
  return Boolean(value) && typeof value === 'object';
7
23
  }
@@ -104,7 +120,7 @@ async function resolveImportSpecifier(options) {
104
120
  return undefined;
105
121
  }
106
122
  options.dependencies.add(resolvedPath);
107
- return resolveDevTransformModuleUrl(options.srcDir, resolvedPath);
123
+ return resolveVersionedDevTransformModuleUrl(options.srcDir, resolvedPath);
108
124
  }
109
125
  return options.resolveVendorUrl(options.specifier);
110
126
  }
@@ -10,19 +10,20 @@ Server-side wiring for the development-only in-browser inspector. Public docs: [
10
10
  | **Client package** (`devToolbar.package`) | Dock UI, panels, and any extra apps |
11
11
  | **Integrations** | Page rendering and browser assets — not toolbar dock apps |
12
12
 
13
- Extend the toolbar by setting `devToolbar.package` to your own client package (or `@ecopages/dev-toolbar`). Integrations do not register dock apps.
13
+ `@ecopages/dev-toolbar` is an optional peer. Core does not import it at runtime unless `devToolbar.package` is configured. The dev manifest contract (`dev-toolbar-manifest-contract.ts`) lives in core so apps and custom toolbar clients can type the payload without installing the reference toolbar package.
14
14
 
15
15
  ## Module map
16
16
 
17
- | File | Role |
18
- | ------------------------------ | -------------------------------------------------------------------------- |
19
- | `dev-toolbar-host.ts` | Enablement, manifest contribution, runtime bundling, HTML injection |
20
- | `dev-toolbar-manifest.ts` | Builds and serializes the per-page dev manifest |
21
- | `dev-toolbar-package.ts` | Resolves `devToolbar.package` bootstrap entry (`bootstrap.js`, then `.ts`) |
22
- | `dev-toolbar-config.ts` | `isDevToolbarEnabled` watch mode, env var, package required |
23
- | `dev-toolbar-html-response.ts` | Adapter helpers for injecting `import '/_dev_toolbar.js'` |
24
- | `dev-toolbar-runtime-paths.ts` | `/_dev_toolbar.js` URL and work-dir paths |
25
- | `define-dev-tool.ts` | Config helper for bring-your-own client packages |
17
+ | File | Role |
18
+ | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19
+ | `dev-toolbar-host.ts` | Enablement, manifest contribution, runtime bundling, HTML injection |
20
+ | `dev-toolbar-manifest-contract.ts` | `#__ECO_DEV_MANIFEST__` id and payload types (public: `@ecopages/core/dev-toolbar/dev-toolbar-manifest-contract`; mirrored in `@ecopages/dev-toolbar` for browser bundling) |
21
+ | `dev-toolbar-manifest.ts` | Builds and serializes the per-page dev manifest |
22
+ | `dev-toolbar-package.ts` | Resolves `devToolbar.package` bootstrap entry (`bootstrap.js`, then `.ts`) |
23
+ | `dev-toolbar-config.ts` | `isDevToolbarEnabled` watch mode, env var, package required |
24
+ | `dev-toolbar-html-response.ts` | Adapter helpers for injecting `import '/_dev_toolbar.js'` |
25
+ | `dev-toolbar-runtime-paths.ts` | `/_dev_toolbar.js` URL and work-dir paths |
26
+ | `define-dev-tool.ts` | Config helper for bring-your-own client packages |
26
27
 
27
28
  ## Injection order
28
29
 
@@ -0,0 +1,22 @@
1
+ /** DOM id core uses when injecting `#__ECO_DEV_MANIFEST__` during watch mode. */
2
+ export declare const DEV_MANIFEST_ELEMENT_ID = "__ECO_DEV_MANIFEST__";
3
+ export type DevManifestAsset = {
4
+ srcUrl?: string;
5
+ kind: 'script' | 'stylesheet';
6
+ packageRole?: string;
7
+ inline?: boolean;
8
+ };
9
+ export type DevManifestPageBrowserGraph = {
10
+ entryAssets: DevManifestAsset[];
11
+ chunkAssets: DevManifestAsset[];
12
+ };
13
+ /**
14
+ * Server-serialized development metadata injected into HTML responses.
15
+ */
16
+ export type EcoDevManifest = {
17
+ route: string;
18
+ integration?: string;
19
+ pageBrowserGraph?: DevManifestPageBrowserGraph;
20
+ vendorUrls: string[];
21
+ devTransformUrls: string[];
22
+ };
@@ -0,0 +1,2 @@
1
+ /** DOM id core uses when injecting `#__ECO_DEV_MANIFEST__` during watch mode. */
2
+ export const DEV_MANIFEST_ELEMENT_ID = '__ECO_DEV_MANIFEST__';
@@ -1,6 +1,6 @@
1
1
  import type { PagePackageResult } from '../types/public-types.js';
2
- export { DEV_MANIFEST_ELEMENT_ID, type DevManifestAsset as DevToolbarManifestAsset, type EcoDevManifest as DevToolbarManifestPayload, } from '@ecopages/dev-toolbar/manifest';
3
- import { type EcoDevManifest } from '@ecopages/dev-toolbar/manifest';
2
+ import { DEV_MANIFEST_ELEMENT_ID, type DevManifestAsset, type EcoDevManifest } from './dev-toolbar-manifest-contract.js';
3
+ export { DEV_MANIFEST_ELEMENT_ID, type DevManifestAsset as DevToolbarManifestAsset, type EcoDevManifest as DevToolbarManifestPayload, };
4
4
  /**
5
5
  * Builds the dev toolbar manifest payload for one rendered page.
6
6
  */
@@ -1,6 +1,6 @@
1
1
  import { DEV_TRANSFORM_URL_PREFIX, VENDOR_URL_PREFIX } from '../hmr/hmr-asset-paths.js';
2
- export { DEV_MANIFEST_ELEMENT_ID, } from '@ecopages/dev-toolbar/manifest';
3
- import { DEV_MANIFEST_ELEMENT_ID } from '@ecopages/dev-toolbar/manifest';
2
+ import { DEV_MANIFEST_ELEMENT_ID, } from './dev-toolbar-manifest-contract.js';
3
+ export { DEV_MANIFEST_ELEMENT_ID, };
4
4
  function serializeAsset(asset) {
5
5
  if (!asset.srcUrl) {
6
6
  return undefined;
package/src/hmr/README.md CHANGED
@@ -34,3 +34,14 @@ Dev client modules are served on demand through `DevTransformServer` (`src/dev/`
34
34
  `BrowserBundleService` is the sole browser-plugin resolver for HMR builds. HMR managers route `hmr-runtime` and `hmr-entrypoint` rebuilds through the `browser-hmr` executor profile.
35
35
 
36
36
  Hosts call `prepareHmrFileChange()` before HMR dispatch (`hmr/hmr-file-change-prep.ts`) so page browser graph sessions invalidate consistently with file changes.
37
+
38
+ ## Client events
39
+
40
+ | Event | Client behavior |
41
+ | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42
+ | `update` | Cache-bust and re-import the changed module URL (or reload the active page module) |
43
+ | `css-update` | Refresh matching stylesheet `link` hrefs |
44
+ | `layout-update` | Soft current-page reload with layout cache cleared (`persistLayouts` remounts the updated layout without a full document reload). Falls back to `location.reload()` only if no navigation owner handles it |
45
+ | `reload` | Full `location.reload()` |
46
+
47
+ Dev-transform local imports are rewritten with a content-hash query (`?v=…`) so transitive layout/component modules get a new ESM module-map key after invalidation. Soft `layout-update` then picks up the new layout while shared outer layout persistence still applies across normal SPA navigations.
@@ -48,10 +48,12 @@ import { applyModuleUpdate, resolveActiveModuleUrl } from './module-update.js';
48
48
  clearCache: true,
49
49
  moduleUrl: getActiveHmrModuleUrl(),
50
50
  })) {
51
+ break;
51
52
  }
52
- else if (!window.__ECOPAGES_HOST_OWNS_RELOAD__) {
53
- location.reload();
53
+ if (window.__ECOPAGES_HOST_OWNS_RELOAD__) {
54
+ break;
54
55
  }
56
+ location.reload();
55
57
  break;
56
58
  }
57
59
  case 'error':