@collagejs/core 0.3.0 β 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -14
- package/dist/MountedPiece.d.ts +6 -5
- package/dist/MountedPiece.js +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mountPiece.d.ts +5 -5
- package/dist/mountPiece.js +2 -2
- package/dist/preventRemount.d.ts +32 -0
- package/dist/preventRemount.js +40 -0
- package/dist/types.d.ts +54 -7
- package/package.json +14 -17
- package/dist/internal-types.d.ts +0 -8
- package/dist/internal-types.js +0 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Micro library for framework-agnostic micro-frontends
|
|
4
4
|
|
|
5
|
-
**π§π§
|
|
5
|
+
**π§π§ I'M LATE. WORK IN PROGRESS... ETA: JULY, 2026 π§π§**
|
|
6
6
|
|
|
7
7
|
**If you're interested, star β the repository to get updates on the progress in your GH homepage.**
|
|
8
8
|
|
|
@@ -10,7 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
[Full Documentation](https://collagejs.dev)
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
> π° **SAD NEWS**
|
|
14
|
+
>
|
|
15
|
+
> `single-spa` creator *Joel/Jolyn Denning* [has passed away in late 2025](https://github.com/single-spa/single-spa/issues/1361#issuecomment-3991093643).
|
|
16
|
+
|
|
17
|
+
*CollageJS* is a very, very small library that enables the composition of a web user interface with micro-frontends created with any technology (Svelte, React, Vue, SolidJS, HTMX, Lit, Ripple-TS, etc.). It is heavily inspired by the *parcel* concept in the excellent `single-spa` routing library.
|
|
14
18
|
|
|
15
19
|
## How It Works
|
|
16
20
|
|
|
@@ -19,9 +23,10 @@
|
|
|
19
23
|
```typescript
|
|
20
24
|
type UnmountFn = () => Promise<void>;
|
|
21
25
|
|
|
22
|
-
interface CorePiece<TProps> {
|
|
23
|
-
mount: (target: HTMLElement, props?: TProps) => Promise<UnmountFn>;
|
|
26
|
+
interface CorePiece<TProps, TCap> {
|
|
27
|
+
mount: (target: HTMLElement | ShadowRoot, props?: TProps) => Promise<UnmountFn>;
|
|
24
28
|
update?: (props: TProps) => Promise<void>;
|
|
29
|
+
readonly capabilities?: CorePieceCapabilities & TCap;
|
|
25
30
|
};
|
|
26
31
|
```
|
|
27
32
|
> βΉοΈ These types were simplified. See the real ones after installing the library.
|
|
@@ -30,6 +35,7 @@ In short: Micro-frontend creators must simply provide a way to generate an obje
|
|
|
30
35
|
|
|
31
36
|
- `mount` mounts the micro-frontend user interface in the document
|
|
32
37
|
- `update` updates the properties given to the micro-frontend
|
|
38
|
+
- `capabilities` is a feature introduced in v0.5.0 that allows core piece objects to declare its capabilities (see more in its own section)
|
|
33
39
|
|
|
34
40
|
The `update` function is optional. The `mount` function must return a cleanup function that, ideally, reverts the mounting process.
|
|
35
41
|
|
|
@@ -42,7 +48,7 @@ This is a simple example that shows a tiny, yet complete micro-frontend made wit
|
|
|
42
48
|
```typescript
|
|
43
49
|
export function buildTestPiece<TProps extends Record<string, any> = Record<string, any>>(
|
|
44
50
|
callbacks?: {
|
|
45
|
-
mount: (target:
|
|
51
|
+
mount: (target: AcceptableTarget, props?: MountProps<TProps>) => void | (() => void);
|
|
46
52
|
unmount: () => void;
|
|
47
53
|
update: (props: TProps) => void;
|
|
48
54
|
}
|
|
@@ -50,7 +56,7 @@ export function buildTestPiece<TProps extends Record<string, any> = Record<strin
|
|
|
50
56
|
let pre: HTMLElement;
|
|
51
57
|
return {
|
|
52
58
|
// Here's mount():
|
|
53
|
-
async mount(target:
|
|
59
|
+
async mount(target: AcceptableTarget, props?: MountProps<TProps>) {
|
|
54
60
|
const delayMountCb = callbacks?.mount?.(target, props);
|
|
55
61
|
pre = document.createElement('pre');
|
|
56
62
|
pre.setAttribute('data-testid', pieceTestId);
|
|
@@ -63,7 +69,7 @@ export function buildTestPiece<TProps extends Record<string, any> = Record<strin
|
|
|
63
69
|
// Here's the unmounting function:
|
|
64
70
|
return () => {
|
|
65
71
|
callbacks?.unmount?.();
|
|
66
|
-
|
|
72
|
+
pre.remove();
|
|
67
73
|
return Promise.resolve();
|
|
68
74
|
};
|
|
69
75
|
},
|
|
@@ -138,7 +144,7 @@ Then the micro-frontends: The concept doesn't exist. At this point (after crea
|
|
|
138
144
|
|
|
139
145
|
While `single-spa` asks you to shape your module exports in a particular way (the lifecycle functions), *CollageJS* imposes no such restriction. It is just not necessary. Just make sure you can get an object of type `CorePiece` to the `<Piece>` component of your preferred framework. Then use your framework's marvels to make the `<Piece>` component appear or disappear.
|
|
140
146
|
|
|
141
|
-
Yes, you'll still be working with import maps. They are super handy. We provide an enhanced (and simplified at the same time) version of `import-map-overrides` named `@collagejs/imo`. It only supports the `overridable-importmap` type (and therefore only native import maps for native ES modules), but carries support for our `@collagejs/aim` plug-in that
|
|
147
|
+
Yes, you'll still be working with import maps. They are super handy. We provide an enhanced (and simplified at the same time) version of `import-map-overrides` named `@collagejs/imo`. It only supports the `overridable-importmap` type (and therefore only native import maps for native ES modules), but carries support for our `@collagejs/vite-aim` plug-in that lets you statically import from micro-frontends. **That's right! We are free from dynamic `import()` calls!** We can statically import from micro-frontends. Furthermore, it has a more modern user interface:
|
|
142
148
|
|
|
143
149
|

|
|
144
150
|
|
|
@@ -152,19 +158,31 @@ In *CollageJS*, `CorePiece.mount()` returns the clean-up (unmounting) function.
|
|
|
152
158
|
|
|
153
159
|
Gone. There's no equivalent in *CollageJS*, as experience with `single-spa` has demonstrated that is rarely needed, and if needed, one can do this initialization easily without having to impose the function requirement. At least for now, there's no foreseeable future where an initialization function similar to `single-spa`'s `bootstrap()` will be defined. But we agree: *Never say NEVER*.
|
|
154
160
|
|
|
161
|
+
## I'm Curious about `capabilities`
|
|
162
|
+
|
|
163
|
+
Ok, in a nutshell, what inspired this feature was implementing the ability to mount micro-frontends (and its CSS) inside shadow root objects, plus give the developers a good DX. In short: If you, the dev, said you wanted the MFE in an open shadow root, but then changed your mind and now you want a closed shadow root, we have to unmount and remount or some other hacky things, like a full page reload. But for this case, and at least in Svelte, we could relocate the component's generated DOM tree without remounting.
|
|
164
|
+
|
|
165
|
+
This sounds great, but what if that breaks the MFE? So the safe path is not to take advantage of cool features. This conclusion made me sad as a developer. Therefore, enter `capabilties`.
|
|
166
|
+
|
|
167
|
+
The `capabilities` object simply states what the core piece object is able to withstand. The core library defines 2 capabilities, and devs can add user-defined ones to the object.
|
|
168
|
+
|
|
169
|
+
One of the stock (or "official" if you will) capabilities is `relocatable: boolean`. If a core piece object returns `true` for `relocatable`, it is making this statement: "I can take DOM relocation operations without going through the mounting lifecycle".
|
|
170
|
+
|
|
171
|
+
With this reassurance at hand, framework adapters like `@collagejs/svelte` and others that can pull the trick cleanly can go ahead and do it, enhancing DX. This made me happy once more as a developer, and hope that it makes more devs happy.
|
|
172
|
+
|
|
155
173
|
## Packages
|
|
156
174
|
|
|
157
175
|
| Package | Status | Links | Description |
|
|
158
176
|
| - | - | - | - |
|
|
159
177
|
| `@collagejs/core` | βοΈ | (This repo) | Core functionality. Provides the general mounting and unmounting logic. |
|
|
160
178
|
| `@collagejs/vite-css` | βοΈ | [Repo](https://github.com/collagejs/vite) | Vite plug-in that offers a CSS-mounting algorithm that is fully compatible with Vite's CSS bundling, including split CSS. It also features FOUC prevention. |
|
|
161
|
-
| `@collagejs/vite-im` |
|
|
162
|
-
| `@collagejs/vite-aim` |
|
|
163
|
-
| `@collagejs/imo` |
|
|
179
|
+
| `@collagejs/vite-im` | βοΈ | [Repo](https://github.com/collagejs/vite) | Vite plug-in that injects an import map and optionally the `@collagejs/imo` package to define bare module identifiers for easy micro-frontend loading and debugging. |
|
|
180
|
+
| `@collagejs/vite-aim` | βοΈ | [Repo](https://github.com/collagejs/vite) | Vite-plugin that auto-externalizes the module identifiers found in the application's import map. It receives the import map live (and with overrides) from the client. This enables static imports (no more dynamic `import()` calls). |
|
|
181
|
+
| `@collagejs/imo` | βοΈ | [Repo](https://github.com/collagejs/imo) | Our version of `import-map-overrides` that does the usual overriding of import map entries, plus it transmits the final import map to Vite development servers found in it. |
|
|
164
182
|
| `@collagejs/svelte` | βοΈ | [Repo](https://github.com/collagejs/svelte) | Svelte component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
|
|
165
|
-
| `@collagejs/react` |
|
|
166
|
-
| `@collagejs/solidjs` | β | [Repo](https://github.com/collagejs/
|
|
167
|
-
| `@collagejs/vue` |
|
|
183
|
+
| `@collagejs/react` | βοΈ | [Repo](https://github.com/collagejs/react) | React component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
|
|
184
|
+
| `@collagejs/solidjs` | β | [Repo](https://github.com/collagejs/solidjs) | SolidJS component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
|
|
185
|
+
| `@collagejs/vue` | π§ | [Repo](https://github.com/collagejs/vue) | **Next in line** VueJS component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
|
|
168
186
|
| `@collagejs/angular` | β | | **External help needed.** We don't have expertise in Angular, nor do we want to acquire it. If you're an Angular developer, please consider contributing. |
|
|
169
187
|
|
|
170
188
|
## Other Repositories
|
package/dist/MountedPiece.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { CorePiece, MountPiece } from "./types.js";
|
|
1
|
+
import type { CorePiece, MountPiece, AcceptableTarget, CorePieceCapabilities } from "./types.js";
|
|
2
2
|
export declare const mountKey: unique symbol;
|
|
3
|
-
export declare class MountedPiece<TProps extends Record<string, any> = Record<string, any
|
|
3
|
+
export declare class MountedPiece<TProps extends Record<string, any> = Record<string, any>, TCap extends Record<string, any> = {}> {
|
|
4
4
|
#private;
|
|
5
|
-
get mountPiece():
|
|
6
|
-
constructor(piece: CorePiece<TProps>, mountPiece: MountPiece<TProps>, parent?: MountedPiece);
|
|
7
|
-
[mountKey](target:
|
|
5
|
+
get mountPiece(): <UProps extends Record<string, any> = Record<string, any>, UCap extends CorePieceCapabilities = CorePieceCapabilities>(piece: CorePiece<UProps, UCap> | Promise<CorePiece<UProps, UCap>>, target: AcceptableTarget, props?: UProps) => Promise<MountedPiece<UProps, UCap>>;
|
|
6
|
+
constructor(piece: CorePiece<TProps, TCap>, mountPiece: MountPiece<TProps, TCap>, parent?: MountedPiece);
|
|
7
|
+
[mountKey](target: AcceptableTarget, props?: TProps): Promise<void>;
|
|
8
8
|
unmount(): Promise<void>;
|
|
9
9
|
update(props: TProps): Promise<void>;
|
|
10
|
+
get capabilities(): (CorePieceCapabilities & TCap) | undefined;
|
|
10
11
|
}
|
package/dist/MountedPiece.js
CHANGED
|
@@ -63,8 +63,12 @@ export class MountedPiece {
|
|
|
63
63
|
if (this.#parent) {
|
|
64
64
|
this.#parent.#childPieces.delete((item) => item.#id === this.#id);
|
|
65
65
|
}
|
|
66
|
+
this.#cleanup = undefined;
|
|
66
67
|
}
|
|
67
68
|
update(props) {
|
|
68
69
|
return doUpdate(this.#piece.update, props);
|
|
69
70
|
}
|
|
71
|
+
get capabilities() {
|
|
72
|
+
return this.#piece.capabilities;
|
|
73
|
+
}
|
|
70
74
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/mountPiece.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { MountedPiece } from "./MountedPiece.js";
|
|
2
|
-
import type { CorePiece, MountPiece } from "./types.js";
|
|
2
|
+
import type { AcceptableTarget, CorePiece, MountPiece } from "./types.js";
|
|
3
3
|
/**
|
|
4
4
|
* Constructor type for MountedPiece classes.
|
|
5
5
|
*
|
|
6
6
|
* This exists merely to allow unit testing.
|
|
7
7
|
*/
|
|
8
8
|
export interface MountedPieceConstructor {
|
|
9
|
-
new
|
|
9
|
+
new (piece: CorePiece<any, any>, mountPiece: MountPiece<any, any>, parent?: MountedPiece<any, any>): MountedPiece<any, any>;
|
|
10
10
|
}
|
|
11
|
-
export declare function mountPieceCore<TProps extends Record<string, any> = Record<string, any
|
|
11
|
+
export declare function mountPieceCore<TProps extends Record<string, any> = Record<string, any>, TCap extends Record<string, any> = {}>(this: MountedPiece<any, any> | undefined, piece: CorePiece<TProps, TCap> | Promise<CorePiece<TProps, TCap>>, target: AcceptableTarget, props?: TProps, MountedPieceClass?: MountedPieceConstructor): Promise<MountedPiece<TProps, TCap>>;
|
|
12
12
|
/**
|
|
13
13
|
* Mounts the CollageJS piece as a child of the target element.
|
|
14
14
|
* @param piece The CollageJS piece to mount.
|
|
15
|
-
* @param target The target element to mount the piece
|
|
15
|
+
* @param target The target HTML element or shadow root where to mount the piece.
|
|
16
16
|
* @param props The properties to pass to the piece.
|
|
17
17
|
*/
|
|
18
|
-
export declare function mountPiece<TProps extends Record<string, any> = Record<string, any
|
|
18
|
+
export declare function mountPiece<TProps extends Record<string, any> = Record<string, any>, TCap extends Record<string, any> = {}>(piece: CorePiece<TProps, TCap>, target: AcceptableTarget, props?: TProps): Promise<MountedPiece<TProps, TCap>>;
|
package/dist/mountPiece.js
CHANGED
|
@@ -3,14 +3,14 @@ export async function mountPieceCore(piece, target, props, MountedPieceClass = M
|
|
|
3
3
|
if (piece instanceof Promise) {
|
|
4
4
|
piece = await piece;
|
|
5
5
|
}
|
|
6
|
-
const mp = new MountedPieceClass(piece,
|
|
6
|
+
const mp = new MountedPieceClass(piece, mountPieceCore, this);
|
|
7
7
|
await mp[mountKey](target, props);
|
|
8
8
|
return mp;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* Mounts the CollageJS piece as a child of the target element.
|
|
12
12
|
* @param piece The CollageJS piece to mount.
|
|
13
|
-
* @param target The target element to mount the piece
|
|
13
|
+
* @param target The target HTML element or shadow root where to mount the piece.
|
|
14
14
|
* @param props The properties to pass to the piece.
|
|
15
15
|
*/
|
|
16
16
|
export function mountPiece(piece, target, props) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { MountFn } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a mount function that can only be called once. If the mount function is called more than once, it will throw
|
|
4
|
+
* an error. This effectively prevents a piece from being mounted more than once.
|
|
5
|
+
*
|
|
6
|
+
* Use this on core piece objects that cannot guarantee the integrity of their state after they unmount.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import { preventRemount } from "@collagejs/core";
|
|
10
|
+
*
|
|
11
|
+
* export function myCorePieceFactory() {
|
|
12
|
+
* ...
|
|
13
|
+
* return {
|
|
14
|
+
* // The most logical place is at the very beginning of the mount array.
|
|
15
|
+
* mount: [preventRemount(), myMount],
|
|
16
|
+
* update: ...,
|
|
17
|
+
* capabilities: {
|
|
18
|
+
* // Informational only: Allow the core piece object to answer the question.
|
|
19
|
+
* remountable: false,
|
|
20
|
+
* }
|
|
21
|
+
* };
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* ### π‘ Tips
|
|
25
|
+
*
|
|
26
|
+
* - Try to always follow the "fail fast" principle, so call `preventRemount()` as early as possible in the mount array.
|
|
27
|
+
* - If for any reason the mount operation is expected to fail (for whatever needed reason), consider moving the call
|
|
28
|
+
* to `preventRemount()` after the mount operation that may fail, so that the piece object does not have to be
|
|
29
|
+
* discarded unnecessarily.
|
|
30
|
+
* @returns A mount function that throws an error if called more than once.
|
|
31
|
+
*/
|
|
32
|
+
export declare function preventRemount<TProps extends Record<string, any> = Record<string, any>>(): MountFn<TProps>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a mount function that can only be called once. If the mount function is called more than once, it will throw
|
|
3
|
+
* an error. This effectively prevents a piece from being mounted more than once.
|
|
4
|
+
*
|
|
5
|
+
* Use this on core piece objects that cannot guarantee the integrity of their state after they unmount.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import { preventRemount } from "@collagejs/core";
|
|
9
|
+
*
|
|
10
|
+
* export function myCorePieceFactory() {
|
|
11
|
+
* ...
|
|
12
|
+
* return {
|
|
13
|
+
* // The most logical place is at the very beginning of the mount array.
|
|
14
|
+
* mount: [preventRemount(), myMount],
|
|
15
|
+
* update: ...,
|
|
16
|
+
* capabilities: {
|
|
17
|
+
* // Informational only: Allow the core piece object to answer the question.
|
|
18
|
+
* remountable: false,
|
|
19
|
+
* }
|
|
20
|
+
* };
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* ### π‘ Tips
|
|
24
|
+
*
|
|
25
|
+
* - Try to always follow the "fail fast" principle, so call `preventRemount()` as early as possible in the mount array.
|
|
26
|
+
* - If for any reason the mount operation is expected to fail (for whatever needed reason), consider moving the call
|
|
27
|
+
* to `preventRemount()` after the mount operation that may fail, so that the piece object does not have to be
|
|
28
|
+
* discarded unnecessarily.
|
|
29
|
+
* @returns A mount function that throws an error if called more than once.
|
|
30
|
+
*/
|
|
31
|
+
export function preventRemount() {
|
|
32
|
+
let mountCount = 0;
|
|
33
|
+
return () => {
|
|
34
|
+
if (mountCount > 0) {
|
|
35
|
+
throw new Error("This piece cannot be mounted more than once. If this is unexpected, you might be unknowingly sharing the same piece object in different places or Piece components.");
|
|
36
|
+
}
|
|
37
|
+
++mountCount;
|
|
38
|
+
return Promise.resolve(() => Promise.resolve());
|
|
39
|
+
};
|
|
40
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defines the type for acceptable targets for mounting *CollageJS* pieces.
|
|
3
|
+
*/
|
|
4
|
+
export type AcceptableTarget = HTMLElement | ShadowRoot;
|
|
1
5
|
/**
|
|
2
6
|
* Properties passed to `mount()` functions of `CorePiece` objects. It extends the piece's supported objects with a
|
|
3
7
|
* property of type `symbol` that carries the piece parent's `mountPiece()` function.
|
|
@@ -11,11 +15,11 @@ export type MountProps<TProps extends Record<string, any> = Record<string, any>>
|
|
|
11
15
|
export type UnmountFn = () => Promise<void>;
|
|
12
16
|
/**
|
|
13
17
|
* Type that defines the signature of the functions accepted in `CorePiece.mount`.
|
|
14
|
-
* @param target The HTML target where the piece will be mounted as a child.
|
|
18
|
+
* @param target The HTML or shadow root target where the piece will be mounted as a child.
|
|
15
19
|
* @param props The piece's initial property values.
|
|
16
20
|
* @returns A promise to the cleanup function that unmounts the piece.
|
|
17
21
|
*/
|
|
18
|
-
export type MountFn<TProps extends Record<string, any> = Record<string, any>> = (target:
|
|
22
|
+
export type MountFn<TProps extends Record<string, any> = Record<string, any>> = (target: AcceptableTarget, props?: MountProps<TProps>) => Promise<UnmountFn>;
|
|
19
23
|
/**
|
|
20
24
|
* Type that defines the signature of the functions accepted in `CorePiece.update`.
|
|
21
25
|
* @param props The new property values for the mounted piece.
|
|
@@ -30,10 +34,39 @@ export type Mount<TProps extends Record<string, any> = Record<string, any>> = Mo
|
|
|
30
34
|
* Defines the accepted shapes for `CorePiece.update`.
|
|
31
35
|
*/
|
|
32
36
|
export type Update<TProps extends Record<string, any> = Record<string, any>> = UpdateFn<TProps> | UpdateFn<TProps>[] | Update[];
|
|
37
|
+
/**
|
|
38
|
+
* Defines the capabilities of a `CorePiece` object recognized by the core *CollageJS* library. These capabilities are
|
|
39
|
+
* used to determine how the core library should handle the piece's lifecycle, or whether a particular action or
|
|
40
|
+
* feature can be enabled or allowed.
|
|
41
|
+
*/
|
|
42
|
+
export type CorePieceCapabilities = {
|
|
43
|
+
/**
|
|
44
|
+
* Informative only: Indicates that the piece can be mounted more than once.
|
|
45
|
+
*
|
|
46
|
+
* Since `@collagejs/core` never injects code into `CorePiece` objects, it cannot enforce this capability. The
|
|
47
|
+
* only place where this can be enforced is at `CorePiece.mount`. The core library provides the `preventRemount()`
|
|
48
|
+
* function to help developers create mount functions that throw an error if called more than once.
|
|
49
|
+
*
|
|
50
|
+
* **π‘TIP**: Official framework adapters provide this functionality.
|
|
51
|
+
*/
|
|
52
|
+
remountable?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Indicates that the piece allows relocation of its HTML markup to a new parent without unmounting. For the best
|
|
55
|
+
* development experience, piece objects should always strive to be relocatable.
|
|
56
|
+
*
|
|
57
|
+
* If `false`, `Piece` components created with official framework adapters will most likely have to ask HMR to
|
|
58
|
+
* perform a full page reload whenever the developer changes shadow DOM options, like moving from an open to a
|
|
59
|
+
* closed shadow root.
|
|
60
|
+
*
|
|
61
|
+
* If `true` **and if the framework is capable** (i. e. Svelte), the piece can be relocated without unmounting, and
|
|
62
|
+
* HMR will be able to update the shadow root options without a full page reload.
|
|
63
|
+
*/
|
|
64
|
+
relocatable?: boolean;
|
|
65
|
+
};
|
|
33
66
|
/**
|
|
34
67
|
* Defines the contract that objects must follow in order to be mountable as *CollageJS* pieces (micro-frontends).
|
|
35
68
|
*/
|
|
36
|
-
export interface CorePiece<TProps extends Record<string, any> = Record<string, any
|
|
69
|
+
export interface CorePiece<TProps extends Record<string, any> = Record<string, any>, TCap extends Record<string, any> = {}> {
|
|
37
70
|
/**
|
|
38
71
|
* Mounts the piece (micro-frontend) in the document. Every mount function should always return a cleanup function
|
|
39
72
|
* that, when called, unmounts the piece.
|
|
@@ -44,11 +77,21 @@ export interface CorePiece<TProps extends Record<string, any> = Record<string, a
|
|
|
44
77
|
* while mounted in the document, and all property values must have been passed during mounting.
|
|
45
78
|
*/
|
|
46
79
|
update?: Update<TProps>;
|
|
80
|
+
/**
|
|
81
|
+
* Declares the capabilities of the piece. This is optional. If not provided, the piece will be assumed to have no
|
|
82
|
+
* capabilities, and the core library will treat it as a simple piece that can be mounted once and unmounted once, and
|
|
83
|
+
* that cannot be relocated or re-mounted.
|
|
84
|
+
*
|
|
85
|
+
* **π‘TIP**: Always try to at least create pieces that are relocatable by not storing the original target element in
|
|
86
|
+
* the piece's state. Instead, just use the piece's root element's `parentElement` property to determine the
|
|
87
|
+
* current parent element.
|
|
88
|
+
*/
|
|
89
|
+
readonly capabilities?: CorePieceCapabilities & TCap;
|
|
47
90
|
}
|
|
48
91
|
/**
|
|
49
92
|
* Defines the shape of the object returned by the process of mounting a `CorePiece` object.
|
|
50
93
|
*/
|
|
51
|
-
export interface MountedPiece<TProps extends Record<string, any> = Record<string, any
|
|
94
|
+
export interface MountedPiece<TProps extends Record<string, any> = Record<string, any>, TCap extends Record<string, any> = {}> {
|
|
52
95
|
/**
|
|
53
96
|
* Function used to apply updated property values to the mounted `CorePiece` object.
|
|
54
97
|
*/
|
|
@@ -64,7 +107,11 @@ export interface MountedPiece<TProps extends Record<string, any> = Record<string
|
|
|
64
107
|
* **IMPORTANT:** Always use this function instead of the global `mountPiece` function when mounting other
|
|
65
108
|
* `CorePiece` objects inside the mounted `CorePiece` object to prevent lifecycle issues.
|
|
66
109
|
*/
|
|
67
|
-
mountPiece:
|
|
110
|
+
mountPiece<UProps extends Record<string, any> = Record<string, any>, UCap extends CorePieceCapabilities = CorePieceCapabilities>(piece: CorePiece<UProps, UCap> | Promise<CorePiece<UProps, UCap>>, target: AcceptableTarget, props?: UProps): Promise<MountedPiece<UProps, UCap>>;
|
|
111
|
+
/**
|
|
112
|
+
* The declared capabilities of the mounted `CorePiece` object.
|
|
113
|
+
*/
|
|
114
|
+
readonly capabilities: (CorePieceCapabilities & TCap) | undefined;
|
|
68
115
|
}
|
|
69
116
|
/**
|
|
70
117
|
* Type definition for the `mountPiece` functions that mount *CollageJS* pieces in the HTML document.
|
|
@@ -73,10 +120,10 @@ export interface MountedPiece<TProps extends Record<string, any> = Record<string
|
|
|
73
120
|
* generates a version of the global function that works identically, except that it tracks the `CollageJS` pieces
|
|
74
121
|
* mounted with it so these are unmounted automatically as soon as the parent is unmounted.
|
|
75
122
|
* @param piece `CorePiece` object to mount in the provided target, or a promise that resolves said object.
|
|
76
|
-
* @param target HTML element where to mount
|
|
123
|
+
* @param target HTML element or shadow root where to mount.
|
|
77
124
|
* @param props Optional properties for the `CorePiece` object.
|
|
78
125
|
*/
|
|
79
|
-
export type MountPiece<TProps extends Record<string, any> = Record<string, any
|
|
126
|
+
export type MountPiece<TProps extends Record<string, any> = Record<string, any>, TCap extends Record<string, any> = {}> = (piece: CorePiece<TProps, TCap> | Promise<CorePiece<TProps, TCap>>, target: AcceptableTarget, props?: TProps) => Promise<MountedPiece<TProps, TCap>>;
|
|
80
127
|
declare global {
|
|
81
128
|
/**
|
|
82
129
|
* Defines the capabilities in the global `CollageJs` object.
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@collagejs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Core functionality for CollageJS.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "npm run
|
|
9
|
-
"test:unit": "
|
|
10
|
-
"test:watch": "
|
|
8
|
+
"test": "npm run test:unit && npm run test:types",
|
|
9
|
+
"test:unit": "vitest run",
|
|
10
|
+
"test:watch": "vitest",
|
|
11
11
|
"test:types": "tstyche ./tests/typetests",
|
|
12
|
-
"
|
|
12
|
+
"clean": "rimraf dist",
|
|
13
|
+
"build": "npm run clean && tsc && pwsh -File ./post-build.ps1 && publint",
|
|
13
14
|
"check": "tsc --noEmit"
|
|
14
15
|
},
|
|
15
16
|
"keywords": [
|
|
@@ -67,19 +68,15 @@
|
|
|
67
68
|
],
|
|
68
69
|
"sideEffects": false,
|
|
69
70
|
"devDependencies": {
|
|
70
|
-
"@types/
|
|
71
|
-
"@types/
|
|
72
|
-
"@types/mocha": "^10.0.10",
|
|
73
|
-
"@types/node": "^25.0.1",
|
|
71
|
+
"@types/jsdom": "^28.0.3",
|
|
72
|
+
"@types/node": "^26.0.0",
|
|
74
73
|
"@types/sinon": "^21.0.0",
|
|
75
|
-
"
|
|
76
|
-
"jsdom": "^27.3.0",
|
|
77
|
-
"mocha": "^11.7.2",
|
|
74
|
+
"jsdom": "^29.1.1",
|
|
78
75
|
"publint": "^0.3.11",
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
76
|
+
"rimraf": "^6.1.3",
|
|
77
|
+
"sinon": "^22.0.0",
|
|
78
|
+
"tstyche": "^7.2.1",
|
|
79
|
+
"typescript": "^6.0.3",
|
|
80
|
+
"vitest": "^4.1.9"
|
|
84
81
|
}
|
|
85
82
|
}
|
package/dist/internal-types.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { UnmountFn, UpdateFn } from "./types.js";
|
|
2
|
-
export declare namespace Internal {
|
|
3
|
-
type MountedPiece<TProps extends Record<string, any> = Record<string, any>> = {
|
|
4
|
-
update: UpdateFn<TProps>;
|
|
5
|
-
unmount: UnmountFn;
|
|
6
|
-
childPieces: Map<string, MountedPiece>;
|
|
7
|
-
};
|
|
8
|
-
}
|
package/dist/internal-types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|