@appshell/runtime 1.0.0-alpha.15

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Navaris Technologies, LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @appshell/runtime
2
+
3
+ The store that delivers a package's runtime configuration (`vars`) to it.
4
+
5
+ This is a **shared singleton**. There is exactly one instance per page, held in the
6
+ module federation share scope, and both the host and every package must declare it as
7
+ such. It replaced `window.__appshell_vars__<scope>`.
8
+
9
+ Most packages should not import this directly — use
10
+ [`@appshell/vars`](../vars/README.md), which supplies the scope for you.
11
+
12
+ ## Contract
13
+
14
+ ```ts
15
+ setVars(scope, vars); // the host, immediately before loading a remote
16
+ readVars(scope); // a package, reading its own configuration
17
+ hasVars(scope); // branch instead of catch
18
+ ```
19
+
20
+ `@appshell/loader` calls `setVars` before it loads a remote, so a package's vars are in
21
+ place before its modules evaluate — including a read at module-eval time.
22
+
23
+ The first write for a scope wins and is frozen. Re-delivering the identical vars is a
24
+ no-op, because the same remote can be mounted more than once; replacing them throws
25
+ `VarsConflictError`.
26
+
27
+ `readVars` throws `MissingVarsError` rather than returning an empty object. A package
28
+ that silently renders with no configuration is the failure this replaced.
29
+
30
+ ## What this does and does not fix
31
+
32
+ Against the global it replaced, it fixes: unbounded, never-cleaned-up keys; silent
33
+ cross-package overwrite; the load-order coupling between host and remote; and being
34
+ untyped and undiscoverable.
35
+
36
+ It **does not make a scope's vars private.** Any code on the page can call
37
+ `readVars('SomeOtherScope')`, and a package that loads early can squat on a scope that
38
+ has not been delivered yet. Nothing short of a separate realm — an iframe, a worker —
39
+ would change that, and none of this is a security boundary. Do not put a secret in
40
+ `vars`; the registry serves them to the browser in the composition either way.
41
+
42
+ ## Setup
43
+
44
+ Both sides declare it, or each ends up with its own empty store:
45
+
46
+ ```js
47
+ new ModuleFederationPlugin({
48
+ shared: {
49
+ '@appshell/runtime': { singleton: true },
50
+ },
51
+ });
52
+ ```
53
+
54
+ `AppshellPlugin` fails the build when a package omits it.
package/dist/main.js ADDED
@@ -0,0 +1 @@
1
+ !function(e,r){if("object"==typeof exports&&"object"==typeof module)module.exports=r();else if("function"==typeof define&&define.amd)define([],r);else{var t=r();for(var s in t)("object"==typeof exports?exports:e)[s]=t[s]}}(self,(()=>(()=>{"use strict";var e={d:(r,t)=>{for(var s in t)e.o(t,s)&&!e.o(r,s)&&Object.defineProperty(r,s,{enumerable:!0,get:t[s]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},r={};e.r(r),e.d(r,{MissingVarsError:()=>t,VarsConflictError:()=>s,hasVars:()=>i,readVars:()=>n,resetVars:()=>c,setVars:()=>a});class t extends Error{constructor(e,r){super(`No vars were delivered for '${e}'. ${r.length?`Vars are present for ${r.map((e=>`'${e}'`)).join(", ")} — check that '${e}' matches the module federation name the registry knows this package by.`:"Nothing has delivered vars on this page — check that the host and this package both declare '@appshell/runtime' as a shared singleton."}`),this.name="MissingVarsError",this.scope=e}}class s extends Error{constructor(e){super(`Vars for '${e}' were already delivered and cannot be replaced. A scope receives its vars once per page load.`),this.name="VarsConflictError",this.scope=e}}const o=new Map,a=(e,r)=>{const t=o.get(e);var a,n;if(t){if(a=t,n=r,![...new Set([...Object.keys(a),...Object.keys(n)])].every((e=>a[e]===n[e])))throw new s(e)}else o.set(e,Object.freeze({...r}))},n=e=>{const r=o.get(e);if(!r)throw new t(e,[...o.keys()]);return r},i=e=>o.has(e),c=()=>{o.clear()};return r})()));
@@ -0,0 +1,26 @@
1
+ /**
2
+ * A package asked for vars that were never delivered.
3
+ *
4
+ * Almost always one of three things: the package was loaded outside `remoteLoader`
5
+ * (a test, a storybook, a direct import), the host and the package resolved separate
6
+ * copies of `@appshell/runtime` because one of them failed to declare it as a
7
+ * singleton, or the scope compiled into the package is not the scope the registry
8
+ * knows it by.
9
+ */
10
+ export declare class MissingVarsError extends Error {
11
+ readonly scope: string;
12
+ constructor(scope: string, known: string[]);
13
+ }
14
+ /**
15
+ * Something tried to replace vars that were already delivered for a scope.
16
+ *
17
+ * The first write wins and is final. Within one page load a scope has exactly one
18
+ * vars object — both resolvers read it from the same `composition.vars[scope]` — so a
19
+ * differing second write is a bug or a package reaching for a scope that is not its own,
20
+ * and neither should be applied quietly.
21
+ */
22
+ export declare class VarsConflictError extends Error {
23
+ readonly scope: string;
24
+ constructor(scope: string);
25
+ }
26
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;CAc3C;AAED;;;;;;;GAOG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM;CAS1B"}
@@ -0,0 +1,4 @@
1
+ export { MissingVarsError, VarsConflictError } from './errors';
2
+ export { hasVars, readVars, resetVars, setVars } from './store';
3
+ export type { Vars } from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAChE,YAAY,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { Vars } from './types';
2
+ /**
3
+ * Delivers a scope's vars. Called by `@appshell/loader` immediately before the remote
4
+ * is loaded, so they are in place before the package's modules evaluate.
5
+ *
6
+ * The first write for a scope wins and is frozen. Re-delivering the identical vars is a
7
+ * no-op — the same remote can be mounted more than once — but replacing them throws.
8
+ * That is what keeps one package from overwriting another's: by the time any package
9
+ * evaluates, the host has already written for it.
10
+ *
11
+ * It does not make a scope's vars *private*. Any code on the page can still read another
12
+ * scope by name, and nothing short of a separate realm would change that.
13
+ */
14
+ export declare const setVars: (scope: string, vars: Vars) => void;
15
+ /**
16
+ * Reads a scope's vars, throwing rather than handing back an empty object — a package
17
+ * that silently renders with no configuration is the failure this replaced.
18
+ *
19
+ * Prefer `getVars()` from `@appshell/vars`, which supplies the scope for you.
20
+ */
21
+ export declare const readVars: <TVars extends Vars = Vars>(scope: string) => TVars;
22
+ /** Whether a scope has been delivered, for callers that want to branch instead of catch. */
23
+ export declare const hasVars: (scope: string) => boolean;
24
+ /** Test seam. Not part of the contract a package should build on. */
25
+ export declare const resetVars: () => void;
26
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAepC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,OAAO,UAAW,MAAM,QAAQ,IAAI,KAAG,IAYnD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,SAAS,IAAI,gBAAgB,MAAM,KAAG,KAQnE,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,OAAO,UAAW,MAAM,KAAG,OAA+B,CAAC;AAExE,qEAAqE;AACrE,eAAO,MAAM,SAAS,QAAO,IAE5B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A package's runtime configuration, already merged by the registry — a package's
3
+ * declared vars, then the application's `overrides.vars`.
4
+ *
5
+ * Structurally identical to `AppshellComposition['vars'][scope]` in `@appshell/config`,
6
+ * but declared here rather than imported. This package is a shared singleton loaded
7
+ * into every micro-frontend on the page, so it carries no dependencies at all.
8
+ */
9
+ export type Vars = Record<string, string | number | undefined>;
10
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@appshell/runtime",
3
+ "version": "1.0.0-alpha.15",
4
+ "description": "The shared singleton that delivers a package's runtime configuration to it",
5
+ "main": "dist/main.js",
6
+ "types": "dist/types/index.d.ts",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/appshellhq/appshell.git"
10
+ },
11
+ "author": "Robert Hamilton <rh@navaris.com>",
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "registry": "https://registry.npmjs.org/"
15
+ },
16
+ "scripts": {
17
+ "build": "webpack --mode production && npm run build:types",
18
+ "build:types": "tsc --emitDeclarationOnly",
19
+ "clean": "rm -rf dist",
20
+ "prebuild": "npm run clean",
21
+ "start": "webpack --watch --mode development && npm run build:types",
22
+ "stats": "webpack --json > stats.json"
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "keywords": [
28
+ "module federation",
29
+ "micro-frontends",
30
+ "appshell"
31
+ ],
32
+ "license": "MIT"
33
+ }