@stonecrop/stonecrop 0.12.7 → 0.13.0
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/dist/composable.js +1 -0
- package/dist/composables/lazy-link.js +125 -0
- package/dist/composables/operation-log.js +224 -0
- package/dist/composables/stonecrop.js +504 -0
- package/dist/composables/use-lazy-link-state.js +125 -0
- package/dist/composables/use-stonecrop.js +476 -0
- package/dist/doctype.js +242 -0
- package/dist/exceptions.js +16 -0
- package/dist/field-triggers.js +575 -0
- package/dist/index.js +27 -0
- package/dist/operation-log-DB-dGNT9.js +593 -0
- package/dist/operation-log-DB-dGNT9.js.map +1 -0
- package/dist/plugins/index.js +99 -0
- package/dist/registry.js +423 -0
- package/dist/schema-validator.js +407 -0
- package/dist/src/composable.d.ts +11 -0
- package/dist/src/composable.d.ts.map +1 -0
- package/dist/src/composable.js +477 -0
- package/dist/src/composables/use-lazy-link-state.d.ts +25 -0
- package/dist/src/composables/use-lazy-link-state.d.ts.map +1 -0
- package/dist/src/composables/use-stonecrop.d.ts +93 -0
- package/dist/src/composables/use-stonecrop.d.ts.map +1 -0
- package/dist/src/composables/useNestedSchema.d.ts +110 -0
- package/dist/src/composables/useNestedSchema.d.ts.map +1 -0
- package/dist/src/composables/useNestedSchema.js +155 -0
- package/dist/src/stores/data.d.ts +11 -0
- package/dist/src/stores/data.d.ts.map +1 -0
- package/dist/src/stores/xstate.d.ts +31 -0
- package/dist/src/stores/xstate.d.ts.map +1 -0
- package/dist/src/tsdoc-metadata.json +11 -0
- package/dist/src/utils.d.ts +24 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/stonecrop.css +1 -0
- package/dist/stonecrop.umd.cjs +6 -0
- package/dist/stonecrop.umd.cjs.map +1 -0
- package/dist/stores/data.js +7 -0
- package/dist/stores/hst.js +496 -0
- package/dist/stores/index.js +12 -0
- package/dist/stores/operation-log.js +580 -0
- package/dist/stores/xstate.js +29 -0
- package/dist/tests/setup.d.ts +5 -0
- package/dist/tests/setup.d.ts.map +1 -0
- package/dist/tests/setup.js +15 -0
- package/dist/types/composable.js +0 -0
- package/dist/types/doctype.js +0 -0
- package/dist/types/field-triggers.js +4 -0
- package/dist/types/hst.js +0 -0
- package/dist/types/index.js +10 -0
- package/dist/types/operation-log.js +0 -0
- package/dist/types/plugin.js +0 -0
- package/dist/types/registry.js +0 -0
- package/dist/types/schema-validator.js +13 -0
- package/dist/types/stonecrop.js +0 -0
- package/dist/utils.js +46 -0
- package/package.json +4 -4
package/dist/doctype.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { List, Map } from 'immutable';
|
|
2
|
+
/**
|
|
3
|
+
* Doctype runtime class with Immutable.js collections for HST change tracking.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export default class Doctype {
|
|
7
|
+
/**
|
|
8
|
+
* The doctype name
|
|
9
|
+
* @public
|
|
10
|
+
* @readonly
|
|
11
|
+
*/
|
|
12
|
+
doctype;
|
|
13
|
+
/**
|
|
14
|
+
* Alias for doctype (for DoctypeLike interface compatibility)
|
|
15
|
+
* @public
|
|
16
|
+
* @readonly
|
|
17
|
+
*/
|
|
18
|
+
get name() {
|
|
19
|
+
return this.doctype;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The doctype schema
|
|
23
|
+
* @public
|
|
24
|
+
* @readonly
|
|
25
|
+
*/
|
|
26
|
+
schema;
|
|
27
|
+
/**
|
|
28
|
+
* The doctype workflow
|
|
29
|
+
* @public
|
|
30
|
+
* @readonly
|
|
31
|
+
*/
|
|
32
|
+
workflow;
|
|
33
|
+
/**
|
|
34
|
+
* The doctype actions and field triggers
|
|
35
|
+
* @public
|
|
36
|
+
* @readonly
|
|
37
|
+
*/
|
|
38
|
+
actions;
|
|
39
|
+
/**
|
|
40
|
+
* The doctype component
|
|
41
|
+
* @public
|
|
42
|
+
* @readonly
|
|
43
|
+
*/
|
|
44
|
+
component;
|
|
45
|
+
/**
|
|
46
|
+
* Relationship links to other doctypes
|
|
47
|
+
* @public
|
|
48
|
+
* @readonly
|
|
49
|
+
*/
|
|
50
|
+
links;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new Doctype instance
|
|
53
|
+
* @param doctype - The doctype name
|
|
54
|
+
* @param schema - The doctype schema definition
|
|
55
|
+
* @param workflow - The doctype workflow configuration (XState machine)
|
|
56
|
+
* @param actions - The doctype actions and field triggers
|
|
57
|
+
* @param component - Optional Vue component for rendering the doctype
|
|
58
|
+
* @param links - Optional relationship links to other doctypes
|
|
59
|
+
*/
|
|
60
|
+
constructor(doctype, schema, workflow, actions, component, links) {
|
|
61
|
+
this.doctype = doctype;
|
|
62
|
+
this.schema = schema;
|
|
63
|
+
this.workflow = workflow;
|
|
64
|
+
this.actions = actions;
|
|
65
|
+
this.component = component;
|
|
66
|
+
this.links = links;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Creates a Doctype instance from a plain configuration object.
|
|
70
|
+
* Handles conversion of arrays to Immutable.js collections internally.
|
|
71
|
+
*
|
|
72
|
+
* This is the recommended way to create a Doctype from API responses
|
|
73
|
+
* or configuration files, as it encapsulates the Immutable.js construction
|
|
74
|
+
* that the framework uses internally.
|
|
75
|
+
*
|
|
76
|
+
* @param config - Plain object with doctype configuration (typically from API response)
|
|
77
|
+
* @returns A new Doctype instance with Immutable.js collections
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* // From an API response
|
|
82
|
+
* const response = await client.getMeta({ doctype: 'plan' })
|
|
83
|
+
* const doctype = Doctype.fromObject(response)
|
|
84
|
+
* registry.addDoctype(doctype)
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* // From a configuration object
|
|
90
|
+
* const planDoctype = Doctype.fromObject({
|
|
91
|
+
* name: 'Plan',
|
|
92
|
+
* fields: [
|
|
93
|
+
* { fieldname: 'title', label: 'Title', fieldtype: 'Data' },
|
|
94
|
+
* { fieldname: 'status', label: 'Status', fieldtype: 'Data' },
|
|
95
|
+
* ],
|
|
96
|
+
* workflow: {
|
|
97
|
+
* id: 'plan',
|
|
98
|
+
* initial: 'draft',
|
|
99
|
+
* states: { draft: {}, submitted: {} }
|
|
100
|
+
* }
|
|
101
|
+
* })
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
106
|
+
static fromObject(config) {
|
|
107
|
+
const schema = config.fields ? List(config.fields) : List();
|
|
108
|
+
const actions = config.actions ? Map(config.actions) : Map();
|
|
109
|
+
return new Doctype(config.name, schema, config.workflow, actions, undefined, config.links);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Returns the schema as a plain array for use with components that expect
|
|
113
|
+
* plain JavaScript arrays (e.g., AForm, ATable).
|
|
114
|
+
*
|
|
115
|
+
* @returns Array of schema fields
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* const schemaArray = doctype.getSchemaArray()
|
|
120
|
+
* // Use with AForm
|
|
121
|
+
* <AForm :schema="schemaArray" v-model:data="formData" />
|
|
122
|
+
* ```
|
|
123
|
+
*
|
|
124
|
+
* @public
|
|
125
|
+
*/
|
|
126
|
+
getSchemaArray() {
|
|
127
|
+
if (!this.schema)
|
|
128
|
+
return [];
|
|
129
|
+
return this.schema.toArray();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Returns the actions as a plain object for use with components that expect
|
|
133
|
+
* plain JavaScript objects.
|
|
134
|
+
*
|
|
135
|
+
* @returns Object mapping action names to field trigger arrays
|
|
136
|
+
*
|
|
137
|
+
* @public
|
|
138
|
+
*/
|
|
139
|
+
getActionsObject() {
|
|
140
|
+
if (!this.actions)
|
|
141
|
+
return {};
|
|
142
|
+
return this.actions.toObject();
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Returns the transitions available from a given workflow state, derived from the
|
|
146
|
+
* doctype's workflow configuration. Supports both XState format and WorkflowMeta format.
|
|
147
|
+
*
|
|
148
|
+
* @param currentState - The state name to read transitions from
|
|
149
|
+
* @returns Array of transition descriptors with `name` and `targetState`
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* const transitions = doctype.getAvailableTransitions('draft')
|
|
154
|
+
* // [{ name: 'SUBMIT', targetState: 'submitted' }]
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* @public
|
|
158
|
+
*/
|
|
159
|
+
getAvailableTransitions(currentState) {
|
|
160
|
+
const workflow = this.workflow;
|
|
161
|
+
if (!workflow)
|
|
162
|
+
return [];
|
|
163
|
+
// Check if this is WorkflowMeta format (states is an array) or XState format (states is an object)
|
|
164
|
+
if (Array.isArray(workflow.states)) {
|
|
165
|
+
// WorkflowMeta format: validate state exists and filter actions by allowedStates
|
|
166
|
+
const states = workflow.states;
|
|
167
|
+
if (!states.includes(currentState))
|
|
168
|
+
return [];
|
|
169
|
+
const actions = workflow.actions;
|
|
170
|
+
if (!actions)
|
|
171
|
+
return [];
|
|
172
|
+
return Object.entries(actions)
|
|
173
|
+
.filter(([, actionDef]) => {
|
|
174
|
+
const allowedStates = actionDef.allowedStates;
|
|
175
|
+
// If no allowedStates specified, action is available in all valid states
|
|
176
|
+
if (!allowedStates || allowedStates.length === 0)
|
|
177
|
+
return true;
|
|
178
|
+
return allowedStates.includes(currentState);
|
|
179
|
+
})
|
|
180
|
+
.map(([name]) => ({
|
|
181
|
+
name,
|
|
182
|
+
// WorkflowMeta doesn't define target states - transitions are handled server-side
|
|
183
|
+
targetState: currentState,
|
|
184
|
+
}));
|
|
185
|
+
}
|
|
186
|
+
// XState format: use the on property of the state
|
|
187
|
+
const states = workflow.states;
|
|
188
|
+
if (!states)
|
|
189
|
+
return [];
|
|
190
|
+
const stateConfig = states[currentState];
|
|
191
|
+
if (!stateConfig?.on)
|
|
192
|
+
return [];
|
|
193
|
+
return Object.entries(stateConfig.on).map(([name, target]) => ({
|
|
194
|
+
name,
|
|
195
|
+
targetState: typeof target === 'string' ? target : 'unknown',
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Returns metadata for a specific action, if available.
|
|
200
|
+
* Only works with WorkflowMeta format; returns undefined for XState format.
|
|
201
|
+
*
|
|
202
|
+
* @param actionName - The action name to get metadata for
|
|
203
|
+
* @returns Action metadata or undefined
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```ts
|
|
207
|
+
* const actionMeta = doctype.getActionMeta('submit')
|
|
208
|
+
* // { label: 'Submit', handler: 'plan:submit', allowedStates: ['draft'] }
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* @public
|
|
212
|
+
*/
|
|
213
|
+
getActionMeta(actionName) {
|
|
214
|
+
const workflow = this.workflow;
|
|
215
|
+
if (!workflow || !Array.isArray(workflow.states))
|
|
216
|
+
return undefined;
|
|
217
|
+
const actions = workflow.actions;
|
|
218
|
+
return actions?.[actionName];
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Converts the registered doctype string to a slug (kebab-case). The following conversions are made:
|
|
222
|
+
* - It replaces camelCase and PascalCase with kebab-case strings
|
|
223
|
+
* - It replaces spaces and underscores with hyphens
|
|
224
|
+
* - It converts the string to lowercase
|
|
225
|
+
*
|
|
226
|
+
* @returns The slugified doctype string
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```ts
|
|
230
|
+
* const doctype = new Doctype('TaskItem', schema, workflow, actions)
|
|
231
|
+
* console.log(doctype.slug) // 'task-item'
|
|
232
|
+
* ```
|
|
233
|
+
*
|
|
234
|
+
* @public
|
|
235
|
+
*/
|
|
236
|
+
get slug() {
|
|
237
|
+
return this.doctype
|
|
238
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
239
|
+
.replace(/[\s_]+/g, '-')
|
|
240
|
+
.toLowerCase();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NotImplementedError
|
|
3
|
+
* @param message {string} - The error message
|
|
4
|
+
* @class
|
|
5
|
+
* @description This error is thrown when a method has not been implemented
|
|
6
|
+
* @example
|
|
7
|
+
* throw new NotImplementedError('Method not implemented')
|
|
8
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error|Error}
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export class NotImplementedError extends Error {
|
|
12
|
+
constructor(message = '') {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'NotImplemented';
|
|
15
|
+
}
|
|
16
|
+
}
|