@appshell/webpack-plugin 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 (82) hide show
  1. package/README.md +21 -24
  2. package/dist/main.js +3 -3
  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/runtime/src/errors.d.ts +32 -0
  28. package/dist/types/runtime/src/identity.d.ts +47 -0
  29. package/dist/types/runtime/src/index.d.ts +6 -0
  30. package/dist/types/runtime/src/store.d.ts +25 -0
  31. package/dist/types/runtime/src/types.d.ts +9 -0
  32. package/dist/types/runtime/src/wire.d.ts +58 -0
  33. package/dist/types/tokens/src/contract.d.ts +51 -0
  34. package/dist/types/tokens/src/contrast.d.ts +37 -0
  35. package/dist/types/tokens/src/index.d.ts +4 -0
  36. package/dist/types/tokens/src/presets.d.ts +4 -0
  37. package/dist/types/tokens/src/theme.d.ts +54 -0
  38. package/dist/types/webpack-plugin/src/AppshellPlugin.d.ts +46 -5
  39. package/dist/types/webpack-plugin/src/devHint.d.ts +45 -0
  40. package/dist/types/webpack-plugin/src/index.d.ts +3 -1
  41. package/dist/types/webpack-plugin/src/shared.d.ts +36 -0
  42. package/package.json +11 -4
  43. package/dist/types/config/src/axios.d.ts.map +0 -1
  44. package/dist/types/config/src/configmap.d.ts.map +0 -1
  45. package/dist/types/config/src/context.d.ts.map +0 -1
  46. package/dist/types/config/src/credentials.d.ts.map +0 -1
  47. package/dist/types/config/src/deregister.d.ts +0 -3
  48. package/dist/types/config/src/deregister.d.ts.map +0 -1
  49. package/dist/types/config/src/generate.env.d.ts +0 -3
  50. package/dist/types/config/src/generate.env.d.ts.map +0 -1
  51. package/dist/types/config/src/generate.global-config.d.ts +0 -10
  52. package/dist/types/config/src/generate.global-config.d.ts.map +0 -1
  53. package/dist/types/config/src/generate.manifest.d.ts.map +0 -1
  54. package/dist/types/config/src/index.d.ts.map +0 -1
  55. package/dist/types/config/src/mappers/appshell.config.d.ts.map +0 -1
  56. package/dist/types/config/src/outdated.d.ts.map +0 -1
  57. package/dist/types/config/src/publish.d.ts.map +0 -1
  58. package/dist/types/config/src/register.d.ts +0 -4
  59. package/dist/types/config/src/register.d.ts.map +0 -1
  60. package/dist/types/config/src/sync.d.ts.map +0 -1
  61. package/dist/types/config/src/types.d.ts.map +0 -1
  62. package/dist/types/config/src/utils/blur.d.ts.map +0 -1
  63. package/dist/types/config/src/utils/compare.d.ts.map +0 -1
  64. package/dist/types/config/src/utils/config.d.ts.map +0 -1
  65. package/dist/types/config/src/utils/copy.d.ts.map +0 -1
  66. package/dist/types/config/src/utils/index.d.ts.map +0 -1
  67. package/dist/types/config/src/utils/isValidUrl.d.ts +0 -3
  68. package/dist/types/config/src/utils/isValidUrl.d.ts.map +0 -1
  69. package/dist/types/config/src/utils/list.d.ts.map +0 -1
  70. package/dist/types/config/src/utils/load.d.ts.map +0 -1
  71. package/dist/types/config/src/utils/loadJson.d.ts +0 -10
  72. package/dist/types/config/src/utils/loadJson.d.ts.map +0 -1
  73. package/dist/types/config/src/utils/merge.d.ts +0 -4
  74. package/dist/types/config/src/utils/merge.d.ts.map +0 -1
  75. package/dist/types/config/src/validators/AppshellGlobalConfigValidator.d.ts +0 -4
  76. package/dist/types/config/src/validators/AppshellGlobalConfigValidator.d.ts.map +0 -1
  77. package/dist/types/config/src/validators/AppshellManifestValidator.d.ts +0 -4
  78. package/dist/types/config/src/validators/AppshellManifestValidator.d.ts.map +0 -1
  79. package/dist/types/config/src/validators/AppshellTemplateValidator.d.ts.map +0 -1
  80. package/dist/types/config/src/validators/index.d.ts.map +0 -1
  81. package/dist/types/webpack-plugin/src/AppshellPlugin.d.ts.map +0 -1
  82. package/dist/types/webpack-plugin/src/index.d.ts.map +0 -1
@@ -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
@@ -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>;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The token contract: the complete, fixed vocabulary a package may consume and an
3
+ * Application must supply.
4
+ *
5
+ * Small and stable is the property that matters. A package authors against these names
6
+ * with fallbacks (`var(--appshell-primary, #0af)`) and renders standalone; an Application
7
+ * supplies the values and every package it composes moves together.
8
+ */
9
+ export type Mode = 'light' | 'dark';
10
+ /** Colour roles an Application's *base* supplies — everything not tied to the accent. */
11
+ export declare const BASE_COLOR_ROLES: readonly ["surface", "on-surface", "surface-raised", "on-surface-raised", "text-muted", "border", "danger", "on-danger", "warning", "on-warning", "success", "on-success"];
12
+ /** Colour roles an Application's *accent* supplies. */
13
+ export declare const ACCENT_COLOR_ROLES: readonly ["primary", "on-primary", "secondary", "on-secondary"];
14
+ /**
15
+ * Derived rather than authored. Hover and active are computed from their accent with
16
+ * `color-mix`, and the focus ring is picked per base+accent so it stays visible. A theme
17
+ * may override any of them; none has to be supplied.
18
+ */
19
+ export declare const DERIVED_COLOR_ROLES: readonly ["primary-hover", "primary-active", "secondary-hover", "secondary-active", "focus-ring"];
20
+ /**
21
+ * Named for their role, not their size. A numeric scale would reintroduce exactly the
22
+ * divergence this contract exists to prevent — one author mapping `h1` to `2xl` and
23
+ * another to `xl` is how headings stop matching across a composed page.
24
+ */
25
+ export declare const TYPE_ROLES: readonly ["font-body", "font-mono", "font-size-h1", "font-size-h2", "font-size-h3", "font-size-h4", "font-size-h5", "font-size-h6", "font-size-body", "font-size-small", "line-height-tight", "line-height-normal"];
26
+ /** Genuinely a scale. Nobody wants `--appshell-space-card-padding`. */
27
+ export declare const DIMENSION_ROLES: readonly ["space-xs", "space-sm", "space-md", "space-lg", "space-xl", "radius-sm", "radius-md", "radius-lg"];
28
+ export type BaseColorRole = (typeof BASE_COLOR_ROLES)[number];
29
+ export type AccentColorRole = (typeof ACCENT_COLOR_ROLES)[number];
30
+ export type DerivedColorRole = (typeof DERIVED_COLOR_ROLES)[number];
31
+ export type TypeRole = (typeof TYPE_ROLES)[number];
32
+ export type DimensionRole = (typeof DIMENSION_ROLES)[number];
33
+ export type TokenRole = BaseColorRole | AccentColorRole | DerivedColorRole | TypeRole | DimensionRole;
34
+ export declare const TOKEN_ROLES: readonly TokenRole[];
35
+ export type BaseTokens = Record<BaseColorRole, string>;
36
+ export type AccentTokens = Record<AccentColorRole, string>;
37
+ export type Theme = Record<TokenRole, string>;
38
+ /** The custom property a role is published as. */
39
+ export declare const cssVar: (role: TokenRole) => string;
40
+ /**
41
+ * Pairs the registry checks for contrast. Because every role that carries text has an
42
+ * `on-` partner, a theme cannot express illegible text without failing this list — which
43
+ * is the failure that actually reaches users, and the one a CSS parser alone never catches.
44
+ */
45
+ export declare const TEXT_PAIRS: readonly (readonly [TokenRole, TokenRole])[];
46
+ /** Muted text has no `on-` partner; it is read against both surfaces. */
47
+ export declare const MUTED_AGAINST: readonly TokenRole[];
48
+ /** Non-text, so 3:1 rather than 4.5:1 — WCAG 1.4.11. */
49
+ export declare const NON_TEXT_PAIRS: readonly (readonly [TokenRole, TokenRole])[];
50
+ export declare const AA_TEXT = 4.5;
51
+ export declare const AA_NON_TEXT = 3;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Contrast checking for a theme.
3
+ *
4
+ * Syntax validation on its own earns little: it catches `--appshell-primary: bananas` and
5
+ * misses `--appshell-on-primary: #fff` on `--appshell-primary: #fff`, which is valid CSS
6
+ * and invisible text. Checking the `on-` pairs catches the failure that reaches users, and
7
+ * subsumes syntax validation for free — a value that will not parse cannot be measured.
8
+ */
9
+ import { type Theme, type TokenRole } from './contract';
10
+ type Rgb = [number, number, number];
11
+ /** Returns undefined rather than throwing — an unmeasurable value is reported, not fatal. */
12
+ export declare const parseColor: (value: string) => Rgb | undefined;
13
+ /** WCAG 2.1 contrast ratio, 1–21. */
14
+ export declare const contrastRatio: (a: Rgb, b: Rgb) => number;
15
+ /**
16
+ * A colour as `#rrggbb`.
17
+ *
18
+ * `<meta name="theme-color">` takes a CSS colour, but browser support for `oklch` there
19
+ * is not something to rely on for a hint the page cannot detect the failure of — a
20
+ * value the browser does not understand is simply ignored, silently.
21
+ */
22
+ export declare const toHex: (value: string) => string | undefined;
23
+ export type ContrastFinding = {
24
+ roles: [TokenRole, TokenRole];
25
+ ratio?: number;
26
+ required: number;
27
+ reason: 'below-threshold' | 'unparseable';
28
+ };
29
+ /**
30
+ * Every finding for a theme. Empty means it passes.
31
+ *
32
+ * `color-mix` values are skipped rather than failed: hover and active are derived from
33
+ * roles that are themselves checked, and resolving them needs a browser.
34
+ */
35
+ export declare const validateTheme: (theme: Theme) => ContrastFinding[];
36
+ export declare const describeFinding: ({ roles, ratio, required, reason }: ContrastFinding) => string;
37
+ export {};
@@ -0,0 +1,4 @@
1
+ export * from './contract';
2
+ export { contrastRatio, describeFinding, parseColor, toHex, validateTheme, type ContrastFinding, } from './contrast';
3
+ export { ACCENTS, BASES, FOCUS_RINGS } from './presets';
4
+ export { DEFAULT_TYPE_AND_DIMENSIONS, composeTheme, cssFrom, pinnedMode, resolveTheme, toCss, type ColorScheme, type CssOptions, type ResolvedTheme, type ThemeSelection, } from './theme';
@@ -0,0 +1,4 @@
1
+ import type { AccentTokens, BaseTokens, Mode } from './contract';
2
+ export declare const BASES: Record<string, Record<Mode, BaseTokens>>;
3
+ export declare const ACCENTS: Record<string, AccentTokens>;
4
+ export declare const FOCUS_RINGS: Record<string, Record<string, Record<Mode, string>>>;
@@ -0,0 +1,54 @@
1
+ import { type AccentTokens, type BaseTokens, type Mode, type Theme } from './contract';
2
+ /**
3
+ * `system` follows the viewer's preference. Pinning a scheme is for an application that
4
+ * ships one look on purpose, and it is honoured all the way down: the palette stops
5
+ * varying, the root is stamped so the tokens cannot be swapped underneath it, and the
6
+ * browser is told which scheme to render its own scrollbars and form controls in.
7
+ */
8
+ export type ColorScheme = 'system' | 'light' | 'dark';
9
+ export type ThemeSelection = {
10
+ /** A base preset name, or the base's own token values. */
11
+ base: string | Record<Mode, BaseTokens>;
12
+ /** An accent preset name, or the accent's own token values. */
13
+ accent: string | AccentTokens;
14
+ /** Defaults to `system`. */
15
+ colorScheme?: ColorScheme;
16
+ /** Overrides applied last, so an Application can adjust a preset without forking it. */
17
+ overrides?: Partial<Theme>;
18
+ };
19
+ /** The mode a pinned scheme resolves to, or undefined when it follows the viewer. */
20
+ export declare const pinnedMode: (selection: ThemeSelection) => Mode | undefined;
21
+ /** Type and dimensions do not vary by mode, and no preset currently changes them. */
22
+ export declare const DEFAULT_TYPE_AND_DIMENSIONS: Record<string, string>;
23
+ /** The full token map for one mode. */
24
+ export declare const composeTheme: (selection: ThemeSelection, mode: Mode) => Theme;
25
+ /**
26
+ * A theme with both modes already worked out.
27
+ *
28
+ * This is the shape a *published* theme stores. Resolving a selection and emitting CSS
29
+ * used to be one step, which meant the only way to render a theme was to re-resolve its
30
+ * preset names — so the values behind a name lived in whatever build was deployed, and an
31
+ * Application's recorded appearance moved when that build did. Materialising both modes
32
+ * lets the values be stored, versioned and rendered from, rather than looked up.
33
+ */
34
+ export type ResolvedTheme = Record<Mode, Theme>;
35
+ /** Works out both modes of a selection, including any overrides it carries. */
36
+ export declare const resolveTheme: (selection: ThemeSelection) => ResolvedTheme;
37
+ export type CssOptions = {
38
+ /** Defaults to `system`. Belongs to whoever is rendering, not to the theme. */
39
+ colorScheme?: ColorScheme;
40
+ /** Applied over the resolved values, so a consumer can adjust without forking. */
41
+ overrides?: Partial<Theme>;
42
+ };
43
+ /**
44
+ * Three states, not two: an explicit choice in either direction, and the system default
45
+ * when nothing is stamped on the root. A theme that only handled `prefers-color-scheme`
46
+ * would give a viewer no way to override it.
47
+ */
48
+ export declare const cssFrom: (resolved: ResolvedTheme, options?: CssOptions) => string;
49
+ /**
50
+ * Resolve and emit in one step. The authoring path — a preset name in hand, CSS wanted.
51
+ * The registry uses `cssFrom` against a stored theme instead, so what it renders cannot
52
+ * drift from what was published.
53
+ */
54
+ export declare const toCss: (selection: ThemeSelection) => string;
@@ -3,7 +3,7 @@ import { Compiler, WebpackOptionsNormalized, WebpackPluginInstance } from 'webpa
3
3
  type AppshellPluginOptions = {
4
4
  config?: string;
5
5
  registry?: string;
6
- environment?: string;
6
+ application?: string;
7
7
  publish?: boolean;
8
8
  force?: boolean;
9
9
  };
@@ -24,14 +24,56 @@ export default class AppshellPlugin {
24
24
  static findModuleFederationPlugin(webpackConfig: WebpackOptionsNormalized): ModuleFederationPluginInstance | undefined;
25
25
  static createTemplate(config: AppshellConfig, plugin: ModuleFederationPluginInstance): AppshellTemplate;
26
26
  static validate(template: AppshellTemplate): boolean;
27
+ /**
28
+ * Which tokens this package's output actually reaches for.
29
+ *
30
+ * Read from the emitted assets rather than declared. The CSS already states it, and a
31
+ * hand-kept list is a second copy that goes stale the first time somebody adds a token
32
+ * and forgets to update it. This cannot drift, because it *is* the usage.
33
+ *
34
+ * A role referenced both with and without a fallback counts as required: one place in
35
+ * the package has nothing to fall back to.
36
+ *
37
+ * The blind spot is a reference built at runtime from a constructed string, which no
38
+ * static scan sees — the same limit Tailwind has with dynamic class names. It fails
39
+ * toward under-reporting, never toward inventing a requirement.
40
+ *
41
+ * Takes file contents rather than webpack assets: by `afterEmit` the compilation has
42
+ * swapped its sources for `SizeOnlySource`, which knows a length and nothing else.
43
+ * The files are on disk by then, which is what the hook means.
44
+ */
45
+ static tokenUsage(sources?: Record<string, string>): {
46
+ required: string[];
47
+ optional: string[];
48
+ unknown: string[];
49
+ };
50
+ /**
51
+ * Whether a request is shared, and shared as a singleton. `shared` has four shapes —
52
+ * an object, an array of names, an array of objects, or a mix — and a bare name shares
53
+ * without making it a singleton, which for the vars store is the same as not sharing it.
54
+ */
55
+ static sharedSingleton(shared: ModuleFederationPluginOptions['shared'], request: string): {
56
+ declared: boolean;
57
+ singleton: boolean;
58
+ };
27
59
  /**
28
60
  * Publish identity is the npm identity of the package being built, not the module
29
61
  * federation name — the registry requires a lowercase name and has no other source
30
62
  * for a version. The scope is taken from the caller's token, so it is stripped here.
31
63
  */
64
+ /**
65
+ * Points this package's remotes at the running dev server, for this developer only.
66
+ *
67
+ * Deliberately incapable of failing a build. A dev server that will not start because a
68
+ * registry is unreachable, a token expired, or a package was never published is worse
69
+ * than one serving code the browser cannot yet compose — the developer can still see
70
+ * their own output, and the message says what to do about the rest.
71
+ */
72
+ private static redirectToDevServer;
32
73
  static identify(context: string): {
33
- name: string;
34
74
  version: string;
75
+ scopeId?: string;
76
+ name: string;
35
77
  };
36
78
  /**
37
79
  * Warns when an env var or explicit option points somewhere other than the
@@ -39,10 +81,10 @@ export default class AppshellPlugin {
39
81
  */
40
82
  static overrideNotices(effective: {
41
83
  registry?: string;
42
- environment?: string;
84
+ application?: string;
43
85
  }, persisted: {
44
86
  registry?: string;
45
- environment?: string;
87
+ application?: string;
46
88
  }): string[];
47
89
  /**
48
90
  * Apply the plugin
@@ -52,4 +94,3 @@ export default class AppshellPlugin {
52
94
  apply(compiler: Compiler): void;
53
95
  }
54
96
  export {};
55
- //# sourceMappingURL=AppshellPlugin.d.ts.map
@@ -0,0 +1,45 @@
1
+ export declare const DEV_HINT_FILE = ".appshell-dev.json";
2
+ export declare const DEV_HINT_VERSION = 1;
3
+ export type DevHint = {
4
+ version: number;
5
+ /** Where this package's dev server is reachable, as a browser on this machine would ask. */
6
+ origin: string;
7
+ /** From the federation `filename`, so a reader can probe without asking the registry. */
8
+ remoteEntryPath: string;
9
+ /**
10
+ * Diagnostics only. Deliberately not a liveness signal: a server running happily for
11
+ * hours writes an old timestamp, and one that crashed a second ago writes a fresh one.
12
+ * Whether the origin is live is answered by asking the origin.
13
+ */
14
+ writtenAt: string;
15
+ };
16
+ type DevServerOptions = {
17
+ [index: string]: unknown;
18
+ } | false | undefined;
19
+ /**
20
+ * Whether this dev server's hot-reload client has an address a browser can actually dial.
21
+ *
22
+ * webpack-dev-server normalizes `client.webSocketURL` into an object before a plugin ever
23
+ * sees it, filling the hostname from whatever the server **bound**. So a server listening
24
+ * on every interface hands its client `0.0.0.0`, which nothing can open a socket to, and
25
+ * asking whether the option is *set* cannot tell that apart from a deliberate choice —
26
+ * it is always set. The dialable address is the property that matters, so that is what is
27
+ * checked, against the same host list `devServerOrigin` already rejects for the same
28
+ * reason one line down.
29
+ *
30
+ * The cost of getting this wrong is silence: the bundle renders, the server reports a
31
+ * successful recompile, and edits never arrive.
32
+ */
33
+ export declare const hotSocketIsDialable: (devServer: DevServerOptions) => boolean;
34
+ export declare const devServerOrigin: (devServer: DevServerOptions) => string | undefined;
35
+ /**
36
+ * Records where this package is being served from while a dev server is running, so tooling
37
+ * can offer it instead of asking a developer to repeat a port they have already
38
+ * configured. Written on every serve build and left to be cleaned with the output
39
+ * directory; nothing removes it when the server stops, which is exactly why a reader
40
+ * must confirm the origin rather than trust the file.
41
+ */
42
+ export declare const writeDevHint: (outputDir: string, devServer: DevServerOptions, remoteEntryPath: string, now?: Date) => DevHint | undefined;
43
+ /** webpack-dev-server sets this itself, however webpack was invoked. */
44
+ export declare const isServing: () => boolean;
45
+ export {};
@@ -3,4 +3,6 @@
3
3
  */
4
4
  export type { AppshellManifest } from '@appshell/config';
5
5
  export { default as AppshellPlugin } from './AppshellPlugin';
6
- //# sourceMappingURL=index.d.ts.map
6
+ export { DEV_HINT_FILE, DEV_HINT_VERSION, devServerOrigin, writeDevHint } from './devHint';
7
+ export type { DevHint } from './devHint';
8
+ export { appshellShared, type AppshellSharedOptions } from './shared';
@@ -0,0 +1,36 @@
1
+ import type { SharedObject } from '@appshell/config';
2
+ export type AppshellSharedOptions = {
3
+ /** Include the React bindings and React itself. */
4
+ react?: boolean;
5
+ /**
6
+ * Usually your package.json `dependencies`. Anything named here is pinned to the range
7
+ * you depend on; anything absent is left for module federation to infer, which it does
8
+ * from the installed package.
9
+ */
10
+ dependencies?: Record<string, string>;
11
+ /** Merged last, so a package can still say something the preset does not. */
12
+ extra?: SharedObject;
13
+ };
14
+ /**
15
+ * The `shared` block an Appshell package needs, so it is not written out by hand in every
16
+ * webpack config and wrong in one of them.
17
+ *
18
+ * It exists because the alternative failed in practice: the examples in this repo declared
19
+ * `@appshell/react` as a singleton in three configs and omitted it in a fourth, which is
20
+ * silent until a root package calls `useRemote()` and gets `undefined`.
21
+ *
22
+ * `AppshellPlugin` cannot inject this itself — `ModuleFederationPlugin` reads its own
23
+ * options during its `apply`, which webpack has already run by the time it reaches ours.
24
+ * Spread into your own config, it sidesteps plugin ordering entirely:
25
+ *
26
+ * ```js
27
+ * const { appshellShared } = require('@appshell/webpack-plugin');
28
+ * const { dependencies } = require('./package.json');
29
+ *
30
+ * new ModuleFederationPlugin({
31
+ * shared: appshellShared({ react: true, dependencies }),
32
+ * });
33
+ * ```
34
+ */
35
+ export declare const appshellShared: ({ react, dependencies, extra, }?: AppshellSharedOptions) => SharedObject;
36
+ export default appshellShared;
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@appshell/webpack-plugin",
3
- "version": "1.0.0-alpha.9",
3
+ "version": "1.0.0-alpha.91",
4
4
  "description": "Webpack plugin used to generate a global Appshell configuration for micro-frontends built with Module Federation",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/types/webpack-plugin/src/index.d.ts",
7
- "repository": "https://github.com/appshell-org/appshell.git",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/appshellhq/appshell.git"
10
+ },
8
11
  "author": "Robert Hamilton <rh@navaris.com>",
9
12
  "publishConfig": {
10
13
  "access": "public",
@@ -17,7 +20,8 @@
17
20
  "clean": "rm -rf dist",
18
21
  "prebuild": "npm run clean",
19
22
  "start": "webpack --watch --mode development && npm run build:types",
20
- "stats": "webpack --json > stats.json"
23
+ "stats": "webpack --json > stats.json",
24
+ "typecheck": "tsc --noEmit"
21
25
  },
22
26
  "files": [
23
27
  "dist"
@@ -29,5 +33,8 @@
29
33
  "plugin"
30
34
  ],
31
35
  "license": "MIT",
32
- "gitHead": "dd1cd33cf2f014563438d29a004ce7939e65dacb"
36
+ "gitHead": "beb3e1dc02a4c32424f163da35e9ce43ee3bdb82",
37
+ "dependencies": {
38
+ "@appshell/tokens": "^1.0.0-alpha.91"
39
+ }
33
40
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"axios.d.ts","sourceRoot":"","sources":["../../../../../config/src/axios.ts"],"names":[],"mappings":";AAEA,wBAA8B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"configmap.d.ts","sourceRoot":"","sources":["../../../../../config/src/configmap.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;;YA0BrC,CAAC,SAAS,MAAM,OAAO,CAAC,aAAa,SAAS,KAAG,CAAC;qBAuBzC,cAAc;;AAEtC,wBAGE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../../config/src/context.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAaF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAAO,eAQjC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,QAAO;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAK5E,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../../../../config/src/credentials.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAKF,eAAO,MAAM,eAAe,cAC6D,CAAC;AAqB1F,eAAO,MAAM,cAAc,aAAc,MAAM,cAAc,UAAU,SAEtE,CAAC;AAEF,eAAO,MAAM,eAAe,aAAc,MAAM,SAI/C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,aAAc,MAAM,KAAG,MAAM,GAAG,SAexD,CAAC;AAEF,eAAO,MAAM,YAAY,aAAc,MAAM,KAAG,MAO/C,CAAC"}
@@ -1,3 +0,0 @@
1
- declare const _default: (moduleName: string, registry: string) => Promise<void>;
2
- export default _default;
3
- //# sourceMappingURL=deregister.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deregister.d.ts","sourceRoot":"","sources":["../../../../../config/src/deregister.ts"],"names":[],"mappings":"qCAoGkC,MAAM,YAAY,MAAM;AAA1D,wBAeE"}
@@ -1,3 +0,0 @@
1
- declare const _default: (prefix?: string) => Promise<Map<string, string | undefined>>;
2
- export default _default;
3
- //# sourceMappingURL=generate.env.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate.env.d.ts","sourceRoot":"","sources":["../../../../../config/src/generate.env.ts"],"names":[],"mappings":";AAGA,wBAuBK"}
@@ -1,10 +0,0 @@
1
- import { AppshellGlobalConfig } from './types';
2
- type GenerateGlobalConfigOptions = {
3
- insecure: boolean;
4
- apiKey?: string;
5
- apiKeyHeader?: string;
6
- proxyUrl?: string;
7
- };
8
- declare const _default: (registries: string[], options?: GenerateGlobalConfigOptions) => Promise<AppshellGlobalConfig>;
9
- export default _default;
10
- //# sourceMappingURL=generate.global-config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate.global-config.d.ts","sourceRoot":"","sources":["../../../../../config/src/generate.global-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAK/C,KAAK,2BAA2B,GAAG;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;qCAGY,MAAM,EAAE,YACX,2BAA2B,KACnC,OAAO,CAAC,oBAAoB,CAAC;AAHhC,wBA8CE"}