@raubjo/architect-core 0.1.0 → 0.1.1
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 +162 -0
- package/bun.lock +82 -1
- package/package.json +54 -6
- package/src/cache/cache.ts +2 -2
- package/src/cache/manager.ts +93 -83
- package/src/config/adapters/esm.ts +26 -0
- package/src/config/clone.ts +5 -5
- package/src/config/env.global.d.ts +2 -1
- package/src/config/env.ts +53 -55
- package/src/config/env_test.helpers.ts +58 -0
- package/src/config/repository.ts +180 -142
- package/src/container/adapters/builtin.ts +347 -0
- package/src/container/adapters/inversify.ts +123 -0
- package/src/container/contract.ts +58 -0
- package/src/container/runtime.ts +149 -0
- package/src/filesystem/adapters/local.ts +92 -83
- package/src/filesystem/adapters/local_test.helpers.ts +50 -0
- package/src/filesystem/filesystem.ts +11 -11
- package/src/foundation/application.ts +205 -175
- package/src/foundation/application_test.helpers.ts +31 -0
- package/src/index.ts +15 -6
- package/src/react.ts +2 -0
- package/src/renderers/adapters/react.tsx +35 -0
- package/src/renderers/adapters/solid.tsx +32 -0
- package/src/renderers/adapters/svelte.ts +44 -0
- package/src/renderers/adapters/vue.ts +28 -0
- package/src/renderers/contract.ts +15 -0
- package/src/runtimes/react.tsx +24 -12
- package/src/runtimes/solid.tsx +30 -0
- package/src/runtimes/svelte.ts +23 -0
- package/src/runtimes/vue.ts +20 -0
- package/src/solid.ts +2 -0
- package/src/storage/adapters/contract.ts +10 -0
- package/src/storage/adapters/indexed-db.ts +170 -156
- package/src/storage/adapters/local-storage.ts +34 -34
- package/src/storage/adapters/memory.ts +25 -25
- package/src/storage/manager.ts +65 -61
- package/src/storage/storage.ts +1 -8
- package/src/support/facades/cache.ts +40 -40
- package/src/support/facades/config.ts +78 -48
- package/src/support/facades/facade.ts +43 -28
- package/src/support/facades/storage.ts +41 -41
- package/src/support/service-provider.ts +11 -11
- package/src/support/str.ts +94 -90
- package/src/support/str_test.helpers.ts +26 -0
- package/src/svelte.ts +2 -0
- package/src/vue.ts +2 -0
- package/tsconfig.json +16 -0
- package/coverage/lcov.info +0 -1078
- package/src/config/app.ts +0 -5
- package/src/rendering/adapters/react.tsx +0 -27
- package/src/rendering/renderer.ts +0 -13
- package/src/support/providers/config-service-provider.ts +0 -19
- package/tests/application.test.ts +0 -236
- package/tests/cache-facade.test.ts +0 -45
- package/tests/cache.test.ts +0 -68
- package/tests/config-clone.test.ts +0 -31
- package/tests/config-env.test.ts +0 -88
- package/tests/config-facade.test.ts +0 -96
- package/tests/config-repository.test.ts +0 -124
- package/tests/facade-base.test.ts +0 -80
- package/tests/filesystem.test.ts +0 -81
- package/tests/runtime-react.test.tsx +0 -37
- package/tests/service-provider.test.ts +0 -23
- package/tests/storage-facade.test.ts +0 -46
- package/tests/storage.test.ts +0 -264
- package/tests/str.test.ts +0 -73
|
@@ -1,207 +1,237 @@
|
|
|
1
|
-
import CacheManager from "
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import CacheManager from "@/cache/manager";
|
|
2
|
+
import { cloneConfigItems } from "@/config/clone";
|
|
3
|
+
import { registerGlobalEnv } from "@/config/env";
|
|
4
|
+
import ConfigRepository, { type ConfigItems } from "@/config/repository";
|
|
5
|
+
import type {
|
|
6
|
+
ContainerContract,
|
|
7
|
+
ContainerIdentifier,
|
|
8
|
+
} from "@/container/contract";
|
|
9
|
+
import {
|
|
10
|
+
createRuntimeContainer,
|
|
11
|
+
mergeContainerRuntimeOptions,
|
|
12
|
+
type ContainerRuntimeOptions,
|
|
13
|
+
} from "@/container/runtime";
|
|
14
|
+
import type Contract from "@/renderers/contract";
|
|
15
|
+
import type { RootComponent } from "@/renderers/contract";
|
|
16
|
+
import StorageManager from "@/storage/manager";
|
|
12
17
|
import ServiceProvider, {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from "
|
|
16
|
-
import { registerGlobalStr } from "
|
|
17
|
-
import Facade from "
|
|
18
|
+
type Cleanup,
|
|
19
|
+
type ServiceProviderContext,
|
|
20
|
+
} from "@/support/service-provider";
|
|
21
|
+
import { registerGlobalStr } from "@/support/str";
|
|
22
|
+
import Facade from "@/support/facades/facade";
|
|
18
23
|
|
|
19
24
|
type StartupHandler = (context: ServiceProviderContext) => void | Cleanup;
|
|
20
25
|
type ServiceRegistrar = (context: ServiceProviderContext) => void | Cleanup;
|
|
21
26
|
|
|
27
|
+
export type ApplicationConfigureOptions = {
|
|
28
|
+
basePath?: string;
|
|
29
|
+
container?: ContainerRuntimeOptions;
|
|
30
|
+
config?: ConfigItems;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type ApplicationResolvedOptions = {
|
|
34
|
+
basePath: string;
|
|
35
|
+
container: ReturnType<typeof mergeContainerRuntimeOptions>;
|
|
36
|
+
config: ConfigItems;
|
|
37
|
+
};
|
|
38
|
+
|
|
22
39
|
registerGlobalEnv();
|
|
23
40
|
registerGlobalStr();
|
|
24
41
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
function mergeConfigureOptions(
|
|
43
|
+
options: ApplicationConfigureOptions = {},
|
|
44
|
+
): ApplicationResolvedOptions {
|
|
45
|
+
return {
|
|
46
|
+
basePath: options.basePath ?? "./",
|
|
47
|
+
container: mergeContainerRuntimeOptions(options.container),
|
|
48
|
+
config: options.config ?? {},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
28
51
|
|
|
29
52
|
export class Application {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.RootComponent = null;
|
|
49
|
-
this.renderer = null;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
protected getDefaultProviders(): ServiceProvider[] {
|
|
53
|
-
return [];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
protected static getCachedConfigItems(basePath: string): ConfigItems {
|
|
57
|
-
const cacheKey = __localAdapterTesting.normalizeBasePath(basePath) || ".";
|
|
58
|
-
|
|
59
|
-
if (!Application.configCache.has(cacheKey)) {
|
|
60
|
-
const loaded = {
|
|
61
|
-
app: appConfig,
|
|
62
|
-
...Application.fileSystem.loadConfigItems(basePath),
|
|
63
|
-
};
|
|
64
|
-
Application.configCache.set(cacheKey, loaded);
|
|
53
|
+
protected static container: ContainerContract | null = null;
|
|
54
|
+
|
|
55
|
+
protected providers: ServiceProvider[];
|
|
56
|
+
protected serviceRegistrars: ServiceRegistrar[];
|
|
57
|
+
protected startupHandlers: StartupHandler[];
|
|
58
|
+
protected rootElementId: string;
|
|
59
|
+
protected RootComponent: RootComponent | null;
|
|
60
|
+
protected renderer: Contract | null;
|
|
61
|
+
protected options: ApplicationResolvedOptions;
|
|
62
|
+
|
|
63
|
+
constructor(options: ApplicationResolvedOptions) {
|
|
64
|
+
this.options = options;
|
|
65
|
+
this.providers = this.getDefaultProviders();
|
|
66
|
+
this.serviceRegistrars = [];
|
|
67
|
+
this.startupHandlers = [];
|
|
68
|
+
this.rootElementId = "root";
|
|
69
|
+
this.RootComponent = null;
|
|
70
|
+
this.renderer = null;
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
static clearConfigCache(basePath?: string): void {
|
|
72
|
-
if (typeof basePath === "string") {
|
|
73
|
-
const cacheKey = __localAdapterTesting.normalizeBasePath(basePath) || ".";
|
|
74
|
-
Application.configCache.delete(cacheKey);
|
|
75
|
-
return;
|
|
73
|
+
protected getDefaultProviders(): ServiceProvider[] {
|
|
74
|
+
return [];
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
protected getConfigItems(): ConfigItems {
|
|
78
|
+
// Give each application instance its own mutable repository data.
|
|
79
|
+
return cloneConfigItems(this.options.config);
|
|
80
|
+
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
static clearConfigCache(_basePath?: string): void {}
|
|
83
|
+
|
|
84
|
+
static configure(basePath?: string): Application;
|
|
85
|
+
static configure(options?: ApplicationConfigureOptions): Application;
|
|
86
|
+
static configure(
|
|
87
|
+
basePathOrOptions: string | ApplicationConfigureOptions = "./",
|
|
88
|
+
) {
|
|
89
|
+
if (typeof basePathOrOptions === "string") {
|
|
90
|
+
return new Application(
|
|
91
|
+
mergeConfigureOptions({ basePath: basePathOrOptions }),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
84
94
|
|
|
85
|
-
|
|
86
|
-
if (!Application.container) {
|
|
87
|
-
throw new Error("Application container is not available. Call run() first.");
|
|
95
|
+
return new Application(mergeConfigureOptions(basePathOrOptions));
|
|
88
96
|
}
|
|
89
97
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return this;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
withServices(registerServices: ServiceRegistrar) {
|
|
99
|
-
this.serviceRegistrars.push(registerServices);
|
|
100
|
-
return this;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
withStartup(startupHandler: StartupHandler) {
|
|
104
|
-
this.startupHandlers.push(startupHandler);
|
|
105
|
-
return this;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
withRoot(RootComponent: RootComponent, options: { rootElementId?: string } = {}) {
|
|
109
|
-
this.RootComponent = RootComponent;
|
|
110
|
-
this.rootElementId = options.rootElementId ?? this.rootElementId;
|
|
111
|
-
return this;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
withRenderer(renderer: RendererAdapter) {
|
|
115
|
-
this.renderer = renderer;
|
|
116
|
-
return this;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
run() {
|
|
120
|
-
const container = new Container({ defaultScope: "Singleton" });
|
|
121
|
-
Application.container = container;
|
|
122
|
-
Facade.clearResolvedInstances();
|
|
123
|
-
const context = { container };
|
|
124
|
-
const cleanupTasks: Cleanup[] = [];
|
|
125
|
-
const configRepository = new ConfigRepository(
|
|
126
|
-
Application.getCachedConfigItems(this.basePath),
|
|
127
|
-
);
|
|
128
|
-
const storageManager = StorageManager.fromConfig(configRepository);
|
|
129
|
-
const cacheManager = CacheManager.fromConfig(configRepository);
|
|
130
|
-
|
|
131
|
-
container.bind("config").toConstantValue(configRepository);
|
|
132
|
-
container.bind(ConfigRepository).toConstantValue(configRepository);
|
|
133
|
-
container.bind("storage").toConstantValue(storageManager);
|
|
134
|
-
container.bind(StorageManager).toConstantValue(storageManager);
|
|
135
|
-
container.bind("cache").toConstantValue(cacheManager);
|
|
136
|
-
container.bind(CacheManager).toConstantValue(cacheManager);
|
|
137
|
-
|
|
138
|
-
for (const provider of this.providers) {
|
|
139
|
-
if (typeof provider.register === "function") {
|
|
140
|
-
const cleanup = provider.register(context);
|
|
141
|
-
if (typeof cleanup === "function") {
|
|
142
|
-
cleanupTasks.push(cleanup);
|
|
98
|
+
static make<T>(identifier: ContainerIdentifier<T>): T {
|
|
99
|
+
if (!Application.container) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
"Application container is not available. Call run() first.",
|
|
102
|
+
);
|
|
143
103
|
}
|
|
144
|
-
|
|
104
|
+
|
|
105
|
+
return Application.container.make<T>(identifier);
|
|
145
106
|
}
|
|
146
107
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
cleanupTasks.push(cleanup);
|
|
151
|
-
}
|
|
108
|
+
withProviders(providers: ServiceProvider[]) {
|
|
109
|
+
this.providers.push(...providers);
|
|
110
|
+
return this;
|
|
152
111
|
}
|
|
153
112
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (typeof cleanup === "function") {
|
|
158
|
-
cleanupTasks.push(cleanup);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
113
|
+
withServices(registerServices: ServiceRegistrar) {
|
|
114
|
+
this.serviceRegistrars.push(registerServices);
|
|
115
|
+
return this;
|
|
161
116
|
}
|
|
162
117
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
cleanupTasks.push(cleanup);
|
|
167
|
-
}
|
|
118
|
+
withStartup(startupHandler: StartupHandler) {
|
|
119
|
+
this.startupHandlers.push(startupHandler);
|
|
120
|
+
return this;
|
|
168
121
|
}
|
|
169
122
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
RootComponent: this.RootComponent,
|
|
178
|
-
rootElementId: this.rootElementId,
|
|
179
|
-
}) ?? rendererCleanup;
|
|
180
|
-
} else if (this.RootComponent) {
|
|
181
|
-
rendererCleanup = new ReactRenderer().render({
|
|
182
|
-
...context,
|
|
183
|
-
RootComponent: this.RootComponent,
|
|
184
|
-
rootElementId: this.rootElementId,
|
|
185
|
-
});
|
|
123
|
+
withRoot(
|
|
124
|
+
RootComponent: RootComponent,
|
|
125
|
+
options: { rootElementId?: string } = {},
|
|
126
|
+
) {
|
|
127
|
+
this.RootComponent = RootComponent;
|
|
128
|
+
this.rootElementId = options.rootElementId ?? this.rootElementId;
|
|
129
|
+
return this;
|
|
186
130
|
}
|
|
187
131
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
Facade.clearResolvedInstances();
|
|
194
|
-
container.unbindAll();
|
|
195
|
-
if (Application.container === container) {
|
|
196
|
-
Application.container = null;
|
|
197
|
-
}
|
|
198
|
-
};
|
|
132
|
+
withRenderer(renderer: Contract) {
|
|
133
|
+
this.renderer = renderer;
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
199
136
|
|
|
200
|
-
|
|
137
|
+
protected createContainer(): ContainerContract {
|
|
138
|
+
return createRuntimeContainer(this.options.container);
|
|
139
|
+
}
|
|
201
140
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
141
|
+
run() {
|
|
142
|
+
const container = this.createContainer();
|
|
143
|
+
|
|
144
|
+
Application.container = container;
|
|
145
|
+
|
|
146
|
+
Facade.clearResolvedInstances();
|
|
147
|
+
|
|
148
|
+
const context = { container };
|
|
149
|
+
const cleanupTasks: Cleanup[] = [];
|
|
150
|
+
const configRepository = new ConfigRepository(this.getConfigItems());
|
|
151
|
+
const storageManager = StorageManager.fromConfig(configRepository);
|
|
152
|
+
const cacheManager = CacheManager.fromConfig(configRepository);
|
|
153
|
+
|
|
154
|
+
container.instance("config", configRepository);
|
|
155
|
+
container.instance(ConfigRepository, configRepository);
|
|
156
|
+
container.instance("storage", storageManager);
|
|
157
|
+
container.instance(StorageManager, storageManager);
|
|
158
|
+
container.instance("cache", cacheManager);
|
|
159
|
+
container.instance(CacheManager, cacheManager);
|
|
160
|
+
|
|
161
|
+
for (const provider of this.providers) {
|
|
162
|
+
if (typeof provider.register === "function") {
|
|
163
|
+
const cleanup = provider.register(context);
|
|
164
|
+
if (typeof cleanup === "function") {
|
|
165
|
+
cleanupTasks.push(cleanup);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (const registerServices of this.serviceRegistrars) {
|
|
171
|
+
const cleanup = registerServices(context);
|
|
172
|
+
if (typeof cleanup === "function") {
|
|
173
|
+
cleanupTasks.push(cleanup);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
for (const provider of this.providers) {
|
|
178
|
+
if (typeof provider.boot === "function") {
|
|
179
|
+
const cleanup = provider.boot(context);
|
|
180
|
+
if (typeof cleanup === "function") {
|
|
181
|
+
cleanupTasks.push(cleanup);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
for (const startupHandler of this.startupHandlers) {
|
|
187
|
+
const cleanup = startupHandler(context);
|
|
188
|
+
if (typeof cleanup === "function") {
|
|
189
|
+
cleanupTasks.push(cleanup);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
let rendererCleanup: Cleanup = () => {};
|
|
194
|
+
|
|
195
|
+
if (this.renderer) {
|
|
196
|
+
if (!this.RootComponent) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
"Root component is required when using a custom renderer.",
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
rendererCleanup =
|
|
203
|
+
this.renderer.render({
|
|
204
|
+
...context,
|
|
205
|
+
RootComponent: this.RootComponent,
|
|
206
|
+
rootElementId: this.rootElementId,
|
|
207
|
+
}) ?? rendererCleanup;
|
|
208
|
+
} else if (this.RootComponent) {
|
|
209
|
+
throw new Error(
|
|
210
|
+
"Renderer is required when root component is set. Install a renderer feature (react/solid/svelte/vue) and call withRenderer(...).",
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const stop: Cleanup = () => {
|
|
215
|
+
rendererCleanup();
|
|
216
|
+
|
|
217
|
+
for (const cleanup of cleanupTasks.reverse()) {
|
|
218
|
+
cleanup();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
Facade.clearResolvedInstances();
|
|
222
|
+
|
|
223
|
+
container.flush();
|
|
224
|
+
|
|
225
|
+
if (Application.container === container) {
|
|
226
|
+
Application.container = null;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
window.addEventListener("beforeunload", stop, { once: true });
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
container,
|
|
234
|
+
stop,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
207
237
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mergeContainerRuntimeOptions,
|
|
3
|
+
packageJsonHasDependency,
|
|
4
|
+
readContainerFactoryRegistry,
|
|
5
|
+
readPackageJsonCandidates,
|
|
6
|
+
type ContainerRuntimeOptions,
|
|
7
|
+
} from "@/container/runtime";
|
|
8
|
+
import type { ConfigItems } from "@/config/repository";
|
|
9
|
+
import { localAdapterTestingHelpers } from "@/filesystem/adapters/local_test.helpers";
|
|
10
|
+
|
|
11
|
+
type ApplicationConfigureOptions = {
|
|
12
|
+
basePath?: string;
|
|
13
|
+
container?: ContainerRuntimeOptions;
|
|
14
|
+
config?: ConfigItems;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function mergeConfigureOptions(options: ApplicationConfigureOptions = {}) {
|
|
18
|
+
return {
|
|
19
|
+
basePath: options.basePath ?? "./",
|
|
20
|
+
container: mergeContainerRuntimeOptions(options.container),
|
|
21
|
+
config: options.config ?? {},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const applicationTestingHelpers = {
|
|
26
|
+
...localAdapterTestingHelpers,
|
|
27
|
+
mergeConfigureOptions,
|
|
28
|
+
readPackageJsonCandidates,
|
|
29
|
+
packageJsonHasDependency,
|
|
30
|
+
readContainerFactoryRegistry,
|
|
31
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
/// <reference path="./config/env.global.d.ts" />
|
|
2
2
|
|
|
3
3
|
export { Application } from "./foundation/application";
|
|
4
|
+
export type { ApplicationConfigureOptions } from "./foundation/application";
|
|
5
|
+
export { default as BuiltinContainer } from "./container/adapters/builtin";
|
|
6
|
+
export { inject as injectDependency } from "./container/adapters/builtin";
|
|
7
|
+
export type {
|
|
8
|
+
ContainerContract,
|
|
9
|
+
ContainerIdentifier,
|
|
10
|
+
ContainerFactory,
|
|
11
|
+
ContainerClass,
|
|
12
|
+
ContainerConcrete,
|
|
13
|
+
} from "./container/contract";
|
|
4
14
|
export { default as ServiceProvider } from "./support/service-provider";
|
|
5
15
|
export { DeferrableServiceProvider } from "./support/service-provider";
|
|
6
16
|
export type { Cleanup, ServiceProviderContext } from "./support/service-provider";
|
|
7
|
-
export { default as ConfigServiceProvider } from "./support/providers/config-service-provider";
|
|
8
17
|
|
|
9
|
-
export { ApplicationProvider, useService } from "./runtimes/react";
|
|
10
18
|
export type {
|
|
11
|
-
|
|
19
|
+
default as Contract,
|
|
12
20
|
RendererContext,
|
|
13
21
|
RootComponent,
|
|
14
|
-
} from "./
|
|
15
|
-
export { default as ReactRenderer } from "./rendering/adapters/react";
|
|
22
|
+
} from "./renderers/contract";
|
|
16
23
|
export { default as ConfigRepository } from "./config/repository";
|
|
17
24
|
export { env } from "./config/env";
|
|
18
25
|
export { default as Str } from "./support/str";
|
|
@@ -25,9 +32,11 @@ export { default as Cache } from "./support/facades/cache";
|
|
|
25
32
|
export { default as StorageManager } from "./storage/manager";
|
|
26
33
|
export { default as StorageFacade } from "./support/facades/storage";
|
|
27
34
|
export { default as Storage } from "./support/facades/storage";
|
|
28
|
-
export type { StorageAdapter } from "./storage/
|
|
35
|
+
export type { Adapter as StorageAdapter } from "./storage/adapters/contract";
|
|
29
36
|
export { default as MemoryStorageAdapter } from "./storage/adapters/memory";
|
|
30
37
|
export { default as LocalStorageAdapter } from "./storage/adapters/local-storage";
|
|
31
38
|
export { default as IndexedDbAdapter } from "./storage/adapters/indexed-db";
|
|
32
39
|
export { FileSystem } from "./filesystem/filesystem";
|
|
33
40
|
export { default as LocalAdapter } from "./filesystem/adapters/local";
|
|
41
|
+
export { default as SvelteRenderer } from "./renderers/adapters/svelte";
|
|
42
|
+
export { default as VueRenderer } from "./renderers/adapters/vue";
|
package/src/react.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import ReactDOM from "react-dom/client";
|
|
2
|
+
import { createElement } from "react";
|
|
3
|
+
import type { ReactElement } from "react";
|
|
4
|
+
import { ApplicationProvider } from "../../runtimes/react";
|
|
5
|
+
import type Contract from "../contract";
|
|
6
|
+
import type { RendererContext } from "../contract";
|
|
7
|
+
import type { Cleanup } from "../../support/service-provider";
|
|
8
|
+
|
|
9
|
+
type ReactRootComponent = () => ReactElement | null;
|
|
10
|
+
|
|
11
|
+
export default class ReactRenderer implements Contract {
|
|
12
|
+
constructor() {}
|
|
13
|
+
|
|
14
|
+
render({
|
|
15
|
+
RootComponent,
|
|
16
|
+
container,
|
|
17
|
+
rootElementId,
|
|
18
|
+
}: RendererContext): Cleanup {
|
|
19
|
+
const mountNode = document.getElementById(rootElementId);
|
|
20
|
+
if (!mountNode) {
|
|
21
|
+
throw new Error(`Missing mount node #${rootElementId}.`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const root = ReactDOM.createRoot(mountNode);
|
|
25
|
+
root.render(
|
|
26
|
+
createElement(
|
|
27
|
+
ApplicationProvider,
|
|
28
|
+
{ container },
|
|
29
|
+
createElement(RootComponent as ReactRootComponent),
|
|
30
|
+
),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return () => root.unmount();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { render } from "solid-js/web";
|
|
2
|
+
import { createComponent, type JSX } from "solid-js";
|
|
3
|
+
import type { Cleanup } from "../../support/service-provider";
|
|
4
|
+
import { ApplicationProvider } from "../../runtimes/solid";
|
|
5
|
+
import type Contract from "../contract";
|
|
6
|
+
import type { RendererContext } from "../contract";
|
|
7
|
+
|
|
8
|
+
type SolidRootComponent = () => JSX.Element;
|
|
9
|
+
|
|
10
|
+
export default class SolidRenderer implements Contract {
|
|
11
|
+
constructor() {}
|
|
12
|
+
|
|
13
|
+
render({
|
|
14
|
+
RootComponent,
|
|
15
|
+
container,
|
|
16
|
+
rootElementId,
|
|
17
|
+
}: RendererContext): Cleanup {
|
|
18
|
+
const mountNode = document.getElementById(rootElementId);
|
|
19
|
+
if (!mountNode) {
|
|
20
|
+
throw new Error(`Missing mount node #${rootElementId}.`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return render(
|
|
24
|
+
() =>
|
|
25
|
+
createComponent(ApplicationProvider, {
|
|
26
|
+
container,
|
|
27
|
+
children: () => (RootComponent as SolidRootComponent)(),
|
|
28
|
+
}),
|
|
29
|
+
mountNode,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Cleanup } from "../../support/service-provider";
|
|
2
|
+
import type Contract from "../contract";
|
|
3
|
+
import type { RendererContext } from "../contract";
|
|
4
|
+
|
|
5
|
+
type SvelteComponentInstance = {
|
|
6
|
+
$destroy?: () => void;
|
|
7
|
+
destroy?: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type SvelteComponentConstructor = new (options: {
|
|
11
|
+
target: Element;
|
|
12
|
+
props?: Record<string, unknown>;
|
|
13
|
+
}) => SvelteComponentInstance;
|
|
14
|
+
|
|
15
|
+
export default class SvelteRenderer implements Contract {
|
|
16
|
+
constructor() {}
|
|
17
|
+
|
|
18
|
+
render({
|
|
19
|
+
RootComponent,
|
|
20
|
+
container,
|
|
21
|
+
rootElementId,
|
|
22
|
+
}: RendererContext): Cleanup {
|
|
23
|
+
const mountNode = document.getElementById(rootElementId);
|
|
24
|
+
if (!mountNode) {
|
|
25
|
+
throw new Error(`Missing mount node #${rootElementId}.`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const Component = RootComponent as SvelteComponentConstructor;
|
|
29
|
+
const instance = new Component({
|
|
30
|
+
target: mountNode,
|
|
31
|
+
props: { container },
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return () => {
|
|
35
|
+
if (typeof instance.$destroy === "function") {
|
|
36
|
+
instance.$destroy();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (typeof instance.destroy === "function") {
|
|
40
|
+
instance.destroy();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createApp, type Component } from "vue";
|
|
2
|
+
import type { Cleanup } from "../../support/service-provider";
|
|
3
|
+
import { containerKey } from "../../runtimes/vue";
|
|
4
|
+
import type Contract from "../contract";
|
|
5
|
+
import type { RendererContext } from "../contract";
|
|
6
|
+
|
|
7
|
+
type VueRootComponent = Component;
|
|
8
|
+
|
|
9
|
+
export default class VueRenderer implements Contract {
|
|
10
|
+
constructor() {}
|
|
11
|
+
|
|
12
|
+
render({
|
|
13
|
+
RootComponent,
|
|
14
|
+
container,
|
|
15
|
+
rootElementId,
|
|
16
|
+
}: RendererContext): Cleanup {
|
|
17
|
+
const mountNode = document.getElementById(rootElementId);
|
|
18
|
+
if (!mountNode) {
|
|
19
|
+
throw new Error(`Missing mount node #${rootElementId}.`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const app = createApp(RootComponent as VueRootComponent);
|
|
23
|
+
app.provide(containerKey, container);
|
|
24
|
+
app.mount(mountNode);
|
|
25
|
+
|
|
26
|
+
return () => app.unmount();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Cleanup,
|
|
3
|
+
ServiceProviderContext,
|
|
4
|
+
} from "../support/service-provider";
|
|
5
|
+
|
|
6
|
+
export type RootComponent = unknown;
|
|
7
|
+
|
|
8
|
+
export type RendererContext = ServiceProviderContext & {
|
|
9
|
+
RootComponent: RootComponent;
|
|
10
|
+
rootElementId: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default interface Contract {
|
|
14
|
+
render(context: RendererContext): void | Cleanup;
|
|
15
|
+
}
|