@servlyadmin/runtime-core 0.1.45 → 0.1.46

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 CHANGED
@@ -14,10 +14,60 @@ pnpm add @servlyadmin/runtime-core
14
14
 
15
15
  ## Quick Start
16
16
 
17
+ The simplest way to render a component:
18
+
19
+ ```typescript
20
+ import { mount } from '@servlyadmin/runtime-core';
21
+
22
+ // Mount a component - that's it!
23
+ const app = await mount({
24
+ componentId: 'my-component-id',
25
+ target: '#app',
26
+ props: { title: 'Hello World' }
27
+ });
28
+
29
+ // Update props
30
+ app.update({ props: { title: 'Updated!' } });
31
+
32
+ // Cleanup
33
+ app.destroy();
34
+ ```
35
+
36
+ ### With Callbacks
37
+
38
+ ```typescript
39
+ const app = await mount({
40
+ componentId: 'my-component-id',
41
+ target: '#app',
42
+ props: { title: 'Hello' },
43
+ onReady: (result) => console.log('Mounted!', result.version),
44
+ onError: (err) => console.error('Failed:', err)
45
+ });
46
+ ```
47
+
48
+ ### With Version & Cache Control
49
+
50
+ ```typescript
51
+ const app = await mount({
52
+ componentId: 'my-component-id',
53
+ target: document.getElementById('app'),
54
+ props: { title: 'Hello' },
55
+ version: '^1.0.0',
56
+ fetchOptions: {
57
+ cacheStrategy: 'memory',
58
+ forceRefresh: true
59
+ }
60
+ });
61
+ ```
62
+
63
+ ## Low-Level API
64
+
65
+ For more control, use `fetchComponent` and `render` directly:
66
+
17
67
  ```typescript
18
68
  import { render, fetchComponent } from '@servlyadmin/runtime-core';
19
69
 
20
- // Fetch a component from the registry (uses Servly's default registry)
70
+ // Fetch a component from the registry
21
71
  const { data } = await fetchComponent('my-component-id');
22
72
 
23
73
  // Render to a container
@@ -135,6 +185,55 @@ const elements = [
135
185
 
136
186
  ## API Reference
137
187
 
188
+ ### mount(options) - Recommended
189
+
190
+ The simplest way to render a component. Handles fetching, container resolution, and rendering.
191
+
192
+ ```typescript
193
+ const app = await mount({
194
+ componentId: string, // Required: Component ID to fetch
195
+ target: string | HTMLElement, // Required: CSS selector or element
196
+ props?: Record<string, any>, // Props to pass (default: {})
197
+ state?: Record<string, any>, // Initial state (default: {})
198
+ context?: Record<string, any>, // Additional context (default: {})
199
+ version?: string, // Version specifier (default: 'latest')
200
+ eventHandlers?: Record<string, Record<string, (e: Event) => void>>,
201
+ fetchOptions?: {
202
+ cacheStrategy?: 'localStorage' | 'memory' | 'none',
203
+ forceRefresh?: boolean,
204
+ apiKey?: string,
205
+ retryConfig?: RetryConfig,
206
+ },
207
+ onReady?: (result: MountResult) => void,
208
+ onError?: (error: Error) => void,
209
+ });
210
+
211
+ // Returns MountResult
212
+ interface MountResult {
213
+ update(context: Partial<BindingContext>): void;
214
+ destroy(): void;
215
+ rootElement: HTMLElement | null;
216
+ container: HTMLElement;
217
+ data: ComponentData;
218
+ fromCache: boolean;
219
+ version: string;
220
+ }
221
+ ```
222
+
223
+ ### mountData(options)
224
+
225
+ Mount with pre-fetched data (useful for SSR or custom data sources):
226
+
227
+ ```typescript
228
+ import { mountData } from '@servlyadmin/runtime-core';
229
+
230
+ const app = mountData({
231
+ data: myComponentData, // Pre-fetched ComponentData
232
+ target: '#app',
233
+ props: { title: 'Hello' }
234
+ });
235
+ ```
236
+
138
237
  ### render(options)
139
238
 
140
239
  Renders elements to a container.
package/dist/index.cjs CHANGED
@@ -773,6 +773,8 @@ __export(index_exports, {
773
773
  loadFont: () => loadFont,
774
774
  loadFonts: () => loadFonts,
775
775
  markElementReady: () => markElementReady,
776
+ mount: () => mount,
777
+ mountData: () => mountData,
776
778
  navigateTo: () => navigateTo,
777
779
  parseVersion: () => parseVersion,
778
780
  prefetchComponents: () => prefetchComponents,
@@ -5282,6 +5284,109 @@ async function getDependencyTree(id, options = {}) {
5282
5284
  return data.data;
5283
5285
  }
5284
5286
 
5287
+ // src/mount.ts
5288
+ async function mount(options) {
5289
+ const {
5290
+ componentId,
5291
+ target,
5292
+ props = {},
5293
+ state = {},
5294
+ context = {},
5295
+ version = "latest",
5296
+ eventHandlers,
5297
+ fetchOptions = {},
5298
+ onReady,
5299
+ onError
5300
+ } = options;
5301
+ try {
5302
+ const container = typeof target === "string" ? document.querySelector(target) : target;
5303
+ if (!container) {
5304
+ throw new Error(`Target container not found: ${target}`);
5305
+ }
5306
+ const fetchResult = await fetchComponentWithDependencies(componentId, {
5307
+ ...fetchOptions,
5308
+ version
5309
+ });
5310
+ const { data, fromCache, version: resolvedVersion, registry, views } = fetchResult;
5311
+ const bindingContext = {
5312
+ props,
5313
+ state,
5314
+ context
5315
+ };
5316
+ const renderResult = render({
5317
+ container,
5318
+ elements: data.layout,
5319
+ context: bindingContext,
5320
+ eventHandlers,
5321
+ componentRegistry: registry,
5322
+ views
5323
+ });
5324
+ const result = {
5325
+ update: (newContext) => {
5326
+ renderResult.update({
5327
+ props: newContext.props ?? props,
5328
+ state: newContext.state ?? state,
5329
+ context: newContext.context ?? context
5330
+ });
5331
+ },
5332
+ destroy: () => {
5333
+ renderResult.destroy();
5334
+ },
5335
+ rootElement: renderResult.rootElement,
5336
+ container,
5337
+ data,
5338
+ fromCache,
5339
+ version: resolvedVersion
5340
+ };
5341
+ onReady?.(result);
5342
+ return result;
5343
+ } catch (error) {
5344
+ const err = error instanceof Error ? error : new Error(String(error));
5345
+ onError?.(err);
5346
+ throw err;
5347
+ }
5348
+ }
5349
+ function mountData(options) {
5350
+ const {
5351
+ data,
5352
+ target,
5353
+ props = {},
5354
+ state = {},
5355
+ context = {},
5356
+ eventHandlers
5357
+ } = options;
5358
+ const container = typeof target === "string" ? document.querySelector(target) : target;
5359
+ if (!container) {
5360
+ throw new Error(`Target container not found: ${target}`);
5361
+ }
5362
+ const bindingContext = {
5363
+ props,
5364
+ state,
5365
+ context
5366
+ };
5367
+ const renderResult = render({
5368
+ container,
5369
+ elements: data.layout,
5370
+ context: bindingContext,
5371
+ eventHandlers
5372
+ });
5373
+ return {
5374
+ update: (newContext) => {
5375
+ renderResult.update({
5376
+ props: newContext.props ?? props,
5377
+ state: newContext.state ?? state,
5378
+ context: newContext.context ?? context
5379
+ });
5380
+ },
5381
+ destroy: () => {
5382
+ renderResult.destroy();
5383
+ },
5384
+ rootElement: renderResult.rootElement,
5385
+ container,
5386
+ data
5387
+ };
5388
+ }
5389
+
5285
5390
  // src/version.ts
5286
5391
  function parseVersion(version) {
5287
5392
  const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
@@ -5754,6 +5859,8 @@ init_tailwind();
5754
5859
  loadFont,
5755
5860
  loadFonts,
5756
5861
  markElementReady,
5862
+ mount,
5863
+ mountData,
5757
5864
  navigateTo,
5758
5865
  parseVersion,
5759
5866
  prefetchComponents,
package/dist/index.js CHANGED
@@ -4479,6 +4479,109 @@ async function getDependencyTree(id, options = {}) {
4479
4479
  return data.data;
4480
4480
  }
4481
4481
 
4482
+ // src/mount.ts
4483
+ async function mount(options) {
4484
+ const {
4485
+ componentId,
4486
+ target,
4487
+ props = {},
4488
+ state = {},
4489
+ context = {},
4490
+ version = "latest",
4491
+ eventHandlers,
4492
+ fetchOptions = {},
4493
+ onReady,
4494
+ onError
4495
+ } = options;
4496
+ try {
4497
+ const container = typeof target === "string" ? document.querySelector(target) : target;
4498
+ if (!container) {
4499
+ throw new Error(`Target container not found: ${target}`);
4500
+ }
4501
+ const fetchResult = await fetchComponentWithDependencies(componentId, {
4502
+ ...fetchOptions,
4503
+ version
4504
+ });
4505
+ const { data, fromCache, version: resolvedVersion, registry, views } = fetchResult;
4506
+ const bindingContext = {
4507
+ props,
4508
+ state,
4509
+ context
4510
+ };
4511
+ const renderResult = render({
4512
+ container,
4513
+ elements: data.layout,
4514
+ context: bindingContext,
4515
+ eventHandlers,
4516
+ componentRegistry: registry,
4517
+ views
4518
+ });
4519
+ const result = {
4520
+ update: (newContext) => {
4521
+ renderResult.update({
4522
+ props: newContext.props ?? props,
4523
+ state: newContext.state ?? state,
4524
+ context: newContext.context ?? context
4525
+ });
4526
+ },
4527
+ destroy: () => {
4528
+ renderResult.destroy();
4529
+ },
4530
+ rootElement: renderResult.rootElement,
4531
+ container,
4532
+ data,
4533
+ fromCache,
4534
+ version: resolvedVersion
4535
+ };
4536
+ onReady?.(result);
4537
+ return result;
4538
+ } catch (error) {
4539
+ const err = error instanceof Error ? error : new Error(String(error));
4540
+ onError?.(err);
4541
+ throw err;
4542
+ }
4543
+ }
4544
+ function mountData(options) {
4545
+ const {
4546
+ data,
4547
+ target,
4548
+ props = {},
4549
+ state = {},
4550
+ context = {},
4551
+ eventHandlers
4552
+ } = options;
4553
+ const container = typeof target === "string" ? document.querySelector(target) : target;
4554
+ if (!container) {
4555
+ throw new Error(`Target container not found: ${target}`);
4556
+ }
4557
+ const bindingContext = {
4558
+ props,
4559
+ state,
4560
+ context
4561
+ };
4562
+ const renderResult = render({
4563
+ container,
4564
+ elements: data.layout,
4565
+ context: bindingContext,
4566
+ eventHandlers
4567
+ });
4568
+ return {
4569
+ update: (newContext) => {
4570
+ renderResult.update({
4571
+ props: newContext.props ?? props,
4572
+ state: newContext.state ?? state,
4573
+ context: newContext.context ?? context
4574
+ });
4575
+ },
4576
+ destroy: () => {
4577
+ renderResult.destroy();
4578
+ },
4579
+ rootElement: renderResult.rootElement,
4580
+ container,
4581
+ data
4582
+ };
4583
+ }
4584
+
4482
4585
  // src/version.ts
4483
4586
  function parseVersion(version) {
4484
4587
  const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
@@ -4946,6 +5049,8 @@ export {
4946
5049
  loadFont,
4947
5050
  loadFonts,
4948
5051
  markElementReady,
5052
+ mount,
5053
+ mountData,
4949
5054
  navigateTo,
4950
5055
  parseVersion,
4951
5056
  prefetchComponents,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servlyadmin/runtime-core",
3
- "version": "0.1.45",
3
+ "version": "0.1.46",
4
4
  "description": "Framework-agnostic core renderer for Servly components",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -40,4 +40,4 @@
40
40
  "vitest": "^1.0.0",
41
41
  "fast-check": "^3.15.0"
42
42
  }
43
- }
43
+ }