@appshell/react 1.0.0-alpha.10 → 1.0.0-alpha.100

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 (142) hide show
  1. package/README.md +36 -49
  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 +8 -5
  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 +11 -0
  16. package/dist/types/config/src/types.d.ts +184 -31
  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 +15 -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 +2 -5
  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/react/src/components/LoadingError.d.ts +0 -1
  33. package/dist/types/react/src/components/RemoteSlot.d.ts +28 -0
  34. package/dist/types/react/src/contexts/RemoteContext.d.ts +2 -4
  35. package/dist/types/react/src/hooks/useRemote.d.ts +1 -2
  36. package/dist/types/react/src/index.d.ts +2 -9
  37. package/dist/types/react/src/resources/jsonResource.d.ts +0 -1
  38. package/dist/types/react/src/types.d.ts +0 -1
  39. package/dist/types/runtime/src/errors.d.ts +32 -0
  40. package/dist/types/runtime/src/identity.d.ts +47 -0
  41. package/dist/types/runtime/src/index.d.ts +6 -0
  42. package/dist/types/runtime/src/store.d.ts +25 -0
  43. package/dist/types/runtime/src/types.d.ts +9 -0
  44. package/dist/types/runtime/src/wire.d.ts +58 -0
  45. package/package.json +14 -4
  46. package/CHANGELOG.md +0 -207
  47. package/__tests__/AppshellComponent.spec.tsx +0 -53
  48. package/__tests__/LoadingError.spec.tsx +0 -14
  49. package/__tests__/ManifestContext.spec.tsx +0 -50
  50. package/__tests__/ReactHost.spec.tsx +0 -136
  51. package/__tests__/__snapshots__/AppshellComponent.spec.tsx.snap +0 -9
  52. package/__tests__/__snapshots__/LoadingError.spec.tsx.snap +0 -88
  53. package/__tests__/__snapshots__/ReactHost.spec.tsx.snap +0 -11
  54. package/__tests__/fixtures/Manifest.ts +0 -16
  55. package/__tests__/fixtures/TestComponent.tsx +0 -5
  56. package/__tests__/fixtures/TestGlobalConfig.ts +0 -8
  57. package/__tests__/jsonResource.spec.ts +0 -27
  58. package/__tests__/useRemote.spec.tsx +0 -36
  59. package/__tests__/utils/waitForResource.ts +0 -15
  60. package/dist/types/config/src/axios.d.ts.map +0 -1
  61. package/dist/types/config/src/configmap.d.ts.map +0 -1
  62. package/dist/types/config/src/context.d.ts.map +0 -1
  63. package/dist/types/config/src/credentials.d.ts.map +0 -1
  64. package/dist/types/config/src/deregister.d.ts +0 -3
  65. package/dist/types/config/src/deregister.d.ts.map +0 -1
  66. package/dist/types/config/src/generate.env.d.ts +0 -3
  67. package/dist/types/config/src/generate.env.d.ts.map +0 -1
  68. package/dist/types/config/src/generate.global-config.d.ts +0 -10
  69. package/dist/types/config/src/generate.global-config.d.ts.map +0 -1
  70. package/dist/types/config/src/generate.manifest.d.ts.map +0 -1
  71. package/dist/types/config/src/index.d.ts.map +0 -1
  72. package/dist/types/config/src/mappers/appshell.config.d.ts.map +0 -1
  73. package/dist/types/config/src/outdated.d.ts.map +0 -1
  74. package/dist/types/config/src/publish.d.ts.map +0 -1
  75. package/dist/types/config/src/register.d.ts +0 -4
  76. package/dist/types/config/src/register.d.ts.map +0 -1
  77. package/dist/types/config/src/sync.d.ts.map +0 -1
  78. package/dist/types/config/src/types.d.ts.map +0 -1
  79. package/dist/types/config/src/utils/blur.d.ts.map +0 -1
  80. package/dist/types/config/src/utils/compare.d.ts.map +0 -1
  81. package/dist/types/config/src/utils/config.d.ts.map +0 -1
  82. package/dist/types/config/src/utils/copy.d.ts.map +0 -1
  83. package/dist/types/config/src/utils/index.d.ts.map +0 -1
  84. package/dist/types/config/src/utils/isValidUrl.d.ts +0 -3
  85. package/dist/types/config/src/utils/isValidUrl.d.ts.map +0 -1
  86. package/dist/types/config/src/utils/list.d.ts.map +0 -1
  87. package/dist/types/config/src/utils/load.d.ts.map +0 -1
  88. package/dist/types/config/src/utils/loadJson.d.ts +0 -10
  89. package/dist/types/config/src/utils/loadJson.d.ts.map +0 -1
  90. package/dist/types/config/src/utils/merge.d.ts +0 -4
  91. package/dist/types/config/src/utils/merge.d.ts.map +0 -1
  92. package/dist/types/config/src/validators/AppshellGlobalConfigValidator.d.ts +0 -4
  93. package/dist/types/config/src/validators/AppshellGlobalConfigValidator.d.ts.map +0 -1
  94. package/dist/types/config/src/validators/AppshellManifestValidator.d.ts +0 -4
  95. package/dist/types/config/src/validators/AppshellManifestValidator.d.ts.map +0 -1
  96. package/dist/types/config/src/validators/AppshellTemplateValidator.d.ts.map +0 -1
  97. package/dist/types/config/src/validators/index.d.ts.map +0 -1
  98. package/dist/types/loader/src/fetchDynamicScript.d.ts +0 -3
  99. package/dist/types/loader/src/fetchDynamicScript.d.ts.map +0 -1
  100. package/dist/types/loader/src/index.d.ts.map +0 -1
  101. package/dist/types/loader/src/loadAppshellComponent.d.ts.map +0 -1
  102. package/dist/types/loader/src/remoteLoader.d.ts.map +0 -1
  103. package/dist/types/loader/src/resolvers.d.ts.map +0 -1
  104. package/dist/types/loader/src/types.d.ts.map +0 -1
  105. package/dist/types/react/src/components/AppshellComponent.d.ts +0 -30
  106. package/dist/types/react/src/components/AppshellComponent.d.ts.map +0 -1
  107. package/dist/types/react/src/components/LoadingError.d.ts.map +0 -1
  108. package/dist/types/react/src/components/ReactHost.d.ts +0 -9
  109. package/dist/types/react/src/components/ReactHost.d.ts.map +0 -1
  110. package/dist/types/react/src/contexts/GlobalConfigContext.d.ts +0 -11
  111. package/dist/types/react/src/contexts/GlobalConfigContext.d.ts.map +0 -1
  112. package/dist/types/react/src/contexts/ManifestContext.d.ts +0 -12
  113. package/dist/types/react/src/contexts/ManifestContext.d.ts.map +0 -1
  114. package/dist/types/react/src/contexts/MetadataContext.d.ts +0 -11
  115. package/dist/types/react/src/contexts/MetadataContext.d.ts.map +0 -1
  116. package/dist/types/react/src/contexts/RemoteContext.d.ts.map +0 -1
  117. package/dist/types/react/src/hooks/useGlobalConfig.d.ts +0 -4
  118. package/dist/types/react/src/hooks/useGlobalConfig.d.ts.map +0 -1
  119. package/dist/types/react/src/hooks/useManifest.d.ts +0 -4
  120. package/dist/types/react/src/hooks/useManifest.d.ts.map +0 -1
  121. package/dist/types/react/src/hooks/useMetadata.d.ts +0 -4
  122. package/dist/types/react/src/hooks/useMetadata.d.ts.map +0 -1
  123. package/dist/types/react/src/hooks/useRemote.d.ts.map +0 -1
  124. package/dist/types/react/src/index.d.ts.map +0 -1
  125. package/dist/types/react/src/resources/jsonResource.d.ts.map +0 -1
  126. package/dist/types/react/src/types.d.ts.map +0 -1
  127. package/src/components/AppshellComponent.tsx +0 -82
  128. package/src/components/LoadingError.tsx +0 -15
  129. package/src/components/ReactHost.tsx +0 -55
  130. package/src/contexts/GlobalConfigContext.tsx +0 -17
  131. package/src/contexts/ManifestContext.tsx +0 -40
  132. package/src/contexts/MetadataContext.tsx +0 -17
  133. package/src/contexts/RemoteContext.tsx +0 -22
  134. package/src/hooks/useGlobalConfig.ts +0 -7
  135. package/src/hooks/useManifest.ts +0 -7
  136. package/src/hooks/useMetadata.ts +0 -6
  137. package/src/hooks/useRemote.ts +0 -7
  138. package/src/index.ts +0 -11
  139. package/src/resources/jsonResource.ts +0 -35
  140. package/src/types.ts +0 -3
  141. package/tsconfig.json +0 -7
  142. package/webpack.config.js +0 -42
@@ -1,7 +1,15 @@
1
- import { AppshellManifest, Metadata } from './types';
1
+ import { AppshellManifest, Metadata, ModuleFederationLoader } from './types';
2
2
  export type PublishOptions = {
3
3
  registry: string;
4
4
  token?: string;
5
+ /**
6
+ * Where this package belongs, when the package name declares it.
7
+ *
8
+ * Omitted means the publisher's own namespace, which is how every publish worked before
9
+ * this existed. The registry refuses a scope the caller does not own, so declaring one
10
+ * is a statement of fact rather than a request.
11
+ */
12
+ scopeId?: string;
5
13
  name: string;
6
14
  version: string;
7
15
  manifest: AppshellManifest;
@@ -11,19 +19,93 @@ export type PublishOptions = {
11
19
  force?: boolean;
12
20
  };
13
21
  export type PublishResult = {
14
- /** `scope/name@version`. The scope comes from the token, not the caller. */
22
+ /** `scope/name@version`. From the package name where it declares one, else the token. */
15
23
  id: string;
16
24
  created: boolean;
25
+ /** Empty unless a shared block was sent. See `openOverlay`. */
26
+ divergence: SharedDivergence[];
17
27
  };
18
28
  /**
19
29
  * Publishing the same content twice is a no-op; publishing different content
20
30
  * under a version that already exists is rejected by the registry, unless
21
31
  * `force` is set and the registry is configured to honor it (dev registries).
22
32
  */
23
- export declare const publish: ({ registry, token, name, version, manifest, visibility, metadata, force, }: PublishOptions) => Promise<PublishResult>;
33
+ export declare const publish: ({ registry, token, scopeId, name, version, manifest, visibility, metadata, force, }: PublishOptions) => Promise<PublishResult>;
24
34
  /**
25
- * Activating a newer version of an already active app upgrades it in place.
26
- * @param environment `scope/name`
35
+ * Activating a newer version of an already active package upgrades it in place.
36
+ * @param application `scope/name`
27
37
  */
28
- export declare const activate: (registry: string, environment: string, appId: string, token?: string) => Promise<void>;
29
- //# sourceMappingURL=publish.d.ts.map
38
+ export declare const activate: (registry: string, application: string, packageId: string, token?: string) => Promise<void>;
39
+ /** What an overlay redirects a single remote to, or introduces one as. */
40
+ export type OverlayRemotePatch = {
41
+ remoteEntryUrl: string;
42
+ manifestUrl?: string;
43
+ /**
44
+ * How to load this build's copy, from the Module Federation config that emits it.
45
+ *
46
+ * Sent because the loader describes the code being loaded, and an overlay points at
47
+ * this build rather than the published one. Without it a redirect addresses a dev
48
+ * server's bundle by whatever container name the last publish happened to have, so
49
+ * renaming the container locally resolves to a container the browser cannot find.
50
+ *
51
+ * It is also what lets an overlay introduce a component that is not published yet: a
52
+ * redirect inherits the published loader, an addition has no published anything.
53
+ */
54
+ loader?: ModuleFederationLoader;
55
+ /**
56
+ * The remote's `metadata` as this build declares it.
57
+ *
58
+ * Sent because a developer iterating on `appshell.config.yaml` is editing metadata as
59
+ * much as code; without it an overlay serves their new bundle beside the published
60
+ * route, displayName and icon. The registry replaces rather than merges, so a key
61
+ * removed from the yaml disappears rather than standing.
62
+ */
63
+ metadata?: Metadata;
64
+ };
65
+ /** One shared dependency where a local build and the published version disagree. */
66
+ export type SharedDivergence = {
67
+ packageId: string;
68
+ shareScope: string;
69
+ packageName: string;
70
+ published?: string;
71
+ local?: string;
72
+ singleton: {
73
+ published: boolean;
74
+ local: boolean;
75
+ };
76
+ };
77
+ export type OpenedOverlay = {
78
+ id: string;
79
+ confirmUrl: string;
80
+ url: string;
81
+ remotes: string[];
82
+ expiresAt: string;
83
+ /**
84
+ * False when an overlay was already open for this developer and this one extended it.
85
+ * A browser carries a single overlay id, so an extended overlay is one some browser has
86
+ * already confirmed — nothing needs sending back to the confirmation page.
87
+ */
88
+ created: boolean;
89
+ /**
90
+ * What this build declares that the published version does not. Empty unless a shared
91
+ * block was sent — see `openOverlay`.
92
+ */
93
+ divergence: SharedDivergence[];
94
+ };
95
+ /**
96
+ * Points some of an application's remotes at a developer's own machine, for that
97
+ * developer only.
98
+ *
99
+ * This is what a local dev loop does instead of republishing. A published version is
100
+ * immutable and content-addressed; overwriting one on every rebuild makes the digest
101
+ * describe whoever built last, and two developers sharing a registry overwrite each
102
+ * other. An overlay is per-developer, per-browser and expiring, so neither happens.
103
+ *
104
+ * Extending is the normal case rather than the exception: the registry merges remotes
105
+ * into whatever overlay this developer already holds, so serving two micro-frontends
106
+ * locally redirects both without minting a second overlay or asking for confirmation
107
+ * twice.
108
+ *
109
+ * @param application `scope/name`
110
+ */
111
+ export declare const openOverlay: (registry: string, application: string, remotes: Record<string, OverlayRemotePatch>, token?: string, shared?: Record<string, unknown>, shellFlavor?: "prod" | "dev") => Promise<OpenedOverlay>;
@@ -18,4 +18,3 @@ export declare const groupByBaselineModule: (conflicts: Record<string, Compariso
18
18
  */
19
19
  declare const _default: (workingDir: string, registry: string, conflicts: Record<string, ComparisonResult>, resolutionStrategy?: ResolutionStrategy, packageManager?: PackageManager, dryRun?: boolean) => Promise<void>;
20
20
  export default _default;
21
- //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1,11 @@
1
+ import https from 'https';
2
+ export declare const caFile: () => string | undefined;
3
+ /**
4
+ * The agent to use for registry and issuer requests, or undefined when no CA is
5
+ * configured and Node's defaults apply.
6
+ *
7
+ * A configured file that does not exist throws rather than being skipped: falling back
8
+ * silently would reproduce the original certificate error, having been told exactly how
9
+ * to avoid it.
10
+ */
11
+ 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,184 @@ 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", "defaultScope", "authIssuer", "clientId", "apiKey", "apiKeyHeader", "caFile", "api"];
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;
64
+ /**
65
+ * The platform api the registry's organizations live on, e.g. https://api.appshell.org.
66
+ * Optional: absent, `appshell org` derives it from the auth issuer's host (auth.<domain> →
67
+ * api.<domain>), and a registry run without a platform behind it has no organizations.
68
+ */
69
+ api?: string;
48
70
  registry: string;
49
- environment: string;
50
- scopeId: string;
71
+ application: string;
72
+ /**
73
+ * Which namespace an unqualified name belongs to, absent anything better.
74
+ *
75
+ * Addressing only, and named for it. It was `scope-id`, which read as *the scope this
76
+ * account has* — identity — and it is not: the registry takes a caller's scope from the
77
+ * token, and this value never reaches it. Publishing takes it from the package name.
78
+ * So a `scope-id` here decided where names resolved while something else decided where
79
+ * writes landed, and the two could disagree without anything saying so.
80
+ *
81
+ * It earns its place all the same: `resolveScopeId` falls back to the account's own
82
+ * scope and deliberately refuses to guess when an account owns several, and this is how
83
+ * that is settled without passing a flag to every command.
84
+ */
85
+ defaultScope: string;
51
86
  authIssuer: string;
52
87
  clientId: string;
53
88
  };
89
+ /**
90
+ * Neither `url` nor `filename`.
91
+ *
92
+ * `url` is an origin, and an origin belongs to a deployment: a package is published once
93
+ * and deployed many times, so a url here would freeze one environment's answer into an
94
+ * immutable version and make the artifact's digest depend on where it was built.
95
+ *
96
+ * `filename` was a hand-written copy of the Module Federation `filename`, which is what
97
+ * actually decides the file webpack emits. Two statements of one fact, and only one of
98
+ * them is enforced by anything.
99
+ */
54
100
  export type AppshellConfigRemote<TMetadata = Metadata> = {
55
101
  id: string;
56
- url: string;
57
- filename: string;
58
102
  metadata: TMetadata;
59
103
  };
60
104
  export type AppshellConfig<TMetadata = Metadata> = {
61
105
  name?: string;
62
- remotes?: Record<string, AppshellConfigRemote<TMetadata>>;
63
- environment?: Record<string, unknown>;
106
+ /**
107
+ * What the registry should publish this package as. `--visibility` overrides it.
108
+ *
109
+ * Declared here but deliberately absent from the manifest, as `name` already is: the
110
+ * manifest is hashed into the package digest, and visibility is not a property of the
111
+ * artifact. Keeping it out is what lets a package be made public later without its
112
+ * content changing identity.
113
+ */
114
+ visibility?: 'public' | 'private';
115
+ /**
116
+ * What this package publishes, keyed by federation entrypoint.
117
+ *
118
+ * Appshell's own word rather than a framework's. It was `remotes`, which is MF's word
119
+ * for the opposite — what a package consumes — so the file read inverted to anyone who
120
+ * knew the framework. `exposes` would fix that and put MF's vocabulary at the top level
121
+ * of appshell's model, which is what the loader recipe exists to prevent.
122
+ */
123
+ components?: Record<string, AppshellConfigRemote<TMetadata>>;
124
+ /**
125
+ * What this package consumes, by the name it refers to them by.
126
+ *
127
+ * A flat list because a referenced remote is required by definition: unbound, the region
128
+ * renders an error. `RemoteSlot`'s `fallback` is a loading placeholder — it shows while
129
+ * the remote arrives, not when it is absent — so unlike a design token's `var()`
130
+ * fallback it describes no degraded-but-working state.
131
+ *
132
+ * The application binds each name to a registry address, so a package never states the
133
+ * scope its siblings were published into — which it cannot know, since scope is assigned
134
+ * by whoever publishes.
135
+ */
136
+ remotes?: string[];
137
+ vars?: Record<string, unknown>;
64
138
  overrides?: AppshellOverrides;
65
139
  };
66
140
  export type AppshellTemplate<TMetadata = Metadata> = {
67
141
  name?: string;
68
- remotes?: Record<string, AppshellConfigRemote<TMetadata>>;
142
+ /** Carried from the yaml for publish to read; never mapped into the manifest. */
143
+ visibility?: 'public' | 'private';
144
+ components?: Record<string, AppshellConfigRemote<TMetadata>>;
145
+ remotes?: string[];
69
146
  module: ModuleFederationPluginOptions;
70
- environment?: Record<string, unknown>;
147
+ vars?: Record<string, unknown>;
148
+ tokens?: Record<string, AppshellTokenUsage>;
71
149
  overrides?: AppshellOverrides;
72
150
  };
73
151
  /** 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;
152
+ /** The parts of a remote an application may point somewhere else. */
153
+ export type RemoteOverride = {
154
+ remoteEntryUrl?: string;
155
+ manifestUrl?: string;
82
156
  };
83
157
  export type AppshellOverrides = {
84
- environment: Record<string, Record<string, string | number | undefined>>;
158
+ vars: Record<string, Record<string, string | number | undefined>>;
159
+ /**
160
+ * Where an application loads a remote from, keyed by registry address.
161
+ *
162
+ * A package is published once; an application is deployed many times, per environment.
163
+ * The origin a bundle is served from is a property of a deployment, so it belongs to
164
+ * whoever deploys rather than being frozen into an immutable artifact at publish — which
165
+ * is also what makes adopting someone else's package and serving it yourself a spec edit
166
+ * rather than a republish.
167
+ *
168
+ * `filename` stays in the manifest: `remoteEntry.js` is genuinely build output. Only the
169
+ * origin varies by environment.
170
+ */
171
+ remotes?: Record<string, RemoteOverride>;
172
+ };
173
+ /**
174
+ * Which design tokens a package's own output reaches for. Observed from the emitted
175
+ * assets rather than declared: the CSS already says it, and a hand-kept list is a copy
176
+ * that drifts the first time someone adds a token and forgets the yaml.
177
+ *
178
+ * `required` is a reference with no fallback — the package has no plan B. `optional` is
179
+ * `var(--appshell-x, something)`, which degrades on its own. That split is read off what
180
+ * the author wrote rather than asked of them.
181
+ */
182
+ export type AppshellTokenUsage = {
183
+ required: string[];
184
+ optional: string[];
185
+ };
186
+ /** A shared-dependency contract, named as one framework's model among possible models. */
187
+ export type SharedContract = {
188
+ apiVersion: 'federation.appshell.org/v1';
189
+ kind: 'ModuleFederation';
190
+ /** Keyed by share scope, as Module Federation groups them. */
191
+ scopes: Record<string, SharedObject>;
85
192
  };
86
193
  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>>;
194
+ /** What this package publishes, keyed by federation entrypoint. */
195
+ components: Record<string, PublishedRemote<TMetadata>>;
196
+ /** What it consumes, by local name; the application binds each to an address. */
197
+ remotes?: string[];
198
+ /**
199
+ * The shared-dependency contract this package was built against.
200
+ *
201
+ * Tagged like the loader recipe, and for the same reason: share scopes, singletons and
202
+ * version ranges are Module Federation's model of the problem, which single-spa and
203
+ * import maps solve differently. This replaced `modules`, which stored MF's plugin
204
+ * options verbatim — one reader took two fields from it, while its source paths and
205
+ * type-generation flags sat inside the package digest.
206
+ */
207
+ shared?: SharedContract;
208
+ vars: Record<string, Record<string, string | number | undefined>>;
209
+ /** Keyed by federation scope, so a merged manifest still says which package needs what. */
210
+ tokens?: Record<string, AppshellTokenUsage>;
90
211
  overrides?: AppshellOverrides;
91
212
  };
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;
213
+ /**
214
+ * A remote as a package publishes it: what the build knows about itself, and nothing
215
+ * about where it ends up.
216
+ *
217
+ * Distinct from `AppshellRemote`, which is the same remote after the registry has
218
+ * resolved it for the browser. They were one type, which is why the origin ended up in
219
+ * the artifact: the browser genuinely needs a url, so the published form appeared to as
220
+ * well. The registry supplies it at composition, from the address and its serving plane.
221
+ */
222
+ export type PublishedRemote<TMetadata = Metadata> = {
223
+ id: string;
224
+ loader: RemoteLoader;
225
+ metadata: TMetadata;
98
226
  };
99
227
  /** An `AppshellRemote` the registry already resolved, so the browser needs no manifest fetch. */
100
228
  export type ResolvedRemote<TMetadata = Metadata> = AppshellRemote<TMetadata>;
@@ -102,19 +230,45 @@ export type ResolvedRemote<TMetadata = Metadata> = AppshellRemote<TMetadata>;
102
230
  * The wire contract for `window.__appshell_config__`. Deliberately not an
103
231
  * `AppshellManifest`: that is a build artifact, and reusing it left it unclear
104
232
  * 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.
233
+ * config and never crosses the wire; `vars` arrives already merged with the
234
+ * application's overrides, leaving the browser only local overrides to apply.
107
235
  */
108
236
  export type AppshellComposition<TMetadata = Metadata> = {
109
237
  /** `scope/name` — makes the payload self-describing for fetch-on-miss and for `env diff`. */
110
- environmentId: string;
238
+ applicationId: string;
111
239
  revision: number;
112
240
  /** The remote key the host mounts at the root, and the props it is given. */
113
241
  root: string;
114
242
  rootProps: Record<string, unknown>;
115
243
  index: AppshellIndex;
116
244
  remotes: Record<string, ResolvedRemote<TMetadata>>;
117
- environment: Record<string, Record<string, string | number | undefined>>;
245
+ vars: Record<string, Record<string, string | number | undefined>>;
246
+ /**
247
+ * Present whenever a per-developer overlay changed anything about this render — a
248
+ * redirected remote, a different shell bundle, a substituted theme, or any combination.
249
+ * The shell is expected to surface it: a page that quietly runs code from somewhere
250
+ * else is the one thing this feature must never be, and swapping the shell or the theme
251
+ * out counts.
252
+ *
253
+ * `shellFlavor` is what was actually served, not what was asked for. `theme` is the ref
254
+ * the overlay substituted, present only when it substituted one.
255
+ */
256
+ overlay?: {
257
+ id: string;
258
+ remotes: string[];
259
+ /**
260
+ * Those of `remotes` the overlay introduced rather than redirected — components the
261
+ * application does not publish, running for this developer and nobody else.
262
+ *
263
+ * Separate from `remotes` because the two are not the same claim. A redirected
264
+ * component exists for everyone and this browser runs a different copy of it; an
265
+ * added one does not exist outside this overlay at all, so a feature built on top of
266
+ * one works here and is absent everywhere else.
267
+ */
268
+ added?: string[];
269
+ shellFlavor: 'prod' | 'dev';
270
+ theme?: string;
271
+ };
118
272
  };
119
273
  /**
120
274
  * Advanced configuration for modules that should be exposed by this container.
@@ -293,4 +447,3 @@ export interface ModuleFederationPluginOptions {
293
447
  */
294
448
  shared?: (string | SharedObject)[] | SharedObject;
295
449
  }
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
@@ -1,6 +1,20 @@
1
1
  import yargs from 'yargs';
2
2
  import { CliConfig } from '../types';
3
+ /**
4
+ * The addressing default: which namespace an unqualified name resolves to.
5
+ *
6
+ * Named `default-scope` and not `scope-id`, because the old name described identity —
7
+ * *the scope this account has* — and the value has never been that. The registry takes a
8
+ * caller's scope from the token and publishing takes it from the package name; this
9
+ * reaches neither. A `scope-id` deciding where names resolved while something else decided
10
+ * where writes landed is how the two came to disagree without anything saying so.
11
+ *
12
+ * Stated once because the cli and the webpack plugin both need the answer, and two
13
+ * precedence chains for one setting is how they drift apart.
14
+ */
15
+ export declare const resolveDefaultScope: (config: {
16
+ defaultScope?: string;
17
+ }, env?: NodeJS.ProcessEnv) => string | undefined;
3
18
  export declare const readConfig: (configPath: string) => CliConfig;
4
19
  export declare const writeConfig: (configPath: string, config: CliConfig) => void;
5
20
  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;
@@ -1,10 +1,7 @@
1
1
  export { default as blur } from './blur';
2
2
  export { compareDependencies, compareDependency, compareSharedDependencies, compareSharedModules, extractDependencies, printResults, } from './compare';
3
- export { mergeConfigWithArgs, readConfig, writeConfig } from './config';
3
+ export { mergeConfigWithArgs, readConfig, resolveDefaultScope, 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
@@ -5,4 +5,3 @@ type ErrorProps = {
5
5
  };
6
6
  declare const LoadingError: FC<ErrorProps>;
7
7
  export default LoadingError;
8
- //# sourceMappingURL=LoadingError.d.ts.map
@@ -0,0 +1,28 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ export type ExtendedProps = Record<string, unknown>;
3
+ export type RemoteSlotProps<TProps extends ExtendedProps = ExtendedProps> = {
4
+ remote: string;
5
+ fallback?: ReactNode;
6
+ } & TProps;
7
+ /**
8
+ * Loads a remote once and leaves it alone.
9
+ *
10
+ * Keeping a remote current while it is being developed is not this component's job.
11
+ * A remote served by a dev server ships webpack's HMR runtime and a dev-server client
12
+ * inside its own `remoteEntry`, so it applies its own edits in place and React Fast
13
+ * Refresh swaps the component implementations underneath this tree — no reload, and no
14
+ * remount that would discard state this component never owned.
15
+ *
16
+ * Watching the remote's socket from here and reloading the page was strictly worse: it
17
+ * raced the remote's own update, and it threw away the entire composed app to deliver a
18
+ * change to one subtree. When webpack genuinely cannot apply an update, the remote's own
19
+ * client still falls back to a full reload — which is the right place for that decision,
20
+ * because it is the only side that knows whether the update applied.
21
+ */
22
+ declare const RemoteSlot: {
23
+ <TProps extends ExtendedProps>({ remote, fallback, ...rest }: RemoteSlotProps<TProps>): ReactElement<TProps>;
24
+ defaultProps: {
25
+ fallback: undefined;
26
+ };
27
+ };
28
+ export default RemoteSlot;
@@ -1,12 +1,10 @@
1
1
  import { AppshellRemote } from '@appshell/config';
2
2
  import type { FC, ReactNode } from 'react';
3
- import React from 'react';
4
3
  interface RemoteProviderProps {
5
4
  remote?: AppshellRemote;
6
5
  children: ReactNode;
7
6
  }
8
- export declare const RemoteContext: React.Context<AppshellRemote | undefined>;
7
+ export declare const RemoteContext: import("react").Context<AppshellRemote | undefined>;
9
8
  export declare const RemoteProvider: FC<RemoteProviderProps>;
10
- export declare const RemoteConsumer: React.Consumer<AppshellRemote | undefined>;
9
+ export declare const RemoteConsumer: import("react").Consumer<AppshellRemote | undefined>;
11
10
  export default RemoteContext;
12
- //# sourceMappingURL=RemoteContext.d.ts.map
@@ -1,5 +1,4 @@
1
1
  import { AppshellRemote } from '@appshell/config';
2
- /** The remote backing the nearest `AppshellComponent` — it already knows its own key. */
2
+ /** The remote backing the nearest `RemoteSlot` — it already knows its own key. */
3
3
  declare const _default: () => AppshellRemote | undefined;
4
4
  export default _default;
5
- //# sourceMappingURL=useRemote.d.ts.map