@stonecrop/stonecrop 0.10.0 → 0.10.2
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 +27 -72
- package/dist/composables/operation-log.js +7 -4
- package/dist/doctype.js +27 -0
- package/dist/registry.js +9 -0
- package/dist/src/composables/operation-log.d.ts.map +1 -1
- package/dist/src/doctype.d.ts +19 -0
- package/dist/src/doctype.d.ts.map +1 -1
- package/dist/src/registry.d.ts +7 -0
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/stonecrop.d.ts +14 -0
- package/dist/src/stonecrop.d.ts.map +1 -1
- package/dist/src/stores/operation-log.d.ts.map +1 -1
- package/dist/stonecrop.d.ts +40 -0
- package/dist/stonecrop.js +209 -157
- package/dist/stonecrop.js.map +1 -1
- package/dist/stores/operation-log.js +0 -3
- package/package.json +3 -3
- package/src/composables/operation-log.ts +7 -4
- package/src/doctype.ts +26 -0
- package/src/registry.ts +10 -0
- package/src/stonecrop.ts +29 -0
- package/src/stores/operation-log.ts +0 -3
|
@@ -409,7 +409,6 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
409
409
|
return;
|
|
410
410
|
broadcastChannel = new BroadcastChannel('stonecrop-operation-log');
|
|
411
411
|
broadcastChannel.addEventListener('message', (event) => {
|
|
412
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
413
412
|
const rawMessage = event.data;
|
|
414
413
|
if (!rawMessage || typeof rawMessage !== 'object')
|
|
415
414
|
return;
|
|
@@ -478,9 +477,7 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
478
477
|
serializer: {
|
|
479
478
|
read: (v) => {
|
|
480
479
|
try {
|
|
481
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
482
480
|
const data = JSON.parse(v);
|
|
483
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
484
481
|
return data;
|
|
485
482
|
}
|
|
486
483
|
catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/stonecrop",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": {
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"vue-router": "^5.0.2",
|
|
60
60
|
"vite": "^7.3.1",
|
|
61
61
|
"vitest": "^4.0.18",
|
|
62
|
-
"@stonecrop/aform": "0.10.
|
|
63
|
-
"@stonecrop/atable": "0.10.
|
|
62
|
+
"@stonecrop/aform": "0.10.2",
|
|
63
|
+
"@stonecrop/atable": "0.10.2",
|
|
64
64
|
"stonecrop-rig": "0.7.0"
|
|
65
65
|
},
|
|
66
66
|
"description": "Schema-driven framework with XState workflows and HST state management",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useMagicKeys, whenever } from '@vueuse/core'
|
|
2
2
|
import { storeToRefs } from 'pinia'
|
|
3
|
-
import { inject } from 'vue'
|
|
3
|
+
import { getCurrentInstance, inject } from 'vue'
|
|
4
4
|
|
|
5
5
|
import type { HSTNode } from '../stores/hst'
|
|
6
6
|
import { useOperationLogStore } from '../stores/operation-log'
|
|
@@ -32,9 +32,12 @@ import type { OperationLogConfig } from '../types/operation-log'
|
|
|
32
32
|
* @public
|
|
33
33
|
*/
|
|
34
34
|
export function useOperationLog(config?: Partial<OperationLogConfig>) {
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
|
|
35
|
+
// inject() is only valid inside a component setup() context. When this
|
|
36
|
+
// composable is called outside one (e.g. directly in test bodies or plain
|
|
37
|
+
// scripts) skip the injection entirely and fall back to the Pinia store.
|
|
38
|
+
const injectedStore = getCurrentInstance()
|
|
39
|
+
? inject<ReturnType<typeof useOperationLogStore> | undefined>('$operationLogStore', undefined)
|
|
40
|
+
: undefined
|
|
38
41
|
const store = injectedStore || useOperationLogStore()
|
|
39
42
|
|
|
40
43
|
// Apply configuration if provided
|
package/src/doctype.ts
CHANGED
|
@@ -64,6 +64,32 @@ export default class DoctypeMeta {
|
|
|
64
64
|
this.component = component
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Returns the transitions available from a given workflow state, derived from the
|
|
69
|
+
* doctype's XState workflow configuration.
|
|
70
|
+
*
|
|
71
|
+
* @param currentState - The state name to read transitions from
|
|
72
|
+
* @returns Array of transition descriptors with `name` and `targetState`
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const transitions = doctype.getAvailableTransitions('draft')
|
|
77
|
+
* // [{ name: 'SUBMIT', targetState: 'submitted' }]
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
getAvailableTransitions(currentState: string): Array<{ name: string; targetState: string }> {
|
|
83
|
+
const states = this.workflow?.states
|
|
84
|
+
if (!states) return []
|
|
85
|
+
const stateConfig = states[currentState]
|
|
86
|
+
if (!stateConfig?.on) return []
|
|
87
|
+
return Object.entries(stateConfig.on).map(([name, target]) => ({
|
|
88
|
+
name,
|
|
89
|
+
targetState: typeof target === 'string' ? target : 'unknown',
|
|
90
|
+
}))
|
|
91
|
+
}
|
|
92
|
+
|
|
67
93
|
/**
|
|
68
94
|
* Converts the registered doctype string to a slug (kebab-case). The following conversions are made:
|
|
69
95
|
* - It replaces camelCase and PascalCase with kebab-case strings
|
package/src/registry.ts
CHANGED
|
@@ -272,6 +272,16 @@ export default class Registry {
|
|
|
272
272
|
return record
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Get a registered doctype by slug
|
|
277
|
+
* @param slug - The doctype slug to look up
|
|
278
|
+
* @returns The DoctypeMeta instance if found, or undefined
|
|
279
|
+
* @public
|
|
280
|
+
*/
|
|
281
|
+
getDoctype(slug: string): DoctypeMeta | undefined {
|
|
282
|
+
return this.registry[slug]
|
|
283
|
+
}
|
|
284
|
+
|
|
275
285
|
// TODO: should we allow clearing the registry at all?
|
|
276
286
|
// clear() {
|
|
277
287
|
// this.registry = {}
|
package/src/stonecrop.ts
CHANGED
|
@@ -290,4 +290,33 @@ export class Stonecrop {
|
|
|
290
290
|
getStore(): HSTNode {
|
|
291
291
|
return this.hstStore
|
|
292
292
|
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Determine the current workflow state for a record.
|
|
296
|
+
*
|
|
297
|
+
* Reads the record's `status` field from the HST store. If the field is absent or
|
|
298
|
+
* empty the doctype's declared `workflow.initial` state is used as the fallback,
|
|
299
|
+
* giving callers a reliable state name without having to duplicate that logic.
|
|
300
|
+
*
|
|
301
|
+
* @param doctype - The doctype slug or DoctypeMeta instance
|
|
302
|
+
* @param recordId - The record identifier
|
|
303
|
+
* @returns The current state name, or an empty string if the doctype has no workflow
|
|
304
|
+
*
|
|
305
|
+
* @public
|
|
306
|
+
*/
|
|
307
|
+
getRecordState(doctype: string | DoctypeMeta, recordId: string): string {
|
|
308
|
+
const slug = typeof doctype === 'string' ? doctype : doctype.slug
|
|
309
|
+
const meta = this.registry.getDoctype(slug)
|
|
310
|
+
if (!meta?.workflow) return ''
|
|
311
|
+
|
|
312
|
+
const record = this.getRecordById(slug, recordId)
|
|
313
|
+
const status = record?.get('status') as string | undefined
|
|
314
|
+
|
|
315
|
+
const initialState =
|
|
316
|
+
typeof meta.workflow.initial === 'string'
|
|
317
|
+
? meta.workflow.initial
|
|
318
|
+
: Object.keys(meta.workflow.states ?? {})[0] ?? ''
|
|
319
|
+
|
|
320
|
+
return status || initialState
|
|
321
|
+
}
|
|
293
322
|
}
|
|
@@ -491,7 +491,6 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
491
491
|
broadcastChannel = new BroadcastChannel('stonecrop-operation-log')
|
|
492
492
|
|
|
493
493
|
broadcastChannel.addEventListener('message', (event: MessageEvent) => {
|
|
494
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
495
494
|
const rawMessage = event.data
|
|
496
495
|
|
|
497
496
|
if (!rawMessage || typeof rawMessage !== 'object') return
|
|
@@ -572,9 +571,7 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
572
571
|
serializer: {
|
|
573
572
|
read: (v: string) => {
|
|
574
573
|
try {
|
|
575
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
576
574
|
const data = JSON.parse(v)
|
|
577
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
578
575
|
return data
|
|
579
576
|
} catch {
|
|
580
577
|
return null
|