@stonecrop/nuxt 0.10.4 → 0.10.6

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
@@ -102,20 +102,26 @@ The module picks up this file and, if `pageComponent` is configured, registers a
102
102
 
103
103
  ### Wire Up Your Data Client
104
104
 
105
- After installing the module, add a client-side plugin to connect your data transport. The `useStonecropRegistry()` composable gives you a stable API for this no need to reach into `globalProperties` directly:
105
+ After installing the module, add a client-side plugin to connect your data transport. Use `useStonecropSetup()` in plugins it's designed for the initialization context where Stonecrop may not be fully ready yet:
106
106
 
107
107
  ```typescript
108
108
  // app/plugins/stonecrop.client.ts
109
109
  import { StonecropClient } from '@stonecrop/graphql-client'
110
110
 
111
111
  export default defineNuxtPlugin(() => {
112
+ const { registerClient, registerMeta } = useStonecropSetup()
113
+
112
114
  const client = new StonecropClient({ endpoint: '/graphql' })
113
- const { setMeta, setFetchRecord, setFetchRecords } = useStonecropRegistry()
114
115
 
115
- // Map the route path/segments to a doctype name, then delegate to your client
116
- setMeta(({ segments }) => client.getMeta({ doctype: segments[0] }))
117
- setFetchRecord((doctype, id) => client.getRecord(doctype, id))
118
- setFetchRecords((doctype) => client.getRecords(doctype))
116
+ // Register the data client for record fetching
117
+ registerClient(client)
118
+
119
+ // Configure metadata fetching for lazy-loaded doctypes
120
+ // Called by useStonecrop() when it needs doctype metadata
121
+ registerMeta(({ segments }) => {
122
+ const doctype = segments[0] // e.g., "task" from /task/123
123
+ return client.getMeta({ doctype })
124
+ })
119
125
  })
120
126
  ```
121
127
 
@@ -321,48 +327,87 @@ The module auto-registers:
321
327
  - **Self-Documenting**: Schemas serve as data model documentation
322
328
  - **Easy Updates**: Change schema, UI updates automatically
323
329
 
324
- ## `useStonecropRegistry()` — Configuring the Framework After Install
325
-
326
- The `@stonecrop/nuxt` runtime plugin installs `StonecropPlugin` with a router but no data transport, because data clients (GraphQL, tRPC, REST) are application-defined and cannot be serialised through `nuxt.config.ts` module options.
330
+ ## `useStonecropSetup()` — Configuring the Framework in Plugins
327
331
 
328
- `useStonecropRegistry()` is the documented extension point for wiring your data transport after plugin install. Call it in a client-side plugin:
332
+ When you need to configure Stonecrop during Nuxt plugin initialization (before components mount), use `useStonecropSetup()`. This composable is designed specifically for the plugin context and returns values that may be `undefined` if Stonecrop hasn't finished initializing.
329
333
 
330
334
  ```typescript
331
335
  // app/plugins/stonecrop.client.ts
336
+ import { StonecropClient } from '@stonecrop/graphql-client'
337
+
332
338
  export default defineNuxtPlugin(() => {
333
- const { setMeta, setFetchRecord, setFetchRecords } = useStonecropRegistry()
339
+ const { isReady, registerClient, registerMeta, registerDoctype } = useStonecropSetup()
334
340
 
335
- // setMeta resolves doctype metadata from the current route
336
- // The context has { path, segments } from the router; adapt to your API.
337
- setMeta(async ({ segments }) => {
338
- // Example: segments[0] is the doctype slug, e.g. "task" from /task/123
339
- const doctype = segments[0]
340
- const meta = await $fetch(`/api/doctypes/${doctype}`)
341
- return meta
342
- })
341
+ // Check if Stonecrop is ready (module plugins run before project plugins)
342
+ if (!isReady) {
343
+ console.warn('Stonecrop not ready - ensure @stonecrop/nuxt module is installed')
344
+ return
345
+ }
343
346
 
344
- // setFetchRecord replaces the default REST stub in useStonecrop({ recordId })
345
- setFetchRecord(async (doctype, id) => {
346
- return await $fetch(`/api/${doctype.slug}/${id}`)
347
- })
347
+ const client = new StonecropClient({ endpoint: '/graphql' })
348
+
349
+ // Register the data client
350
+ registerClient(client)
348
351
 
349
- // setFetchRecords replaces the default REST stub for list loading
350
- setFetchRecords(async (doctype) => {
351
- return await $fetch(`/api/${doctype.slug}`)
352
+ // Configure metadata fetching for lazy-loaded doctypes
353
+ registerMeta(({ segments }) => {
354
+ const doctype = segments[0]
355
+ return client.getMeta({ doctype })
352
356
  })
357
+
358
+ // Optionally pre-load doctypes into the Registry
359
+ const planDoctype = Doctype.fromObject({ name: 'plan', fields: [...] })
360
+ registerDoctype(planDoctype)
353
361
  })
354
362
  ```
355
363
 
356
- **Why a composable and not module options?** Nuxt module options are serialised at build time — functions cannot be passed through `nuxt.config.ts`. `useStonecropRegistry()` is the composable equivalent of `usePinia()` or `useNuxtApp()`: a stable, typed API for configuring the framework singleton after it has been installed.
364
+ ### `useStonecropSetup()` vs `useStonecropRegistry()`
365
+
366
+ | Context | Use | Behavior |
367
+ |---------|-----|----------|
368
+ | **Plugin/initialization** | `useStonecropSetup()` | Returns values that may be `undefined`; provides `isReady` check |
369
+ | **Component/runtime** | `useStonecropRegistry()` | Throws if Stonecrop isn't initialized (expected to be ready) |
370
+
371
+ ### `useStonecropSetup()` API
372
+
373
+ | Property/Method | Type | Description |
374
+ |-----------------|------|-------------|
375
+ | `registry` | `Registry \| undefined` | The Registry instance (undefined if not ready) |
376
+ | `stonecrop` | `Stonecrop \| undefined` | The Stonecrop instance (undefined if not ready) |
377
+ | `isReady` | `boolean` | `true` when both registry and stonecrop are available |
378
+ | `registerClient(client)` | `(client: DataClient) => void` | Set the data client for record fetching. Throws if stonecrop not available. |
379
+ | `getClient()` | `() => DataClient \| undefined` | Get the currently configured client. |
380
+ | `registerMeta(fn)` | `(fn: (ctx) => Doctype) => void` | Set the `getMeta` function on the Registry. Throws if registry not available. |
381
+ | `registerDoctype(doctype)` | `(doctype: Doctype) => void` | Pre-load a doctype into the Registry. Throws if registry not available. |
382
+ | `dispatchAction(...)` | `Promise<{ success, data, error }>` | Dispatch an action via the configured client. |
383
+
384
+ ## `useStonecropRegistry()` — Using the Framework in Components
385
+
386
+ `useStonecropRegistry()` is for component/runtime context where the framework is expected to be fully initialized. Use it in components to access the configured registry and stonecrop instances.
387
+
388
+ ```typescript
389
+ // In a component or composable
390
+ const { registry, stonecrop, dispatchAction } = useStonecropRegistry()
391
+
392
+ // Access doctype metadata
393
+ const plan = registry.getDoctype('plan')
394
+
395
+ // Dispatch actions
396
+ await dispatchAction({ name: 'plan' }, 'SUBMIT', [recordId])
397
+ ```
398
+
399
+ **Note**: If called before Stonecrop is initialized (e.g., in a plugin), this throws with guidance to use `useStonecropSetup()` instead.
357
400
 
358
- ### API
401
+ ### `useStonecropRegistry()` API
359
402
 
360
- | Method | Signature | Description |
361
- |--------|-----------|-------------|
362
- | `setMeta` | `(fn: (ctx) => DoctypeMeta \| Promise<DoctypeMeta>) => void` | Sets the `getMeta` function on the Registry. Called by `useStonecrop()` to lazy-load doctype metadata for the current route. `ctx` = `{ path, segments }`. |
363
- | `setFetchRecord` | `(fn: (doctype, id) => Promise<Record \| null>) => void` | Replaces the default REST fetch stub in `Stonecrop.getRecord()`. Enables GraphQL-backed or any other custom transport. |
364
- | `setFetchRecords` | `(fn: (doctype) => Promise<Record[]>) => void` | Replaces the default REST fetch stub in `Stonecrop.getRecords()`. |
365
- | `registry` | `Registry` | The raw Registry instance, for advanced use cases. |
403
+ | Property/Method | Type | Description |
404
+ |-----------------|------|-------------|
405
+ | `registry` | `Registry` | The Registry instance for doctype management. |
406
+ | `stonecrop` | `Stonecrop` | The Stonecrop instance for HST and operation log access. Throws if not initialized. |
407
+ | `setMeta(fn)` | `(fn: (ctx) => Doctype \| Promise<Doctype>) => void` | Sets the `getMeta` function on the Registry. Called by `useStonecrop()` to lazy-load doctype metadata for the current route. `ctx` = `{ path, segments }`. |
408
+ | `setClient(client)` | `(client: DataClient) => void` | Set the data client for record fetching. Throws if stonecrop not available. |
409
+ | `getClient()` | `() => DataClient \| undefined` | Get the currently configured client. |
410
+ | `dispatchAction(doctype, action, args)` | `Promise<{ success, data, error }>` | Dispatch an action via the configured client. Returns error if doctype not found in registry. |
366
411
 
367
412
  ## Advanced Features
368
413
 
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stonecrop/nuxt",
3
3
  "configKey": "stonecrop",
4
- "version": "0.10.4",
4
+ "version": "0.10.6",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -1,8 +1,16 @@
1
- import type { DataClient, DoctypeMeta } from '@stonecrop/schema';
2
- import type { RouteContext } from '@stonecrop/stonecrop';
1
+ import type { DataClient } from '@stonecrop/schema';
2
+ import type { Doctype, Registry, RouteContext, Stonecrop } from '@stonecrop/stonecrop';
3
3
  /**
4
- * Provides a stable, documented API for accessing and configuring the Stonecrop
5
- * Registry instance after the `@stonecrop/nuxt` plugin has installed it.
4
+ * Provides a stable, documented API for accessing the configured Stonecrop
5
+ * Registry instance in components and composables.
6
+ *
7
+ * ## When to Use This vs useStonecropSetup()
8
+ *
9
+ * - **`useStonecropRegistry()`** - Call in components or composables to use the configured
10
+ * framework. Throws if Stonecrop isn't initialized (expected to be ready at this point).
11
+ *
12
+ * - **`useStonecropSetup()`** - Call in Nuxt plugins to configure clients, metadata functions,
13
+ * and pre-load doctypes. Returns values that may be `undefined` if Stonecrop isn't ready yet.
6
14
  *
7
15
  * ## Why This Composable Exists
8
16
  *
@@ -12,9 +20,8 @@ import type { RouteContext } from '@stonecrop/stonecrop';
12
20
  * - **@stonecrop/graphql-client**: Reference `DataClient` implementation using GraphQL
13
21
  * - **@stonecrop/nuxt**: Nuxt integration that bootstraps the Registry and Stonecrop instances
14
22
  *
15
- * This composable bridges Nuxt's plugin lifecycle with Stonecrop's registry, allowing
16
- * applications to inject their data client and configure metadata fetching after the
17
- * framework is mounted.
23
+ * This composable bridges Nuxt's plugin lifecycle with Stonecrop's registry, providing
24
+ * a clean API for components to interact with the configured framework.
18
25
  *
19
26
  * ## RouteContext vs DoctypeContext
20
27
  *
@@ -24,8 +31,8 @@ import type { RouteContext } from '@stonecrop/stonecrop';
24
31
  * - **DoctypeContext** (`{ doctype, recordId? }`): Semantic doctype context. Used by the
25
32
  * data layer to identify "what we're working with" (e.g., `{ doctype: 'Plan', recordId: '123' }`).
26
33
  *
27
- * Your `setMeta` implementation bridges these: extract doctype/recordId from the route
28
- * segments and pass `DoctypeContext` to your data client.
34
+ * Your `setMeta` implementation (configured via `useStonecropSetup()`) bridges these:
35
+ * extract doctype/recordId from the route segments and pass `DoctypeContext` to your data client.
29
36
  *
30
37
  * ## Data Flow
31
38
  *
@@ -34,49 +41,42 @@ import type { RouteContext } from '@stonecrop/stonecrop';
34
41
  * ↓
35
42
  * RouteContext ({ path: '/plan/123', segments: ['plan', '123'] })
36
43
  * ↓
37
- * getMeta (your implementation)
44
+ * getMeta (configured in plugin via useStonecropSetup)
38
45
  * ↓
39
46
  * DoctypeContext ({ doctype: 'Plan', recordId: '123' })
40
47
  * ↓
41
- * DataClient.getMeta() → DoctypeMeta
48
+ * DataClient.getMeta() → Doctype
42
49
  * ```
43
50
  *
44
51
  * @example
45
52
  * ```ts
46
- * // app/plugins/stonecrop.client.ts
47
- * import { StonecropClient } from '@stonecrop/graphql-client'
48
- *
49
- * export default defineNuxtPlugin(() => {
50
- * const client = new StonecropClient({ endpoint: '/graphql' })
51
- * const { setClient, setMeta } = useStonecropRegistry()
52
- *
53
- * // Set the data client for record fetching
54
- * setClient(client)
55
- *
56
- * // Bridge RouteContext → DoctypeContext for metadata fetching
57
- * setMeta(({ segments }) => {
58
- * const doctype = segments[0] // e.g. "plan" → doctype "Plan"
59
- * return client.getMeta({ doctype }) // client expects DoctypeContext
60
- * })
61
- * })
53
+ * // In a component or composable
54
+ * const { registry, stonecrop, dispatchAction } = useStonecropRegistry()
55
+ *
56
+ * // Access the registry
57
+ * const plan = registry.getDoctype('plan')
58
+ *
59
+ * // Dispatch an action
60
+ * await dispatchAction({ name: 'plan' }, 'SUBMIT', [recordId])
62
61
  * ```
63
62
  *
64
63
  * @public
65
64
  */
66
65
  export declare function useStonecropRegistry(): {
67
66
  /**
68
- * The raw Registry instance, for advanced use cases.
69
- * Prefer the typed setter methods below for normal configuration.
67
+ * The Registry instance for doctype management.
68
+ * Use this to access doctype metadata, resolve schemas, etc.
69
+ */
70
+ registry: Registry;
71
+ /**
72
+ * The Stonecrop instance for HST and operation log access.
70
73
  */
71
- registry: {
72
- getMeta?: (routeContext: RouteContext) => DoctypeMeta | Promise<DoctypeMeta>;
73
- };
74
+ readonly stonecrop: Stonecrop;
74
75
  /**
75
76
  * Set the data client on the Stonecrop instance.
76
77
  * Required before fetching records or dispatching actions.
77
78
  *
78
79
  * @param client - DataClient implementation (e.g., StonecropClient from \@stonecrop/graphql-client)
79
- *
80
80
  * @throws Error if Stonecrop instance is not available
81
81
  *
82
82
  * @example
@@ -95,7 +95,9 @@ export declare function useStonecropRegistry(): {
95
95
  * Dispatch an action to the server via the configured data client.
96
96
  * All state changes flow through this single mutation endpoint.
97
97
  *
98
- * @param doctype - Doctype reference (name and optional slug)
98
+ * @param doctype - Doctype reference object with `name` and optional `slug` properties
99
+ * @param doctype.name - Doctype name (e.g., 'plan')
100
+ * @param doctype.slug - Optional doctype slug if it differs from the name (e.g., 'project-plan')
99
101
  * @param action - Action name to execute (e.g., 'SUBMIT', 'APPROVE', 'save')
100
102
  * @param args - Action arguments (typically record ID and/or form data)
101
103
  * @returns Action result with success status, response data, and any error
@@ -103,10 +105,10 @@ export declare function useStonecropRegistry(): {
103
105
  * @example
104
106
  * ```ts
105
107
  * // Save a record
106
- * const result = await dispatchAction(doctype, 'save', [{ id: recordId, data: formData }])
108
+ * const result = await dispatchAction({ name: 'plan' }, 'save', [{ id: recordId, data: formData }])
107
109
  *
108
110
  * // Submit for approval
109
- * const result = await dispatchAction(doctype, 'SUBMIT', [recordId])
111
+ * const result = await dispatchAction({ name: 'plan' }, 'SUBMIT', [recordId])
110
112
  * ```
111
113
  */
112
114
  dispatchAction(doctype: {
@@ -135,7 +137,7 @@ export declare function useStonecropRegistry(): {
135
137
  * })
136
138
  * ```
137
139
  *
138
- * @param fn - Function that receives RouteContext and returns DoctypeMeta.
140
+ * @param fn - Function that receives RouteContext and returns Doctype.
139
141
  */
140
- setMeta(fn: (routeContext: RouteContext) => DoctypeMeta | Promise<DoctypeMeta>): void;
142
+ setMeta(fn: (routeContext: RouteContext) => Doctype | Promise<Doctype>): void;
141
143
  };
@@ -4,22 +4,32 @@ export function useStonecropRegistry() {
4
4
  const registry = nuxtApp.$registry;
5
5
  if (!registry) {
6
6
  throw new Error(
7
- "[useStonecropRegistry] The Stonecrop Registry is not available. Ensure @stonecrop/nuxt is installed and the plugin has run before calling this composable."
7
+ "[useStonecropRegistry] The Stonecrop Registry is not available. Ensure @stonecrop/nuxt is installed.\n\nIf you are calling this from a Nuxt plugin, use useStonecropSetup() instead, which is designed for the plugin initialization context."
8
8
  );
9
9
  }
10
10
  const stonecrop = nuxtApp.$stonecrop;
11
11
  return {
12
12
  /**
13
- * The raw Registry instance, for advanced use cases.
14
- * Prefer the typed setter methods below for normal configuration.
13
+ * The Registry instance for doctype management.
14
+ * Use this to access doctype metadata, resolve schemas, etc.
15
15
  */
16
16
  registry,
17
+ /**
18
+ * The Stonecrop instance for HST and operation log access.
19
+ */
20
+ get stonecrop() {
21
+ if (!stonecrop) {
22
+ throw new Error(
23
+ "[useStonecropRegistry] Stonecrop instance is not available. Ensure @stonecrop/nuxt is installed.\n\nIf you are calling this from a Nuxt plugin, use useStonecropSetup() instead."
24
+ );
25
+ }
26
+ return stonecrop;
27
+ },
17
28
  /**
18
29
  * Set the data client on the Stonecrop instance.
19
30
  * Required before fetching records or dispatching actions.
20
31
  *
21
32
  * @param client - DataClient implementation (e.g., StonecropClient from \@stonecrop/graphql-client)
22
- *
23
33
  * @throws Error if Stonecrop instance is not available
24
34
  *
25
35
  * @example
@@ -31,7 +41,7 @@ export function useStonecropRegistry() {
31
41
  setClient(client) {
32
42
  if (!stonecrop) {
33
43
  throw new Error(
34
- "[useStonecropRegistry] Stonecrop instance is not available. Ensure @stonecrop/nuxt is installed and the plugin has run."
44
+ "[useStonecropRegistry] Stonecrop instance is not available. Ensure @stonecrop/nuxt is installed.\n\nIf you are calling this from a Nuxt plugin, use useStonecropSetup() instead."
35
45
  );
36
46
  }
37
47
  stonecrop.setClient(client);
@@ -47,7 +57,9 @@ export function useStonecropRegistry() {
47
57
  * Dispatch an action to the server via the configured data client.
48
58
  * All state changes flow through this single mutation endpoint.
49
59
  *
50
- * @param doctype - Doctype reference (name and optional slug)
60
+ * @param doctype - Doctype reference object with `name` and optional `slug` properties
61
+ * @param doctype.name - Doctype name (e.g., 'plan')
62
+ * @param doctype.slug - Optional doctype slug if it differs from the name (e.g., 'project-plan')
51
63
  * @param action - Action name to execute (e.g., 'SUBMIT', 'APPROVE', 'save')
52
64
  * @param args - Action arguments (typically record ID and/or form data)
53
65
  * @returns Action result with success status, response data, and any error
@@ -55,21 +67,29 @@ export function useStonecropRegistry() {
55
67
  * @example
56
68
  * ```ts
57
69
  * // Save a record
58
- * const result = await dispatchAction(doctype, 'save', [{ id: recordId, data: formData }])
70
+ * const result = await dispatchAction({ name: 'plan' }, 'save', [{ id: recordId, data: formData }])
59
71
  *
60
72
  * // Submit for approval
61
- * const result = await dispatchAction(doctype, 'SUBMIT', [recordId])
73
+ * const result = await dispatchAction({ name: 'plan' }, 'SUBMIT', [recordId])
62
74
  * ```
63
75
  */
64
76
  dispatchAction(doctype, action, args) {
65
77
  if (!stonecrop) {
66
78
  return Promise.reject(
67
79
  new Error(
68
- "[useStonecropRegistry] Stonecrop instance is not available. Ensure @stonecrop/nuxt is installed and the plugin has run."
80
+ "[useStonecropRegistry] Stonecrop instance is not available. Ensure @stonecrop/nuxt is installed.\n\nIf you are calling this from a Nuxt plugin, use useStonecropSetup() instead."
69
81
  )
70
82
  );
71
83
  }
72
- return stonecrop.dispatchAction(doctype, action, args);
84
+ const meta = registry.getDoctype(doctype.slug || doctype.name.toLowerCase());
85
+ if (!meta) {
86
+ return Promise.resolve({
87
+ success: false,
88
+ data: null,
89
+ error: `Doctype '${doctype.name}' not found in registry`
90
+ });
91
+ }
92
+ return stonecrop.dispatchAction(meta, action, args);
73
93
  },
74
94
  /**
75
95
  * Set the `getMeta` function on the Registry.
@@ -89,7 +109,7 @@ export function useStonecropRegistry() {
89
109
  * })
90
110
  * ```
91
111
  *
92
- * @param fn - Function that receives RouteContext and returns DoctypeMeta.
112
+ * @param fn - Function that receives RouteContext and returns Doctype.
93
113
  */
94
114
  setMeta(fn) {
95
115
  registry.getMeta = fn;
@@ -0,0 +1,108 @@
1
+ import type { DataClient } from '@stonecrop/schema';
2
+ import type { Doctype, Registry, RouteContext, Stonecrop } from '@stonecrop/stonecrop';
3
+ /**
4
+ * Composable for Stonecrop initialization in Nuxt plugins.
5
+ *
6
+ * Use this during the plugin/initialization phase to configure the framework
7
+ * before components mount. For component/runtime usage, use `useStonecropRegistry()` instead.
8
+ *
9
+ * ## When to Use This vs useStonecropRegistry()
10
+ *
11
+ * - **`useStonecropSetup()`** - Call in Nuxt plugins to configure clients, metadata functions,
12
+ * and pre-load doctypes. Returns values that may be `undefined` if Stonecrop isn't ready yet.
13
+ *
14
+ * - **`useStonecropRegistry()`** - Call in components or composables to use the configured
15
+ * framework. Throws if Stonecrop isn't initialized (expected to be ready at this point).
16
+ *
17
+ * ## Example
18
+ *
19
+ * ```ts
20
+ * // app/plugins/stonecrop.client.ts
21
+ * import { StonecropClient } from '@stonecrop/graphql-client'
22
+ *
23
+ * export default defineNuxtPlugin(() => {
24
+ * const { registerClient, registerMeta, registerDoctype } = useStonecropSetup()
25
+ *
26
+ * const client = new StonecropClient({ endpoint: '/graphql' })
27
+ * registerClient(client)
28
+ *
29
+ * // Configure metadata fetching for lazy-loaded doctypes
30
+ * registerMeta(({ segments }) => {
31
+ * const doctype = segments[0]
32
+ * return client.getMeta({ doctype })
33
+ * })
34
+ *
35
+ * // Optionally pre-load doctypes
36
+ * const plan = Doctype.fromObject({ name: 'plan', fields: [...] })
37
+ * registerDoctype(plan)
38
+ * })
39
+ * ```
40
+ *
41
+ * @public
42
+ */
43
+ export declare function useStonecropSetup(): {
44
+ /**
45
+ * The Registry instance.
46
+ * Returns `undefined` if the @stonecrop/nuxt plugin hasn't run yet.
47
+ */
48
+ readonly registry: Registry | undefined;
49
+ /**
50
+ * The Stonecrop instance.
51
+ * Returns `undefined` if the @stonecrop/nuxt plugin hasn't run yet.
52
+ */
53
+ readonly stonecrop: Stonecrop | undefined;
54
+ /**
55
+ * Check if Stonecrop is ready for configuration.
56
+ * Returns `true` when both Registry and Stonecrop instances are available.
57
+ */
58
+ readonly isReady: boolean;
59
+ /**
60
+ * Register the data client on the Stonecrop instance.
61
+ * Required before fetching records or dispatching actions.
62
+ *
63
+ * @param client - DataClient implementation (e.g., StonecropClient from \@stonecrop/graphql-client)
64
+ * @throws Error if the Stonecrop plugin is not installed
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * const client = new StonecropClient({ endpoint: '/graphql' })
69
+ * registerClient(client)
70
+ * ```
71
+ */
72
+ registerClient(client: DataClient): void;
73
+ /**
74
+ * Set the `getMeta` function on the Registry.
75
+ * Called by `useStonecrop()` to lazy-load doctype metadata for the current route.
76
+ *
77
+ * You must bridge `RouteContext` → `DoctypeContext`:
78
+ * - Extract doctype name from `segments` (e.g., `segments[0]`)
79
+ * - Extract record ID from `segments` if present (e.g., `segments[1]`)
80
+ * - Pass `DoctypeContext` to your data client
81
+ *
82
+ * @param fn - Function that receives RouteContext and returns Doctype
83
+ * @throws Error if the Registry is not available
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * registerMeta(({ segments }) => {
88
+ * const doctype = segments[0] // /plan/123 → 'plan'
89
+ * return client.getMeta({ doctype })
90
+ * })
91
+ * ```
92
+ */
93
+ registerMeta(fn: (routeContext: RouteContext) => Doctype | Promise<Doctype>): void;
94
+ /**
95
+ * Load a doctype into the Registry.
96
+ * Convenience method that calls `registry.addDoctype()` if available.
97
+ *
98
+ * @param doctype - The Doctype instance to register
99
+ * @throws Error if the Registry is not available
100
+ *
101
+ * @example
102
+ * ```ts
103
+ * const plan = Doctype.fromObject({ name: 'plan', fields: [...] })
104
+ * registerDoctype(plan)
105
+ * ```
106
+ */
107
+ registerDoctype(doctype: Doctype): void;
108
+ };
@@ -0,0 +1,100 @@
1
+ import { useNuxtApp } from "nuxt/app";
2
+ export function useStonecropSetup() {
3
+ const nuxtApp = useNuxtApp();
4
+ return {
5
+ /**
6
+ * The Registry instance.
7
+ * Returns `undefined` if the @stonecrop/nuxt plugin hasn't run yet.
8
+ */
9
+ get registry() {
10
+ return nuxtApp.$registry;
11
+ },
12
+ /**
13
+ * The Stonecrop instance.
14
+ * Returns `undefined` if the @stonecrop/nuxt plugin hasn't run yet.
15
+ */
16
+ get stonecrop() {
17
+ return nuxtApp.$stonecrop;
18
+ },
19
+ /**
20
+ * Check if Stonecrop is ready for configuration.
21
+ * Returns `true` when both Registry and Stonecrop instances are available.
22
+ */
23
+ get isReady() {
24
+ return !!(nuxtApp.$registry && nuxtApp.$stonecrop);
25
+ },
26
+ /**
27
+ * Register the data client on the Stonecrop instance.
28
+ * Required before fetching records or dispatching actions.
29
+ *
30
+ * @param client - DataClient implementation (e.g., StonecropClient from \@stonecrop/graphql-client)
31
+ * @throws Error if the Stonecrop plugin is not installed
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const client = new StonecropClient({ endpoint: '/graphql' })
36
+ * registerClient(client)
37
+ * ```
38
+ */
39
+ registerClient(client) {
40
+ const stonecrop = nuxtApp.$stonecrop;
41
+ if (!stonecrop) {
42
+ throw new Error(
43
+ "[useStonecropSetup] Stonecrop instance not available. Ensure the @stonecrop/nuxt module is installed and its plugin has run before calling this."
44
+ );
45
+ }
46
+ stonecrop.setClient(client);
47
+ },
48
+ /**
49
+ * Set the `getMeta` function on the Registry.
50
+ * Called by `useStonecrop()` to lazy-load doctype metadata for the current route.
51
+ *
52
+ * You must bridge `RouteContext` → `DoctypeContext`:
53
+ * - Extract doctype name from `segments` (e.g., `segments[0]`)
54
+ * - Extract record ID from `segments` if present (e.g., `segments[1]`)
55
+ * - Pass `DoctypeContext` to your data client
56
+ *
57
+ * @param fn - Function that receives RouteContext and returns Doctype
58
+ * @throws Error if the Registry is not available
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * registerMeta(({ segments }) => {
63
+ * const doctype = segments[0] // /plan/123 → 'plan'
64
+ * return client.getMeta({ doctype })
65
+ * })
66
+ * ```
67
+ */
68
+ registerMeta(fn) {
69
+ const registry = nuxtApp.$registry;
70
+ if (!registry) {
71
+ throw new Error(
72
+ "[useStonecropSetup] Registry not available. Ensure the @stonecrop/nuxt module is installed and its plugin has run before calling this."
73
+ );
74
+ }
75
+ registry.getMeta = fn;
76
+ },
77
+ /**
78
+ * Load a doctype into the Registry.
79
+ * Convenience method that calls `registry.addDoctype()` if available.
80
+ *
81
+ * @param doctype - The Doctype instance to register
82
+ * @throws Error if the Registry is not available
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const plan = Doctype.fromObject({ name: 'plan', fields: [...] })
87
+ * registerDoctype(plan)
88
+ * ```
89
+ */
90
+ registerDoctype(doctype) {
91
+ const registry = nuxtApp.$registry;
92
+ if (!registry) {
93
+ throw new Error(
94
+ "[useStonecropSetup] Registry not available. Ensure the @stonecrop/nuxt module is installed and its plugin has run before calling this."
95
+ );
96
+ }
97
+ registry.addDoctype(doctype);
98
+ }
99
+ };
100
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/nuxt",
3
- "version": "0.10.4",
3
+ "version": "0.10.6",
4
4
  "description": "Nuxt module for Stonecrop",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,14 +44,14 @@
44
44
  "jiti": "^2.4.2",
45
45
  "pathe": "^2.0.3",
46
46
  "prompts": "^2.4.2",
47
- "@stonecrop/atable": "0.10.4",
48
- "@stonecrop/aform": "0.10.4",
49
- "@stonecrop/nuxt-grafserv": "0.10.4",
50
- "@stonecrop/casl-middleware": "0.10.4",
51
- "@stonecrop/graphql-middleware": "0.10.4",
52
- "@stonecrop/node-editor": "0.10.4",
53
- "@stonecrop/schema": "0.10.4",
54
- "@stonecrop/stonecrop": "0.10.4"
47
+ "@stonecrop/atable": "0.10.6",
48
+ "@stonecrop/aform": "0.10.6",
49
+ "@stonecrop/casl-middleware": "0.10.6",
50
+ "@stonecrop/graphql-middleware": "0.10.6",
51
+ "@stonecrop/node-editor": "0.10.6",
52
+ "@stonecrop/nuxt-grafserv": "0.10.6",
53
+ "@stonecrop/schema": "0.10.6",
54
+ "@stonecrop/stonecrop": "0.10.6"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@eslint/js": "^9.39.2",