@appshell/loader 1.0.0-alpha.9 → 1.0.0-alpha.91

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.
Files changed (97) hide show
  1. package/README.md +19 -21
  2. package/dist/main.js +1 -1
  3. package/dist/types/config/src/axios.d.ts +0 -1
  4. package/dist/types/config/src/configmap.d.ts +0 -1
  5. package/dist/types/config/src/context.d.ts +3 -4
  6. package/dist/types/config/src/credentials.d.ts +35 -3
  7. package/dist/types/config/src/generate.manifest.d.ts +30 -2
  8. package/dist/types/config/src/index.d.ts +9 -10
  9. package/dist/types/config/src/loader.d.ts +18 -0
  10. package/dist/types/config/src/mappers/appshell.config.d.ts +9 -3
  11. package/dist/types/config/src/outdated.d.ts +0 -1
  12. package/dist/types/config/src/package-name.d.ts +20 -0
  13. package/dist/types/config/src/publish.d.ts +89 -7
  14. package/dist/types/config/src/sync.d.ts +0 -1
  15. package/dist/types/config/src/tls.d.ts +23 -0
  16. package/dist/types/config/src/types.d.ts +164 -30
  17. package/dist/types/config/src/utils/blur.d.ts +0 -1
  18. package/dist/types/config/src/utils/compare.d.ts +0 -1
  19. package/dist/types/config/src/utils/config.d.ts +0 -1
  20. package/dist/types/config/src/utils/copy.d.ts +0 -1
  21. package/dist/types/config/src/utils/dump.d.ts +10 -0
  22. package/dist/types/config/src/utils/index.d.ts +1 -4
  23. package/dist/types/config/src/utils/list.d.ts +0 -1
  24. package/dist/types/config/src/utils/load.d.ts +0 -1
  25. package/dist/types/config/src/validators/AppshellTemplateValidator.d.ts +0 -1
  26. package/dist/types/config/src/validators/index.d.ts +0 -3
  27. package/dist/types/loader/src/index.d.ts +0 -1
  28. package/dist/types/loader/src/loadAppshellComponent.d.ts +13 -14
  29. package/dist/types/loader/src/remoteLoader.d.ts +2 -3
  30. package/dist/types/loader/src/resolvers.d.ts +4 -12
  31. package/dist/types/loader/src/types.d.ts +0 -1
  32. package/dist/types/runtime/src/errors.d.ts +32 -0
  33. package/dist/types/runtime/src/identity.d.ts +47 -0
  34. package/dist/types/runtime/src/index.d.ts +6 -0
  35. package/dist/types/runtime/src/store.d.ts +25 -0
  36. package/dist/types/runtime/src/types.d.ts +9 -0
  37. package/dist/types/runtime/src/wire.d.ts +58 -0
  38. package/package.json +15 -4
  39. package/CHANGELOG.md +0 -197
  40. package/__tests__/fetchDynamicScript.spec.ts +0 -44
  41. package/__tests__/fixtures/TestComponent.ts +0 -3
  42. package/__tests__/loadAppshellComponent.spec.ts +0 -102
  43. package/__tests__/remoteLoader.spec.ts +0 -144
  44. package/__tests__/resolvers.spec.ts +0 -128
  45. package/dist/types/config/src/axios.d.ts.map +0 -1
  46. package/dist/types/config/src/configmap.d.ts.map +0 -1
  47. package/dist/types/config/src/context.d.ts.map +0 -1
  48. package/dist/types/config/src/credentials.d.ts.map +0 -1
  49. package/dist/types/config/src/deregister.d.ts +0 -3
  50. package/dist/types/config/src/deregister.d.ts.map +0 -1
  51. package/dist/types/config/src/generate.env.d.ts +0 -3
  52. package/dist/types/config/src/generate.env.d.ts.map +0 -1
  53. package/dist/types/config/src/generate.global-config.d.ts +0 -10
  54. package/dist/types/config/src/generate.global-config.d.ts.map +0 -1
  55. package/dist/types/config/src/generate.manifest.d.ts.map +0 -1
  56. package/dist/types/config/src/index.d.ts.map +0 -1
  57. package/dist/types/config/src/mappers/appshell.config.d.ts.map +0 -1
  58. package/dist/types/config/src/outdated.d.ts.map +0 -1
  59. package/dist/types/config/src/publish.d.ts.map +0 -1
  60. package/dist/types/config/src/register.d.ts +0 -4
  61. package/dist/types/config/src/register.d.ts.map +0 -1
  62. package/dist/types/config/src/sync.d.ts.map +0 -1
  63. package/dist/types/config/src/types.d.ts.map +0 -1
  64. package/dist/types/config/src/utils/blur.d.ts.map +0 -1
  65. package/dist/types/config/src/utils/compare.d.ts.map +0 -1
  66. package/dist/types/config/src/utils/config.d.ts.map +0 -1
  67. package/dist/types/config/src/utils/copy.d.ts.map +0 -1
  68. package/dist/types/config/src/utils/index.d.ts.map +0 -1
  69. package/dist/types/config/src/utils/isValidUrl.d.ts +0 -3
  70. package/dist/types/config/src/utils/isValidUrl.d.ts.map +0 -1
  71. package/dist/types/config/src/utils/list.d.ts.map +0 -1
  72. package/dist/types/config/src/utils/load.d.ts.map +0 -1
  73. package/dist/types/config/src/utils/loadJson.d.ts +0 -10
  74. package/dist/types/config/src/utils/loadJson.d.ts.map +0 -1
  75. package/dist/types/config/src/utils/merge.d.ts +0 -4
  76. package/dist/types/config/src/utils/merge.d.ts.map +0 -1
  77. package/dist/types/config/src/validators/AppshellGlobalConfigValidator.d.ts +0 -4
  78. package/dist/types/config/src/validators/AppshellGlobalConfigValidator.d.ts.map +0 -1
  79. package/dist/types/config/src/validators/AppshellManifestValidator.d.ts +0 -4
  80. package/dist/types/config/src/validators/AppshellManifestValidator.d.ts.map +0 -1
  81. package/dist/types/config/src/validators/AppshellTemplateValidator.d.ts.map +0 -1
  82. package/dist/types/config/src/validators/index.d.ts.map +0 -1
  83. package/dist/types/loader/src/fetchDynamicScript.d.ts +0 -3
  84. package/dist/types/loader/src/fetchDynamicScript.d.ts.map +0 -1
  85. package/dist/types/loader/src/index.d.ts.map +0 -1
  86. package/dist/types/loader/src/loadAppshellComponent.d.ts.map +0 -1
  87. package/dist/types/loader/src/remoteLoader.d.ts.map +0 -1
  88. package/dist/types/loader/src/resolvers.d.ts.map +0 -1
  89. package/dist/types/loader/src/types.d.ts.map +0 -1
  90. package/src/fetchDynamicScript.ts +0 -49
  91. package/src/index.ts +0 -7
  92. package/src/loadAppshellComponent.ts +0 -48
  93. package/src/remoteLoader.ts +0 -80
  94. package/src/resolvers.ts +0 -110
  95. package/src/types.ts +0 -10
  96. package/tsconfig.json +0 -7
  97. package/webpack.config.js +0 -37
@@ -0,0 +1,23 @@
1
+ import https from 'https';
2
+ /**
3
+ * An extra CA bundle to trust, from `ca-file` in the cli config or `APPSHELL_CA_FILE`.
4
+ *
5
+ * A registry behind a private CA — a corporate root, a TLS-inspecting proxy, or a local
6
+ * cluster using mkcert — fails with "unable to verify the first certificate", which says
7
+ * nothing about which host or what to do. Node can be told through `NODE_EXTRA_CA_CERTS`
8
+ * or `--use-system-ca`, but both are environment variables a user has to remember in
9
+ * every new terminal, and neither travels with the registry they apply to.
10
+ *
11
+ * npm draws the same conclusion with `cafile` in .npmrc: trust is configuration of the
12
+ * registry you talk to, not of the shell you happen to be in.
13
+ */
14
+ export declare const caFile: () => string | undefined;
15
+ /**
16
+ * The agent to use for registry and issuer requests, or undefined when no CA is
17
+ * configured and Node's defaults apply.
18
+ *
19
+ * A configured file that does not exist throws rather than being skipped: falling back
20
+ * silently would reproduce the original certificate error, having been told exactly how
21
+ * to avoid it.
22
+ */
23
+ export declare const httpsAgent: () => https.Agent | undefined;
@@ -1,4 +1,6 @@
1
+ import type { AppshellIndex, AppshellRemote, Metadata, RemoteLoader } from '@appshell/runtime';
1
2
  import { JSONSchema4, JSONSchema6, JSONSchema7 } from 'json-schema';
3
+ export type { AppshellIndex, AppshellRemote, Metadata, ModuleFederationLoader, RemoteLoader, } from '@appshell/runtime';
2
4
  export type Schema = JSONSchema4 | JSONSchema6 | JSONSchema7;
3
5
  export type ConfigValidator = {
4
6
  validate: <T>(...config: T[]) => void;
@@ -43,58 +45,165 @@ export type ComparisonTarget = {
43
45
  name: string;
44
46
  dependencies: Record<string, string | undefined>;
45
47
  };
48
+ /**
49
+ * Every key `appshell config set` accepts, kept adjacent to the type it must agree with.
50
+ *
51
+ * It used to live in the set handler, and adding `caFile` to CliConfig without touching it
52
+ * produced a setting the cli could read and refuse to write.
53
+ */
54
+ export declare const CLI_SETTINGS: readonly ["registry", "application", "scopeId", "authIssuer", "clientId", "apiKey", "apiKeyHeader", "caFile"];
55
+ export type CliSetting = (typeof CLI_SETTINGS)[number];
46
56
  export type CliConfig = Record<string, string> & {
47
57
  apiKey: string;
58
+ /**
59
+ * PEM bundle to trust in addition to Node's built-ins, for a registry behind a private
60
+ * CA. Optional, and absent from `config init` output: an empty path is not a default
61
+ * worth writing, and its absence means "use Node's defaults".
62
+ */
63
+ caFile?: string;
48
64
  registry: string;
49
- environment: string;
65
+ application: string;
50
66
  scopeId: string;
51
67
  authIssuer: string;
52
68
  clientId: string;
53
69
  };
70
+ /**
71
+ * Neither `url` nor `filename`.
72
+ *
73
+ * `url` is an origin, and an origin belongs to a deployment: a package is published once
74
+ * and deployed many times, so a url here would freeze one environment's answer into an
75
+ * immutable version and make the artifact's digest depend on where it was built.
76
+ *
77
+ * `filename` was a hand-written copy of the Module Federation `filename`, which is what
78
+ * actually decides the file webpack emits. Two statements of one fact, and only one of
79
+ * them is enforced by anything.
80
+ */
54
81
  export type AppshellConfigRemote<TMetadata = Metadata> = {
55
82
  id: string;
56
- url: string;
57
- filename: string;
58
83
  metadata: TMetadata;
59
84
  };
60
85
  export type AppshellConfig<TMetadata = Metadata> = {
61
86
  name?: string;
62
- remotes?: Record<string, AppshellConfigRemote<TMetadata>>;
63
- environment?: Record<string, unknown>;
87
+ /**
88
+ * What the registry should publish this package as. `--visibility` overrides it.
89
+ *
90
+ * Declared here but deliberately absent from the manifest, as `name` already is: the
91
+ * manifest is hashed into the package digest, and visibility is not a property of the
92
+ * artifact. Keeping it out is what lets a package be made public later without its
93
+ * content changing identity.
94
+ */
95
+ visibility?: 'public' | 'private';
96
+ /**
97
+ * What this package publishes, keyed by federation entrypoint.
98
+ *
99
+ * Appshell's own word rather than a framework's. It was `remotes`, which is MF's word
100
+ * for the opposite — what a package consumes — so the file read inverted to anyone who
101
+ * knew the framework. `exposes` would fix that and put MF's vocabulary at the top level
102
+ * of appshell's model, which is what the loader recipe exists to prevent.
103
+ */
104
+ components?: Record<string, AppshellConfigRemote<TMetadata>>;
105
+ /**
106
+ * What this package consumes, by the name it refers to them by.
107
+ *
108
+ * A flat list because a referenced remote is required by definition: unbound, the region
109
+ * renders an error. `RemoteSlot`'s `fallback` is a loading placeholder — it shows while
110
+ * the remote arrives, not when it is absent — so unlike a design token's `var()`
111
+ * fallback it describes no degraded-but-working state.
112
+ *
113
+ * The application binds each name to a registry address, so a package never states the
114
+ * scope its siblings were published into — which it cannot know, since scope is assigned
115
+ * by whoever publishes.
116
+ */
117
+ remotes?: string[];
118
+ vars?: Record<string, unknown>;
64
119
  overrides?: AppshellOverrides;
65
120
  };
66
121
  export type AppshellTemplate<TMetadata = Metadata> = {
67
122
  name?: string;
68
- remotes?: Record<string, AppshellConfigRemote<TMetadata>>;
123
+ /** Carried from the yaml for publish to read; never mapped into the manifest. */
124
+ visibility?: 'public' | 'private';
125
+ components?: Record<string, AppshellConfigRemote<TMetadata>>;
126
+ remotes?: string[];
69
127
  module: ModuleFederationPluginOptions;
70
- environment?: Record<string, unknown>;
128
+ vars?: Record<string, unknown>;
129
+ tokens?: Record<string, AppshellTokenUsage>;
71
130
  overrides?: AppshellOverrides;
72
131
  };
73
132
  /** Appshell manifest types */
74
- export type AppshellRemote<TMetadata = Metadata> = {
75
- id: string;
76
- manifestUrl: string;
77
- remoteEntryUrl: string;
78
- scope: string;
79
- module: string;
80
- shareScope?: string;
81
- metadata: TMetadata;
133
+ /** The parts of a remote an application may point somewhere else. */
134
+ export type RemoteOverride = {
135
+ remoteEntryUrl?: string;
136
+ manifestUrl?: string;
82
137
  };
83
138
  export type AppshellOverrides = {
84
- environment: Record<string, Record<string, string | number | undefined>>;
139
+ vars: Record<string, Record<string, string | number | undefined>>;
140
+ /**
141
+ * Where an application loads a remote from, keyed by registry address.
142
+ *
143
+ * A package is published once; an application is deployed many times, per environment.
144
+ * The origin a bundle is served from is a property of a deployment, so it belongs to
145
+ * whoever deploys rather than being frozen into an immutable artifact at publish — which
146
+ * is also what makes adopting someone else's package and serving it yourself a spec edit
147
+ * rather than a republish.
148
+ *
149
+ * `filename` stays in the manifest: `remoteEntry.js` is genuinely build output. Only the
150
+ * origin varies by environment.
151
+ */
152
+ remotes?: Record<string, RemoteOverride>;
153
+ };
154
+ /**
155
+ * Which design tokens a package's own output reaches for. Observed from the emitted
156
+ * assets rather than declared: the CSS already says it, and a hand-kept list is a copy
157
+ * that drifts the first time someone adds a token and forgets the yaml.
158
+ *
159
+ * `required` is a reference with no fallback — the package has no plan B. `optional` is
160
+ * `var(--appshell-x, something)`, which degrades on its own. That split is read off what
161
+ * the author wrote rather than asked of them.
162
+ */
163
+ export type AppshellTokenUsage = {
164
+ required: string[];
165
+ optional: string[];
166
+ };
167
+ /** A shared-dependency contract, named as one framework's model among possible models. */
168
+ export type SharedContract = {
169
+ apiVersion: 'federation.appshell.org/v1';
170
+ kind: 'ModuleFederation';
171
+ /** Keyed by share scope, as Module Federation groups them. */
172
+ scopes: Record<string, SharedObject>;
85
173
  };
86
174
  export type AppshellManifest<TMetadata = Metadata> = {
87
- remotes: Record<string, AppshellRemote<TMetadata>>;
88
- modules: Record<string, ModuleFederationPluginOptions>;
89
- environment: Record<string, Record<string, string | number | undefined>>;
175
+ /** What this package publishes, keyed by federation entrypoint. */
176
+ components: Record<string, PublishedRemote<TMetadata>>;
177
+ /** What it consumes, by local name; the application binds each to an address. */
178
+ remotes?: string[];
179
+ /**
180
+ * The shared-dependency contract this package was built against.
181
+ *
182
+ * Tagged like the loader recipe, and for the same reason: share scopes, singletons and
183
+ * version ranges are Module Federation's model of the problem, which single-spa and
184
+ * import maps solve differently. This replaced `modules`, which stored MF's plugin
185
+ * options verbatim — one reader took two fields from it, while its source paths and
186
+ * type-generation flags sat inside the package digest.
187
+ */
188
+ shared?: SharedContract;
189
+ vars: Record<string, Record<string, string | number | undefined>>;
190
+ /** Keyed by federation scope, so a merged manifest still says which package needs what. */
191
+ tokens?: Record<string, AppshellTokenUsage>;
90
192
  overrides?: AppshellOverrides;
91
193
  };
92
- export type AppshellIndex = Record<string, string>;
93
- export type Metadata = Record<string, unknown>;
94
- export type AppshellGlobalConfig<TMetadata = Metadata> = {
95
- index: AppshellIndex;
96
- metadata?: Record<string, TMetadata>;
97
- overrides?: AppshellOverrides;
194
+ /**
195
+ * A remote as a package publishes it: what the build knows about itself, and nothing
196
+ * about where it ends up.
197
+ *
198
+ * Distinct from `AppshellRemote`, which is the same remote after the registry has
199
+ * resolved it for the browser. They were one type, which is why the origin ended up in
200
+ * the artifact: the browser genuinely needs a url, so the published form appeared to as
201
+ * well. The registry supplies it at composition, from the address and its serving plane.
202
+ */
203
+ export type PublishedRemote<TMetadata = Metadata> = {
204
+ id: string;
205
+ loader: RemoteLoader;
206
+ metadata: TMetadata;
98
207
  };
99
208
  /** An `AppshellRemote` the registry already resolved, so the browser needs no manifest fetch. */
100
209
  export type ResolvedRemote<TMetadata = Metadata> = AppshellRemote<TMetadata>;
@@ -102,19 +211,45 @@ export type ResolvedRemote<TMetadata = Metadata> = AppshellRemote<TMetadata>;
102
211
  * The wire contract for `window.__appshell_config__`. Deliberately not an
103
212
  * `AppshellManifest`: that is a build artifact, and reusing it left it unclear
104
213
  * which fields the browser actually needs. `modules` is build-time webpack
105
- * config and never crosses the wire; `environment` arrives already merged with
106
- * the environment's overrides, leaving the browser only local overrides to apply.
214
+ * config and never crosses the wire; `vars` arrives already merged with the
215
+ * application's overrides, leaving the browser only local overrides to apply.
107
216
  */
108
217
  export type AppshellComposition<TMetadata = Metadata> = {
109
218
  /** `scope/name` — makes the payload self-describing for fetch-on-miss and for `env diff`. */
110
- environmentId: string;
219
+ applicationId: string;
111
220
  revision: number;
112
221
  /** The remote key the host mounts at the root, and the props it is given. */
113
222
  root: string;
114
223
  rootProps: Record<string, unknown>;
115
224
  index: AppshellIndex;
116
225
  remotes: Record<string, ResolvedRemote<TMetadata>>;
117
- environment: Record<string, Record<string, string | number | undefined>>;
226
+ vars: Record<string, Record<string, string | number | undefined>>;
227
+ /**
228
+ * Present whenever a per-developer overlay changed anything about this render — a
229
+ * redirected remote, a different shell bundle, a substituted theme, or any combination.
230
+ * The shell is expected to surface it: a page that quietly runs code from somewhere
231
+ * else is the one thing this feature must never be, and swapping the shell or the theme
232
+ * out counts.
233
+ *
234
+ * `shellFlavor` is what was actually served, not what was asked for. `theme` is the ref
235
+ * the overlay substituted, present only when it substituted one.
236
+ */
237
+ overlay?: {
238
+ id: string;
239
+ remotes: string[];
240
+ /**
241
+ * Those of `remotes` the overlay introduced rather than redirected — components the
242
+ * application does not publish, running for this developer and nobody else.
243
+ *
244
+ * Separate from `remotes` because the two are not the same claim. A redirected
245
+ * component exists for everyone and this browser runs a different copy of it; an
246
+ * added one does not exist outside this overlay at all, so a feature built on top of
247
+ * one works here and is absent everywhere else.
248
+ */
249
+ added?: string[];
250
+ shellFlavor: 'prod' | 'dev';
251
+ theme?: string;
252
+ };
118
253
  };
119
254
  /**
120
255
  * Advanced configuration for modules that should be exposed by this container.
@@ -293,4 +428,3 @@ export interface ModuleFederationPluginOptions {
293
428
  */
294
429
  shared?: (string | SharedObject)[] | SharedObject;
295
430
  }
296
- //# sourceMappingURL=types.d.ts.map
@@ -1,3 +1,2 @@
1
1
  declare const _default: (token?: string, chars?: number) => string;
2
2
  export default _default;
3
- //# sourceMappingURL=blur.d.ts.map
@@ -5,4 +5,3 @@ export declare const compareDependencies: (sample: ComparisonTarget, baseline: C
5
5
  export declare const compareSharedDependencies: (packageSpec: PackageSpec, sharedModule: SharedModuleSpec) => ComparisonResults;
6
6
  export declare const compareSharedModules: (sampleSpec: SharedModuleSpec, baselineSpec: SharedModuleSpec) => ComparisonResults;
7
7
  export declare const printResults: (results: ComparisonResults) => void;
8
- //# sourceMappingURL=compare.d.ts.map
@@ -3,4 +3,3 @@ import { CliConfig } from '../types';
3
3
  export declare const readConfig: (configPath: string) => CliConfig;
4
4
  export declare const writeConfig: (configPath: string, config: CliConfig) => void;
5
5
  export declare const mergeConfigWithArgs: (config: CliConfig, argv: yargs.ArgumentsCamelCase<unknown>) => void;
6
- //# sourceMappingURL=config.d.ts.map
@@ -8,4 +8,3 @@ declare const _default: (pattern: {
8
8
  to: string;
9
9
  }) => void;
10
10
  export default _default;
11
- //# sourceMappingURL=copy.d.ts.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Serialises a value to YAML.
3
+ *
4
+ * The counterpart to `load`, and here rather than at each call site so the YAML library
5
+ * stays in one package. `appshell theme init` writes a file an author then edits, so the
6
+ * output is line-wrapped generously — a colour value broken across lines is technically
7
+ * valid and horrible to read.
8
+ */
9
+ declare const dump: (value: unknown) => string;
10
+ export default dump;
@@ -2,9 +2,6 @@ export { default as blur } from './blur';
2
2
  export { compareDependencies, compareDependency, compareSharedDependencies, compareSharedModules, extractDependencies, printResults, } from './compare';
3
3
  export { mergeConfigWithArgs, readConfig, writeConfig } from './config';
4
4
  export { default as copy } from './copy';
5
- export { default as isValidUrl } from './isValidUrl';
5
+ export { default as dump } from './dump';
6
6
  export { default as list } from './list';
7
7
  export { default as load, loadAll } from './load';
8
- export { default as loadJson } from './loadJson';
9
- export { default as merge } from './merge';
10
- //# sourceMappingURL=index.d.ts.map
@@ -7,4 +7,3 @@
7
7
  */
8
8
  declare const list: (dirPath: string, depth?: number, target?: string | RegExp) => string[];
9
9
  export default list;
10
- //# sourceMappingURL=list.d.ts.map
@@ -11,4 +11,3 @@ declare const load: <TSchema>(configPath: string) => TSchema;
11
11
  */
12
12
  export declare const loadAll: <TSchema>(...paths: string[]) => TSchema[];
13
13
  export default load;
14
- //# sourceMappingURL=load.d.ts.map
@@ -1,4 +1,3 @@
1
1
  import { ConfigValidator } from '../types';
2
2
  declare const _default: ConfigValidator;
3
3
  export default _default;
4
- //# sourceMappingURL=AppshellTemplateValidator.d.ts.map
@@ -1,4 +1 @@
1
- export { default as AppshellGlobalConfigValidator } from './AppshellGlobalConfigValidator';
2
- export { default as AppshellManifestValidator } from './AppshellManifestValidator';
3
1
  export { default as AppshellTemplateValidator } from './AppshellTemplateValidator';
4
- //# sourceMappingURL=index.d.ts.map
@@ -3,4 +3,3 @@ export type { RemoteLoaderOptions } from './remoteLoader';
3
3
  export * from './resolvers';
4
4
  export * from './types';
5
5
  export default remoteLoader;
6
- //# sourceMappingURL=index.d.ts.map
@@ -1,14 +1,13 @@
1
- import { ShareScope } from './types';
2
- declare global {
3
- function __webpack_init_sharing__(id: string): Promise<void>;
4
- const __webpack_share_scopes__: {
5
- default: ShareScope;
6
- };
7
- interface Window {
8
- [key: string]: unknown;
9
- __webpack_share_scopes__: Record<string, ShareScope>;
10
- }
11
- }
12
- declare const _default: <TComponent>(scope: string, module: string, shareScope?: string) => Promise<TComponent>;
13
- export default _default;
14
- //# sourceMappingURL=loadAppshellComponent.d.ts.map
1
+ import type { RemoteLoader } from '@appshell/runtime';
2
+ /**
3
+ * Dispatches on the loader's kind rather than assuming federation.
4
+ *
5
+ * There is one kind today. Naming it is what lets a second — single-spa, import maps —
6
+ * arrive without reinterpreting manifests already published, and what stops federation's
7
+ * vocabulary reading as though it were appshell's.
8
+ */
9
+ export declare const load: <TComponent>(remote: {
10
+ loader: RemoteLoader;
11
+ remoteEntryUrl: string;
12
+ }) => Promise<TComponent>;
13
+ export default load;
@@ -1,4 +1,4 @@
1
- import type { AppshellComposition, AppshellGlobalConfig } from '@appshell/config';
1
+ import type { AppshellComposition } from '@appshell/config';
2
2
  import { type RemoteResolver } from './resolvers';
3
3
  declare global {
4
4
  interface Window {
@@ -10,6 +10,5 @@ export type RemoteLoaderOptions = {
10
10
  /** Replaces the resolver chain outright; a seam for tests and embedders. */
11
11
  resolver?: RemoteResolver;
12
12
  };
13
- declare const _default: (config: AppshellGlobalConfig, options?: RemoteLoaderOptions) => <TComponent>(key: string) => Promise<readonly [null, null] | readonly [Awaited<TComponent>, import("@appshell/config").AppshellManifest]>;
13
+ declare const _default: (options?: RemoteLoaderOptions) => <TComponent>(key: string) => Promise<readonly [Awaited<TComponent>, import("@appshell/config").ResolvedRemote]>;
14
14
  export default _default;
15
- //# sourceMappingURL=remoteLoader.d.ts.map
@@ -1,20 +1,12 @@
1
- import type { AppshellComposition, AppshellGlobalConfig, AppshellManifest, ResolvedRemote } from '@appshell/config';
1
+ import type { AppshellComposition, ResolvedRemote } from '@appshell/config';
2
2
  export type RemoteResolution = {
3
3
  remote: ResolvedRemote;
4
- /** Already merged with the environment's overrides — nothing left for the browser to layer on. */
5
- environment: Record<string, string | number | undefined>;
6
- /** Back-compat payload for `ManifestProvider`; synthesized when the source was a composition. */
7
- manifest: AppshellManifest;
4
+ /** Already merged with the application's overrides — nothing left for the browser to layer on. */
5
+ vars: Record<string, string | number | undefined>;
8
6
  };
9
7
  export type RemoteResolver = (key: string) => Promise<RemoteResolution | undefined>;
10
8
  /** The registry inlined the composition into the page, so no network call is needed. */
11
9
  export declare const inlineResolver: (composition?: AppshellComposition) => RemoteResolver;
12
- /** Fetch-on-miss: covers an app activated after this page was served. */
10
+ /** Fetch-on-miss: covers a package activated after this page was served. */
13
11
  export declare const registryResolver: (composition?: AppshellComposition, origin?: string) => RemoteResolver;
14
- /**
15
- * Pre-registry hosts: follow `index[key]` to the app's own manifest. The override
16
- * merge stays here because in this mode no server has done it.
17
- */
18
- export declare const legacyManifestResolver: (config: AppshellGlobalConfig) => RemoteResolver;
19
12
  export declare const chainResolvers: (...resolvers: RemoteResolver[]) => RemoteResolver;
20
- //# sourceMappingURL=resolvers.d.ts.map
@@ -8,4 +8,3 @@ export interface ModuleContainer<TComponent> {
8
8
  init(shareScope: ShareScope<TComponent>): Promise<void>;
9
9
  get(module: string): Promise<() => Record<string, TComponent>>;
10
10
  }
11
- //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,32 @@
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
+ /**
27
+ * The package was built without `AppshellPlugin`, so nothing substituted the scope the
28
+ * `@appshell/runtime/vars` accessor needs to know which vars are its own.
29
+ */
30
+ export declare class MissingScopeError extends Error {
31
+ constructor();
32
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Who is looking at the page, as the registry was told by the gateway.
3
+ *
4
+ * Unlike vars this is not scope-specific — there is one visitor per page, not one
5
+ * per package — so it lives in the main entry rather than needing the subpath
6
+ * trick `@appshell/runtime/vars` uses to get a per-package scope substituted.
7
+ *
8
+ * It is also not delivered through the vars store, and that is a constraint rather
9
+ * than a preference: `setVars` freezes on first write and throws on replacement,
10
+ * which is what stops one package overwriting another's configuration. Identity
11
+ * changes — sign-in, sign-out, token refresh — so it cannot live behind a
12
+ * write-once door without either breaking that guarantee or never updating.
13
+ */
14
+ /**
15
+ * A discriminated union rather than an optional user, so `username` cannot be read
16
+ * without the anonymous case having been handled. The compiler enforces what a
17
+ * convention would only ask for.
18
+ */
19
+ export type Identity = {
20
+ authenticated: false;
21
+ } | {
22
+ authenticated: true;
23
+ subject: string;
24
+ username: string;
25
+ roles: string[];
26
+ };
27
+ export declare const ANONYMOUS: Identity;
28
+ declare global {
29
+ interface Window {
30
+ __appshell_identity__?: unknown;
31
+ }
32
+ }
33
+ /**
34
+ * The visitor, or the anonymous identity when there is none.
35
+ *
36
+ * Never throws and never returns undefined — an absent or malformed value is
37
+ * anonymous, which is a state every caller already has to handle. That is the
38
+ * opposite of `readVars`, which throws when a scope is missing, and the difference
39
+ * is deliberate: a package with no configuration cannot do its job, while a package
40
+ * with no signed-in user usually can and simply renders differently.
41
+ *
42
+ * This is a typed accessor, not a boundary. The value is inlined into the document
43
+ * and any script on the page can read it directly, exactly as with vars. Treat it
44
+ * as what the server said about the visitor, never as proof of anything: it carries
45
+ * no token and grants nothing. Anything that matters is re-checked server-side.
46
+ */
47
+ export declare const getIdentity: () => Identity;
@@ -0,0 +1,6 @@
1
+ export { MissingScopeError, MissingVarsError, VarsConflictError } from './errors';
2
+ export { ANONYMOUS, getIdentity } from './identity';
3
+ export type { Identity } from './identity';
4
+ export { hasVars, readVars, resetVars, setVars } from './store';
5
+ export type { Vars } from './types';
6
+ export type { AppshellIndex, AppshellRemote, Metadata, ModuleFederationLoader, RemoteLoader, } from './wire';
@@ -0,0 +1,25 @@
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/runtime/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;
@@ -0,0 +1,9 @@
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>;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * What the browser is told about a remote.
3
+ *
4
+ * These live here rather than in `@appshell/config` because config is build tooling — it
5
+ * carries yaml, lodash and axios — and a package that only wants to type a remote should
6
+ * not install a compiler to get it. This package is already the one every micro-frontend
7
+ * on the page shares, and it has no dependencies of its own to pass on.
8
+ *
9
+ * `AppshellManifest` deliberately stays in `@appshell/config`. It is a build artifact, and
10
+ * its `modules` field is Module Federation plugin options — build-time webpack
11
+ * configuration the browser never sees and this package should never drag in.
12
+ */
13
+ /** Arbitrary, application-defined description of a remote. Appshell never reads it. */
14
+ export type Metadata = Record<string, unknown>;
15
+ /**
16
+ * How a host loads a remote, named as one kind among possible kinds.
17
+ *
18
+ * scope, module and shareScope are Module Federation's vocabulary, and they used to sit
19
+ * at the top level of a remote where nothing said so — which is what would have made a
20
+ * second framework awkward, not the words themselves. Nested under a kind they are
21
+ * exactly correct, and something like single-spa slots beside them without reinterpreting
22
+ * anything already published.
23
+ *
24
+ * apiVersion follows the house style set by appshell.app.yaml, and the group is appshell's
25
+ * because appshell owns this schema: it decides which fields it stores, even though the
26
+ * fields describe federation concepts. If federation ever needs a different recipe that is
27
+ * a v2, and manifests published under v1 keep meaning what they meant — which matters,
28
+ * because they are immutable and hashed.
29
+ */
30
+ export type ModuleFederationLoader = {
31
+ apiVersion: 'federation.appshell.org/v1';
32
+ kind: 'ModuleFederation';
33
+ scope: string;
34
+ module: string;
35
+ shareScope?: string;
36
+ /** The entry file the build emits, conventionally remoteEntry.js. */
37
+ filename: string;
38
+ /**
39
+ * What built this, recorded as a fact rather than a constraint.
40
+ *
41
+ * Deliberately not a version range. A range is a claim about the environment, and a
42
+ * package cannot make it: it knows what built it and not what will load it, and the
43
+ * host is what registers the remote. Freezing one into an immutable artifact is the
44
+ * same mistake as freezing its origin.
45
+ */
46
+ builtWith?: string;
47
+ };
48
+ export type RemoteLoader = ModuleFederationLoader;
49
+ /** A remote the registry has already resolved, so the browser needs no manifest fetch. */
50
+ export type AppshellRemote<TMetadata = Metadata> = {
51
+ id: string;
52
+ manifestUrl: string;
53
+ remoteEntryUrl: string;
54
+ loader: RemoteLoader;
55
+ metadata: TMetadata;
56
+ };
57
+ /** Remote key to manifest url. */
58
+ export type AppshellIndex = Record<string, string>;