@stonecrop/stonecrop 0.10.2 → 0.10.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/stonecrop",
3
- "version": "0.10.2",
3
+ "version": "0.10.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": {
@@ -33,7 +33,8 @@
33
33
  "immutable": "^5.1.4",
34
34
  "pinia-shared-state": "^1.0.1",
35
35
  "pinia-xstate": "^3.0.0",
36
- "xstate": "^5.25.0"
36
+ "xstate": "^5.25.0",
37
+ "@stonecrop/schema": "0.10.4"
37
38
  },
38
39
  "peerDependencies": {
39
40
  "pinia": "^3.0.4",
@@ -59,9 +60,9 @@
59
60
  "vue-router": "^5.0.2",
60
61
  "vite": "^7.3.1",
61
62
  "vitest": "^4.0.18",
62
- "@stonecrop/aform": "0.10.2",
63
- "@stonecrop/atable": "0.10.2",
64
- "stonecrop-rig": "0.7.0"
63
+ "@stonecrop/aform": "0.10.4",
64
+ "stonecrop-rig": "0.7.0",
65
+ "@stonecrop/atable": "0.10.4"
65
66
  },
66
67
  "description": "Schema-driven framework with XState workflows and HST state management",
67
68
  "publishConfig": {
@@ -1,13 +1,12 @@
1
- // src/composable.ts
2
1
  import { inject, onMounted, Ref, ref, watch, provide, computed, ComputedRef } from 'vue'
3
2
 
4
- import Registry from './registry'
5
- import { Stonecrop } from './stonecrop'
6
- import DoctypeMeta from './doctype'
7
- import type { HSTNode } from './stores/hst'
8
- import { RouteContext } from './types/registry'
3
+ import Registry from '../registry'
4
+ import { Stonecrop } from '../stonecrop'
5
+ import DoctypeMeta from '../doctype'
6
+ import type { HSTNode } from '../stores/hst'
7
+ import { RouteContext } from '../types/registry'
9
8
  import { storeToRefs } from 'pinia'
10
- import type { HSTOperation, OperationLogConfig, OperationLogSnapshot } from './types/operation-log'
9
+ import type { HSTOperation, OperationLogConfig, OperationLogSnapshot } from '../types/operation-log'
11
10
  import { SchemaTypes, DoctypeSchema } from '@stonecrop/aform'
12
11
 
13
12
  /**
@@ -449,9 +448,9 @@ export function useStonecrop(options?: {
449
448
  * Recursively save a record with all nested doctype fields
450
449
  * @param doctype - The doctype metadata
451
450
  * @param recordId - The record ID to save
452
- * @returns Promise resolving to the complete save payload
451
+ * @returns The complete save payload
453
452
  */
454
- const saveRecursive = async (doctype: DoctypeMeta, recordId: string): Promise<Record<string, any>> => {
453
+ const saveRecursive = (doctype: DoctypeMeta, recordId: string): Record<string, any> => {
455
454
  if (!hstStore.value || !stonecrop.value) {
456
455
  throw new Error('HST store not initialized')
457
456
  }
package/src/doctype.ts CHANGED
@@ -14,6 +14,15 @@ export default class DoctypeMeta {
14
14
  */
15
15
  readonly doctype: string
16
16
 
17
+ /**
18
+ * Alias for doctype (for DoctypeLike interface compatibility)
19
+ * @public
20
+ * @readonly
21
+ */
22
+ get name(): string {
23
+ return this.doctype
24
+ }
25
+
17
26
  /**
18
27
  * The doctype schema
19
28
  * @public
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export type * from '@stonecrop/aform/types'
2
2
  export type * from '@stonecrop/atable/types'
3
3
 
4
- import { useStonecrop } from './composable'
4
+ import { useStonecrop } from './composables/stonecrop'
5
5
  import { useOperationLog, useUndoRedoShortcuts, withBatch } from './composables/operation-log'
6
6
  import DoctypeMeta from './doctype'
7
7
  import {
@@ -14,13 +14,13 @@ import {
14
14
  } from './field-triggers'
15
15
  import plugin from './plugins'
16
16
  import Registry from './registry'
17
- import { Stonecrop } from './stonecrop'
17
+ import { type StonecropOptions, Stonecrop } from './stonecrop'
18
18
  import { HST, createHST, type HSTNode } from './stores/hst'
19
19
  import { useOperationLogStore } from './stores/operation-log'
20
20
  // Export schema validator
21
21
  import { SchemaValidator, createValidator, validateSchema } from './schema-validator'
22
22
  export type * from './types'
23
- export type { BaseStonecropReturn, HSTChangeData, HSTStonecropReturn, OperationLogAPI } from './composable'
23
+ export type { BaseStonecropReturn, HSTChangeData, HSTStonecropReturn, OperationLogAPI } from './composables/stonecrop'
24
24
  export type { FieldTriggerEngine } from './field-triggers'
25
25
  export type {
26
26
  FieldChangeContext,
@@ -39,6 +39,7 @@ export {
39
39
  DoctypeMeta,
40
40
  Registry,
41
41
  Stonecrop,
42
+ StonecropOptions,
42
43
  useStonecrop,
43
44
  // HST exports for advanced usage
44
45
  HST,
@@ -33,14 +33,19 @@ async function setupAutoInitialization(
33
33
  * ```ts
34
34
  * import { createApp } from 'vue'
35
35
  * import Stonecrop from '@stonecrop/stonecrop'
36
+ * import { StonecropClient } from '@stonecrop/graphql-client'
36
37
  * import router from './router'
37
38
  *
39
+ * const client = new StonecropClient({ endpoint: '/graphql' })
40
+ *
38
41
  * const app = createApp(App)
39
42
  * app.use(Stonecrop, {
40
43
  * router,
44
+ * client,
41
45
  * getMeta: async (routeContext) => {
42
46
  * // routeContext contains: { path, segments }
43
- * // fetch doctype meta from your API using the route context
47
+ * // use the client to fetch doctype meta
48
+ * return client.getMeta({ doctype: routeContext.segments[0] })
44
49
  * },
45
50
  * autoInitializeRouter: true,
46
51
  * onRouterInitialized: async (registry, stonecrop) => {
@@ -67,7 +72,7 @@ const plugin: Plugin = {
67
72
  app.config.globalProperties.$registry = registry
68
73
 
69
74
  // Create and provide a global Stonecrop instance
70
- const stonecrop = new Stonecrop(registry)
75
+ const stonecrop = new Stonecrop(registry, undefined, options?.client ? { client: options.client } : undefined)
71
76
  app.provide('$stonecrop', stonecrop)
72
77
  app.config.globalProperties.$stonecrop = stonecrop
73
78
 
@@ -85,6 +90,7 @@ const plugin: Plugin = {
85
90
  }
86
91
  } catch (error) {
87
92
  // Pinia not available - operation log won't work, but app should still function
93
+ // eslint-disable-next-line no-console
88
94
  console.warn('Pinia not available - operation log features will be disabled:', error)
89
95
  }
90
96
 
package/src/stonecrop.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import type { DataClient } from '@stonecrop/schema'
1
2
  import { reactive } from 'vue'
3
+
2
4
  import DoctypeMeta from './doctype'
3
5
  import Registry from './registry'
4
6
  import { createHST, type HSTNode } from './stores/hst'
@@ -6,6 +8,22 @@ import { useOperationLogStore } from './stores/operation-log'
6
8
  import type { OperationLogConfig } from './types/operation-log'
7
9
  import type { RouteContext } from './types/registry'
8
10
 
11
+ /**
12
+ * Options for constructing a Stonecrop instance directly.
13
+ * When using the Vue plugin, pass these via `InstallOptions` instead.
14
+ * @public
15
+ */
16
+ export interface StonecropOptions {
17
+ /**
18
+ * Data client for fetching doctype metadata and records.
19
+ * Use \@stonecrop/graphql-client's StonecropClient for GraphQL backends,
20
+ * or implement DataClient for custom data sources.
21
+ *
22
+ * Can be set later via `setClient()` for deferred configuration.
23
+ */
24
+ client?: DataClient
25
+ }
26
+
9
27
  /**
10
28
  * Main Stonecrop class with HST integration and built-in Operation Log
11
29
  * @public
@@ -14,6 +32,7 @@ export class Stonecrop {
14
32
  private hstStore: HSTNode
15
33
  private _operationLogStore?: ReturnType<typeof useOperationLogStore>
16
34
  private _operationLogConfig?: Partial<OperationLogConfig>
35
+ private _client?: DataClient
17
36
 
18
37
  /** The registry instance containing all doctype definitions */
19
38
  readonly registry: Registry
@@ -22,18 +41,47 @@ export class Stonecrop {
22
41
  * Creates a new Stonecrop instance with HST integration
23
42
  * @param registry - The Registry instance containing doctype definitions
24
43
  * @param operationLogConfig - Optional configuration for the operation log
44
+ * @param options - Options including the data client (can be set later via setClient)
25
45
  */
26
- constructor(registry: Registry, operationLogConfig?: Partial<OperationLogConfig>) {
46
+ constructor(registry: Registry, operationLogConfig?: Partial<OperationLogConfig>, options?: StonecropOptions) {
27
47
  this.registry = registry
28
48
 
29
49
  // Store config for lazy initialization
30
50
  this._operationLogConfig = operationLogConfig
31
51
 
52
+ // Store data client (can be set later via setClient)
53
+ this._client = options?.client
54
+
32
55
  // Initialize HST store with auto-sync to Registry
33
56
  this.initializeHSTStore()
34
57
  this.setupRegistrySync()
35
58
  }
36
59
 
60
+ /**
61
+ * Set the data client for fetching doctype metadata and records.
62
+ * Use this for deferred configuration in Nuxt/Vue plugin setups.
63
+ *
64
+ * @param client - DataClient implementation (e.g., StonecropClient from \@stonecrop/graphql-client)
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * const { setClient } = useStonecropRegistry()
69
+ * const client = new StonecropClient({ endpoint: '/graphql' })
70
+ * setClient(client)
71
+ * ```
72
+ */
73
+ setClient(client: DataClient): void {
74
+ this._client = client
75
+ }
76
+
77
+ /**
78
+ * Get the current data client
79
+ * @returns The DataClient instance or undefined if not set
80
+ */
81
+ getClient(): DataClient | undefined {
82
+ return this._client
83
+ }
84
+
37
85
  /**
38
86
  * Get the operation log store (lazy initialization)
39
87
  * @internal
@@ -233,32 +281,72 @@ export class Stonecrop {
233
281
  }
234
282
 
235
283
  /**
236
- * Get records from server (maintains compatibility)
284
+ * Get records from server using the configured data client.
237
285
  * @param doctype - The doctype
286
+ * @throws Error if no data client has been configured
238
287
  */
239
288
  async getRecords(doctype: DoctypeMeta): Promise<void> {
240
- const response = await fetch(`/${doctype.slug}`)
241
- const records = (await response.json()) as { id: string }[]
289
+ if (!this._client) {
290
+ throw new Error(
291
+ 'No data client configured. Call setClient() with a DataClient implementation ' +
292
+ '(e.g., StonecropClient from @stonecrop/graphql-client) before fetching records.'
293
+ )
294
+ }
295
+
296
+ const records = await this._client.getRecords(doctype)
242
297
 
243
298
  // Store each record in HST
244
299
  records.forEach(record => {
245
300
  if (record.id) {
246
- this.addRecord(doctype, record.id, record)
301
+ this.addRecord(doctype, record.id as string, record)
247
302
  }
248
303
  })
249
304
  }
250
305
 
251
306
  /**
252
- * Get single record from server (maintains compatibility)
307
+ * Get single record from server using the configured data client.
253
308
  * @param doctype - The doctype
254
309
  * @param recordId - The record ID
310
+ * @throws Error if no data client has been configured
255
311
  */
256
312
  async getRecord(doctype: DoctypeMeta, recordId: string): Promise<void> {
257
- const response = await fetch(`/${doctype.slug}/${recordId}`)
258
- const record = await response.json()
313
+ if (!this._client) {
314
+ throw new Error(
315
+ 'No data client configured. Call setClient() with a DataClient implementation ' +
316
+ '(e.g., StonecropClient from @stonecrop/graphql-client) before fetching records.'
317
+ )
318
+ }
319
+
320
+ const record = await this._client.getRecord(doctype, recordId)
321
+
322
+ if (record) {
323
+ this.addRecord(doctype, recordId, record)
324
+ }
325
+ }
326
+
327
+ /**
328
+ * Dispatch an action to the server via the configured data client.
329
+ * All state changes flow through this single mutation endpoint.
330
+ *
331
+ * @param doctype - The doctype
332
+ * @param action - Action name to execute (e.g., 'SUBMIT', 'APPROVE', 'save')
333
+ * @param args - Action arguments (typically record ID and/or form data)
334
+ * @returns Action result with success status, response data, and any error
335
+ * @throws Error if no data client has been configured
336
+ */
337
+ async dispatchAction(
338
+ doctype: DoctypeMeta,
339
+ action: string,
340
+ args?: unknown[]
341
+ ): Promise<{ success: boolean; data: unknown; error: string | null }> {
342
+ if (!this._client) {
343
+ throw new Error(
344
+ 'No data client configured. Call setClient() with a DataClient implementation ' +
345
+ '(e.g., StonecropClient from @stonecrop/graphql-client) before dispatching actions.'
346
+ )
347
+ }
259
348
 
260
- // Store record
261
- this.addRecord(doctype, recordId, record)
349
+ return this._client.runAction(doctype, action, args)
262
350
  }
263
351
 
264
352
  /**
@@ -1,3 +1,4 @@
1
+ import type { DataClient } from '@stonecrop/schema'
1
2
  import type { SchemaTypes } from '@stonecrop/aform'
2
3
  import { List, Map } from 'immutable'
3
4
  import type { Component } from 'vue'
@@ -47,6 +48,22 @@ export type InstallOptions = {
47
48
  router?: Router
48
49
  components?: Record<string, Component>
49
50
  getMeta?: (routeContext: RouteContext) => DoctypeMeta | Promise<DoctypeMeta>
51
+ /**
52
+ * Data client for fetching doctype metadata and records.
53
+ * Use \@stonecrop/graphql-client's StonecropClient for GraphQL backends,
54
+ * or implement DataClient for custom data sources.
55
+ *
56
+ * Can be set later via `useStonecropRegistry().setClient()` for deferred configuration.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * import { StonecropClient } from '@stonecrop/graphql-client'
61
+ *
62
+ * const client = new StonecropClient({ endpoint: '/graphql' })
63
+ * app.use(StonecropPlugin, { client })
64
+ * ```
65
+ */
66
+ client?: DataClient
50
67
  /** Automatically run initialization callback after app mounting (default: false) */
51
68
  autoInitializeRouter?: boolean
52
69
  /** Callback function called after plugin is ready and mounted */
@@ -1 +0,0 @@
1
- {"version":3,"file":"composable.d.ts","sourceRoot":"","sources":["../../src/composable.ts"],"names":[],"mappings":"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"}