@stonecrop/graphql-client 0.13.14 → 0.14.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/README.md CHANGED
@@ -18,7 +18,7 @@ This boundary exists because PostGraphile's schema naming is configurable. An ap
18
18
 
19
19
  | Operation | Arguments | Returns |
20
20
  |-----------|-----------|---------|
21
- | `stonecropRecord` | `doctype`, `id`, `options?` | `{ record, unknownLinks? }` |
21
+ | `stonecropRecord` | `doctype`, `id`, `options?` | `{ data, unknownLinks? }` |
22
22
  | `stonecropRecords` | `doctype`, `filters?`, `orderBy?`, `limit?`, `offset?`, `options?` | `{ data[], count }` |
23
23
  | `stonecropMeta` | `doctype` | `DoctypeMeta` |
24
24
  | `stonecropAllMeta` | — | `DoctypeMeta[]` |
@@ -1,4 +1,87 @@
1
- class s {
1
+ const n = `
2
+ query GetMeta($doctype: String!) {
3
+ stonecropMeta(doctype: $doctype) {
4
+ name
5
+ slug
6
+ fields {
7
+ kind
8
+ fieldname
9
+ component
10
+ doctype
11
+ label
12
+ width
13
+ align
14
+ edit
15
+ mask
16
+ format
17
+ mode
18
+ options
19
+ required
20
+ readOnly
21
+ hidden
22
+ default
23
+ validation
24
+ cardinality
25
+ source
26
+ }
27
+ workflow {
28
+ states
29
+ actions {
30
+ label
31
+ requiredFields
32
+ allowedStates
33
+ }
34
+ }
35
+ inherits
36
+ }
37
+ }
38
+ `, s = `
39
+ mutation RunAction($doctype: String!, $action: String!, $args: JSON) {
40
+ stonecropAction(doctype: $doctype, action: $action, args: $args) {
41
+ success
42
+ data
43
+ error
44
+ }
45
+ }
46
+ `, a = `
47
+ query GetAllMeta {
48
+ stonecropAllMeta {
49
+ name
50
+ slug
51
+ fields {
52
+ kind
53
+ fieldname
54
+ component
55
+ doctype
56
+ label
57
+ width
58
+ align
59
+ edit
60
+ mask
61
+ format
62
+ mode
63
+ options
64
+ required
65
+ readOnly
66
+ hidden
67
+ default
68
+ validation
69
+ cardinality
70
+ source
71
+ }
72
+ workflow {
73
+ states
74
+ actions {
75
+ label
76
+ requiredFields
77
+ allowedStates
78
+ }
79
+ }
80
+ inherits
81
+ }
82
+ }
83
+ `;
84
+ class c {
2
85
  endpoint;
3
86
  headers;
4
87
  metaCache = /* @__PURE__ */ new Map();
@@ -43,95 +126,16 @@ class s {
43
126
  async getMeta(e) {
44
127
  const t = this.metaCache.get(e.doctype);
45
128
  if (t) return t;
46
- const o = await this.query(
47
- `
48
- query GetMeta($doctype: String!) {
49
- stonecropMeta(doctype: $doctype) {
50
- name
51
- slug
52
- fields {
53
- fieldname
54
- fieldtype
55
- component
56
- label
57
- width
58
- align
59
- required
60
- readOnly
61
- edit
62
- hidden
63
- default
64
- options
65
- mask
66
- precision
67
- scale
68
- mode
69
- validation
70
- }
71
- workflow {
72
- states
73
- actions {
74
- label
75
- handler
76
- requiredFields
77
- allowedStates
78
- confirm
79
- args
80
- }
81
- }
82
- inherits
83
- }
84
- }
85
- `,
86
- { doctype: e.doctype }
87
- );
129
+ const o = await this.query(n, {
130
+ doctype: e.doctype
131
+ });
88
132
  return o.stonecropMeta && this.metaCache.set(e.doctype, o.stonecropMeta), o.stonecropMeta;
89
133
  }
90
134
  /**
91
135
  * Get all doctype metadata
92
136
  */
93
137
  async getAllMeta() {
94
- const e = await this.query(
95
- `
96
- query GetAllMeta {
97
- stonecropAllMeta {
98
- name
99
- slug
100
- fields {
101
- fieldname
102
- fieldtype
103
- component
104
- label
105
- width
106
- align
107
- required
108
- readOnly
109
- edit
110
- hidden
111
- default
112
- options
113
- mask
114
- precision
115
- scale
116
- mode
117
- validation
118
- }
119
- workflow {
120
- states
121
- actions {
122
- label
123
- handler
124
- requiredFields
125
- allowedStates
126
- confirm
127
- args
128
- }
129
- }
130
- inherits
131
- }
132
- }
133
- `
134
- );
138
+ const e = await this.query(a);
135
139
  for (const t of e.stonecropAllMeta)
136
140
  this.metaCache.set(t.name, t);
137
141
  return e.stonecropAllMeta;
@@ -212,22 +216,11 @@ class s {
212
216
  * @param args - Action arguments
213
217
  */
214
218
  async runAction(e, t, o) {
215
- return (await this.query(
216
- `
217
- mutation RunAction($doctype: String!, $action: String!, $args: JSON) {
218
- stonecropAction(doctype: $doctype, action: $action, args: $args) {
219
- success
220
- data
221
- error
222
- }
223
- }
224
- `,
225
- {
226
- doctype: e.name,
227
- action: t,
228
- args: o
229
- }
230
- )).stonecropAction;
219
+ return (await this.query(s, {
220
+ doctype: e.name,
221
+ action: t,
222
+ args: o
223
+ })).stonecropAction;
231
224
  }
232
225
  /**
233
226
  * Clear the cached doctype metadata.
@@ -240,6 +233,6 @@ class s {
240
233
  }
241
234
  }
242
235
  export {
243
- s as StonecropClient
236
+ c as StonecropClient
244
237
  };
245
238
  //# sourceMappingURL=graphql-client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"graphql-client.js","sources":["../src/client.ts"],"sourcesContent":["import type {\n\tDataClient,\n\tDoctypeMeta,\n\tDoctypeContext,\n\tDoctypeRef,\n\tGetRecordOptions,\n\tGetRecordsOptions,\n} from '@stonecrop/schema'\nimport type { GetRecordResult } from './types'\n\nexport type { DoctypeContext, DoctypeRef }\nexport type { GetRecordResult }\n\n/**\n * Options for creating a Stonecrop client\n * @public\n */\nexport interface StonecropClientOptions {\n\t/** GraphQL endpoint URL */\n\tendpoint: string\n\t/** Additional HTTP headers to include in requests */\n\theaders?: Record<string, string>\n}\n\n/**\n * Client for interacting with Stonecrop GraphQL API.\n *\n * Acts as a transport layer — it passes requests to the middleware and returns\n * merged results. Does not construct queries itself.\n *\n * @public\n */\nexport class StonecropClient implements DataClient {\n\tprivate endpoint: string\n\tprivate headers: Record<string, string>\n\tprivate metaCache: Map<string, DoctypeMeta> = new Map()\n\n\tconstructor(options: StonecropClientOptions) {\n\t\tthis.endpoint = options.endpoint\n\t\tthis.headers = {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...options.headers,\n\t\t}\n\t}\n\n\t/**\n\t * Execute a GraphQL query against the configured endpoint.\n\t *\n\t * @param query - GraphQL query string\n\t * @param variables - Query variables\n\t * @throws Error if the GraphQL response contains errors\n\t */\n\tasync query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T> {\n\t\tconst response = await fetch(this.endpoint, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: this.headers,\n\t\t\tbody: JSON.stringify({ query, variables }),\n\t\t})\n\n\t\tconst json: { data?: T; errors?: Array<{ message: string }> } = await response.json()\n\n\t\tif (json.errors?.length) {\n\t\t\tthrow new Error(json.errors[0].message)\n\t\t}\n\n\t\tif (json.data === undefined) {\n\t\t\tthrow new Error('GraphQL response missing data field')\n\t\t}\n\n\t\treturn json.data\n\t}\n\n\t/**\n\t * Execute a GraphQL mutation. Delegates to query() since both use POST.\n\t *\n\t * @param mutation - GraphQL mutation string\n\t * @param variables - Mutation variables\n\t */\n\tasync mutate<T = unknown>(mutation: string, variables?: Record<string, unknown>): Promise<T> {\n\t\treturn this.query<T>(mutation, variables)\n\t}\n\n\t/**\n\t * Get doctype metadata\n\t * @param context - Doctype context containing doctype name\n\t */\n\tasync getMeta(context: DoctypeContext): Promise<DoctypeMeta | null> {\n\t\tconst cached = this.metaCache.get(context.doctype)\n\t\tif (cached) return cached\n\n\t\tconst result = await this.query<{ stonecropMeta: DoctypeMeta | null }>(\n\t\t\t`\n\t\t\tquery GetMeta($doctype: String!) {\n\t\t\t\tstonecropMeta(doctype: $doctype) {\n\t\t\t\t\tname\n\t\t\t\t\tslug\n\t\t\t\t\tfields {\n\t\t\t\t\t\tfieldname\n\t\t\t\t\t\tfieldtype\n\t\t\t\t\t\tcomponent\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\twidth\n\t\t\t\t\t\talign\n\t\t\t\t\t\trequired\n\t\t\t\t\t\treadOnly\n\t\t\t\t\t\tedit\n\t\t\t\t\t\thidden\n\t\t\t\t\t\tdefault\n\t\t\t\t\t\toptions\n\t\t\t\t\t\tmask\n\t\t\t\t\t\tprecision\n\t\t\t\t\t\tscale\n\t\t\t\t\t\tmode\n\t\t\t\t\t\tvalidation\n\t\t\t\t\t}\n\t\t\t\t\tworkflow {\n\t\t\t\t\t\tstates\n\t\t\t\t\t\tactions {\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\thandler\n\t\t\t\t\t\t\trequiredFields\n\t\t\t\t\t\t\tallowedStates\n\t\t\t\t\t\t\tconfirm\n\t\t\t\t\t\t\targs\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tinherits\n\t\t\t\t}\n\t\t\t}\n\t\t\t`,\n\t\t\t{ doctype: context.doctype }\n\t\t)\n\n\t\tif (result.stonecropMeta) {\n\t\t\tthis.metaCache.set(context.doctype, result.stonecropMeta)\n\t\t}\n\n\t\treturn result.stonecropMeta\n\t}\n\n\t/**\n\t * Get all doctype metadata\n\t */\n\tasync getAllMeta(): Promise<DoctypeMeta[]> {\n\t\tconst result = await this.query<{ stonecropAllMeta: DoctypeMeta[] }>(\n\t\t\t`\n\t\t\tquery GetAllMeta {\n\t\t\t\tstonecropAllMeta {\n\t\t\t\t\tname\n\t\t\t\t\tslug\n\t\t\t\t\tfields {\n\t\t\t\t\t\tfieldname\n\t\t\t\t\t\tfieldtype\n\t\t\t\t\t\tcomponent\n\t\t\t\t\t\tlabel\n\t\t\t\t\t\twidth\n\t\t\t\t\t\talign\n\t\t\t\t\t\trequired\n\t\t\t\t\t\treadOnly\n\t\t\t\t\t\tedit\n\t\t\t\t\t\thidden\n\t\t\t\t\t\tdefault\n\t\t\t\t\t\toptions\n\t\t\t\t\t\tmask\n\t\t\t\t\t\tprecision\n\t\t\t\t\t\tscale\n\t\t\t\t\t\tmode\n\t\t\t\t\t\tvalidation\n\t\t\t\t\t}\n\t\t\t\t\tworkflow {\n\t\t\t\t\t\tstates\n\t\t\t\t\t\tactions {\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\thandler\n\t\t\t\t\t\t\trequiredFields\n\t\t\t\t\t\t\tallowedStates\n\t\t\t\t\t\t\tconfirm\n\t\t\t\t\t\t\targs\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tinherits\n\t\t\t\t}\n\t\t\t}\n\t\t\t`\n\t\t)\n\n\t\tfor (const meta of result.stonecropAllMeta) {\n\t\t\tthis.metaCache.set(meta.name, meta)\n\t\t}\n\n\t\treturn result.stonecropAllMeta\n\t}\n\n\t/**\n\t * Get a single record by ID.\n\t *\n\t * Routes through the stonecropRecord resolver which handles nested data\n\t * fetching based on the includeNested option.\n\t *\n\t * @param doctype - Doctype reference (name and optional slug)\n\t * @param recordId - Record ID to fetch\n\t * @param options - Query options (includeNested, maxDepth)\n\t */\n\tasync getRecord(doctype: DoctypeRef, recordId: string, options?: GetRecordOptions): Promise<GetRecordResult> {\n\t\tconst result = await this.query<{\n\t\t\tstonecropRecord: { data: Record<string, unknown> | null; unknownLinks?: string[] }\n\t\t}>(\n\t\t\t`query GetRecord($doctype: String!, $id: String!, $options: JSON) {\n\t\t\t\tstonecropRecord(doctype: $doctype, id: $id, options: $options) {\n\t\t\t\t\tdata\n\t\t\t\t\tunknownLinks\n\t\t\t\t}\n\t\t\t}`,\n\t\t\t{\n\t\t\t\tdoctype: doctype.name,\n\t\t\t\tid: recordId,\n\t\t\t\toptions: options?.includeNested\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tincludeNested: options.includeNested,\n\t\t\t\t\t\t\tmaxDepth: options.maxDepth,\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t}\n\t\t)\n\n\t\treturn {\n\t\t\trecord: result.stonecropRecord?.data ?? null,\n\t\t\tunknownLinks: result.stonecropRecord?.unknownLinks,\n\t\t}\n\t}\n\n\t/**\n\t * Get multiple records with optional filtering and pagination.\n\t *\n\t * Returns flat arrays — the middleware merges connection format (\\{ nodes: [...] \\})\n\t * into plain arrays before returning.\n\t *\n\t * @param doctype - Doctype reference (name and optional slug)\n\t * @param options - Query options (filters, orderBy, limit, offset)\n\t */\n\tasync getRecords(doctype: DoctypeRef, options?: GetRecordsOptions): Promise<Record<string, unknown>[]> {\n\t\tconst result = await this.query<{\n\t\t\tstonecropRecords: { data: Record<string, unknown>[] }\n\t\t}>(\n\t\t\t`\n\t\t\tquery GetRecords(\n\t\t\t\t$doctype: String!\n\t\t\t\t$filters: JSON\n\t\t\t\t$orderBy: String\n\t\t\t\t$limit: Int\n\t\t\t\t$offset: Int\n\t\t\t) {\n\t\t\t\tstonecropRecords(\n\t\t\t\t\tdoctype: $doctype\n\t\t\t\t\tfilters: $filters\n\t\t\t\t\torderBy: $orderBy\n\t\t\t\t\tlimit: $limit\n\t\t\t\t\toffset: $offset\n\t\t\t\t) {\n\t\t\t\t\tdata\n\t\t\t\t\tcount\n\t\t\t\t}\n\t\t\t}\n\t\t\t`,\n\t\t\t{\n\t\t\t\tdoctype: doctype.name,\n\t\t\t\t...options,\n\t\t\t}\n\t\t)\n\n\t\treturn result.stonecropRecords.data\n\t}\n\n\t/**\n\t * Execute a doctype action\n\t * @param doctype - Doctype reference (name and optional slug)\n\t * @param action - Action name to execute\n\t * @param args - Action arguments\n\t */\n\tasync runAction(\n\t\tdoctype: DoctypeRef,\n\t\taction: string,\n\t\targs?: unknown[]\n\t): Promise<{ success: boolean; data: unknown; error: string | null }> {\n\t\tconst result = await this.query<{\n\t\t\tstonecropAction: { success: boolean; data: unknown; error: string | null }\n\t\t}>(\n\t\t\t`\n\t\t\tmutation RunAction($doctype: String!, $action: String!, $args: JSON) {\n\t\t\t\tstonecropAction(doctype: $doctype, action: $action, args: $args) {\n\t\t\t\t\tsuccess\n\t\t\t\t\tdata\n\t\t\t\t\terror\n\t\t\t\t}\n\t\t\t}\n\t\t\t`,\n\t\t\t{\n\t\t\t\tdoctype: doctype.name,\n\t\t\t\taction,\n\t\t\t\targs,\n\t\t\t}\n\t\t)\n\n\t\treturn result.stonecropAction\n\t}\n\n\t/**\n\t * Clear the cached doctype metadata.\n\t *\n\t * Call this if the server-side doctype schema has changed and you need\n\t * to fetch fresh metadata (e.g., after adding a new field).\n\t */\n\tclearMetaCache(): void {\n\t\tthis.metaCache.clear()\n\t}\n}\n"],"names":["StonecropClient","options","query","variables","json","mutation","context","cached","result","meta","doctype","recordId","action","args"],"mappings":"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"}
1
+ {"version":3,"file":"graphql-client.js","sources":["../src/queries.ts","../src/client.ts"],"sourcesContent":["/**\n * GraphQL query documents sent by {@link StonecropClient} to the middleware.\n *\n * These are the client's half of the wire contract with `@stonecrop/graphql-middleware`.\n * They live here as exported constants (rather than inline in the client methods) so the\n * cross-package contract test can validate the exact strings the client sends against the\n * middleware's published SDL — a field the server drops while a query still selects it must\n * fail CI, not production.\n *\n * @public\n */\nexport const GET_META_QUERY = `\n\tquery GetMeta($doctype: String!) {\n\t\tstonecropMeta(doctype: $doctype) {\n\t\t\tname\n\t\t\tslug\n\t\t\tfields {\n\t\t\t\tkind\n\t\t\t\tfieldname\n\t\t\t\tcomponent\n\t\t\t\tdoctype\n\t\t\t\tlabel\n\t\t\t\twidth\n\t\t\t\talign\n\t\t\t\tedit\n\t\t\t\tmask\n\t\t\t\tformat\n\t\t\t\tmode\n\t\t\t\toptions\n\t\t\t\trequired\n\t\t\t\treadOnly\n\t\t\t\thidden\n\t\t\t\tdefault\n\t\t\t\tvalidation\n\t\t\t\tcardinality\n\t\t\t\tsource\n\t\t\t}\n\t\t\tworkflow {\n\t\t\t\tstates\n\t\t\t\tactions {\n\t\t\t\t\tlabel\n\t\t\t\t\trequiredFields\n\t\t\t\t\tallowedStates\n\t\t\t\t}\n\t\t\t}\n\t\t\tinherits\n\t\t}\n\t}\n`\n\n/**\n * Mutation document for dispatching a workflow action (the server-owned transition).\n * @public\n */\nexport const RUN_ACTION_MUTATION = `\n\tmutation RunAction($doctype: String!, $action: String!, $args: JSON) {\n\t\tstonecropAction(doctype: $doctype, action: $action, args: $args) {\n\t\t\tsuccess\n\t\t\tdata\n\t\t\terror\n\t\t}\n\t}\n`\n\n/**\n * Query document for fetching all doctype metadata.\n * @public\n */\nexport const GET_ALL_META_QUERY = `\n\tquery GetAllMeta {\n\t\tstonecropAllMeta {\n\t\t\tname\n\t\t\tslug\n\t\t\tfields {\n\t\t\t\tkind\n\t\t\t\tfieldname\n\t\t\t\tcomponent\n\t\t\t\tdoctype\n\t\t\t\tlabel\n\t\t\t\twidth\n\t\t\t\talign\n\t\t\t\tedit\n\t\t\t\tmask\n\t\t\t\tformat\n\t\t\t\tmode\n\t\t\t\toptions\n\t\t\t\trequired\n\t\t\t\treadOnly\n\t\t\t\thidden\n\t\t\t\tdefault\n\t\t\t\tvalidation\n\t\t\t\tcardinality\n\t\t\t\tsource\n\t\t\t}\n\t\t\tworkflow {\n\t\t\t\tstates\n\t\t\t\tactions {\n\t\t\t\t\tlabel\n\t\t\t\t\trequiredFields\n\t\t\t\t\tallowedStates\n\t\t\t\t}\n\t\t\t}\n\t\t\tinherits\n\t\t}\n\t}\n`\n","import type {\n\tDataClient,\n\tDoctypeMeta,\n\tDoctypeContext,\n\tDoctypeRef,\n\tGetRecordOptions,\n\tGetRecordsOptions,\n} from '@stonecrop/schema'\nimport type { GetRecordResult } from './types'\nimport { GET_META_QUERY, GET_ALL_META_QUERY, RUN_ACTION_MUTATION } from './queries'\n\nexport type { DoctypeContext, DoctypeRef }\nexport type { GetRecordResult }\n\n/**\n * Options for creating a Stonecrop client\n * @public\n */\nexport interface StonecropClientOptions {\n\t/** GraphQL endpoint URL */\n\tendpoint: string\n\t/** Additional HTTP headers to include in requests */\n\theaders?: Record<string, string>\n}\n\n/**\n * Client for interacting with Stonecrop GraphQL API.\n *\n * Acts as a transport layer — it passes requests to the middleware and returns\n * merged results. Does not construct queries itself.\n *\n * @public\n */\nexport class StonecropClient implements DataClient {\n\tprivate endpoint: string\n\tprivate headers: Record<string, string>\n\tprivate metaCache: Map<string, DoctypeMeta> = new Map()\n\n\tconstructor(options: StonecropClientOptions) {\n\t\tthis.endpoint = options.endpoint\n\t\tthis.headers = {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...options.headers,\n\t\t}\n\t}\n\n\t/**\n\t * Execute a GraphQL query against the configured endpoint.\n\t *\n\t * @param query - GraphQL query string\n\t * @param variables - Query variables\n\t * @throws Error if the GraphQL response contains errors\n\t */\n\tasync query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T> {\n\t\tconst response = await fetch(this.endpoint, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: this.headers,\n\t\t\tbody: JSON.stringify({ query, variables }),\n\t\t})\n\n\t\tconst json: { data?: T; errors?: Array<{ message: string }> } = await response.json()\n\n\t\tif (json.errors?.length) {\n\t\t\tthrow new Error(json.errors[0].message)\n\t\t}\n\n\t\tif (json.data === undefined) {\n\t\t\tthrow new Error('GraphQL response missing data field')\n\t\t}\n\n\t\treturn json.data\n\t}\n\n\t/**\n\t * Execute a GraphQL mutation. Delegates to query() since both use POST.\n\t *\n\t * @param mutation - GraphQL mutation string\n\t * @param variables - Mutation variables\n\t */\n\tasync mutate<T = unknown>(mutation: string, variables?: Record<string, unknown>): Promise<T> {\n\t\treturn this.query<T>(mutation, variables)\n\t}\n\n\t/**\n\t * Get doctype metadata\n\t * @param context - Doctype context containing doctype name\n\t */\n\tasync getMeta(context: DoctypeContext): Promise<DoctypeMeta | null> {\n\t\tconst cached = this.metaCache.get(context.doctype)\n\t\tif (cached) return cached\n\n\t\tconst result = await this.query<{ stonecropMeta: DoctypeMeta | null }>(GET_META_QUERY, {\n\t\t\tdoctype: context.doctype,\n\t\t})\n\n\t\tif (result.stonecropMeta) {\n\t\t\tthis.metaCache.set(context.doctype, result.stonecropMeta)\n\t\t}\n\n\t\treturn result.stonecropMeta\n\t}\n\n\t/**\n\t * Get all doctype metadata\n\t */\n\tasync getAllMeta(): Promise<DoctypeMeta[]> {\n\t\tconst result = await this.query<{ stonecropAllMeta: DoctypeMeta[] }>(GET_ALL_META_QUERY)\n\n\t\tfor (const meta of result.stonecropAllMeta) {\n\t\t\tthis.metaCache.set(meta.name, meta)\n\t\t}\n\n\t\treturn result.stonecropAllMeta\n\t}\n\n\t/**\n\t * Get a single record by ID.\n\t *\n\t * Routes through the stonecropRecord resolver which handles nested data\n\t * fetching based on the includeNested option.\n\t *\n\t * @param doctype - Doctype reference (name and optional slug)\n\t * @param recordId - Record ID to fetch\n\t * @param options - Query options (includeNested, maxDepth)\n\t */\n\tasync getRecord(doctype: DoctypeRef, recordId: string, options?: GetRecordOptions): Promise<GetRecordResult> {\n\t\tconst result = await this.query<{\n\t\t\tstonecropRecord: { data: Record<string, unknown> | null; unknownLinks?: string[] }\n\t\t}>(\n\t\t\t`query GetRecord($doctype: String!, $id: String!, $options: JSON) {\n\t\t\t\tstonecropRecord(doctype: $doctype, id: $id, options: $options) {\n\t\t\t\t\tdata\n\t\t\t\t\tunknownLinks\n\t\t\t\t}\n\t\t\t}`,\n\t\t\t{\n\t\t\t\tdoctype: doctype.name,\n\t\t\t\tid: recordId,\n\t\t\t\toptions: options?.includeNested\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tincludeNested: options.includeNested,\n\t\t\t\t\t\t\tmaxDepth: options.maxDepth,\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t}\n\t\t)\n\n\t\treturn {\n\t\t\trecord: result.stonecropRecord?.data ?? null,\n\t\t\tunknownLinks: result.stonecropRecord?.unknownLinks,\n\t\t}\n\t}\n\n\t/**\n\t * Get multiple records with optional filtering and pagination.\n\t *\n\t * Returns flat arrays — the middleware merges connection format (\\{ nodes: [...] \\})\n\t * into plain arrays before returning.\n\t *\n\t * @param doctype - Doctype reference (name and optional slug)\n\t * @param options - Query options (filters, orderBy, limit, offset)\n\t */\n\tasync getRecords(doctype: DoctypeRef, options?: GetRecordsOptions): Promise<Record<string, unknown>[]> {\n\t\tconst result = await this.query<{\n\t\t\tstonecropRecords: { data: Record<string, unknown>[] }\n\t\t}>(\n\t\t\t`\n\t\t\tquery GetRecords(\n\t\t\t\t$doctype: String!\n\t\t\t\t$filters: JSON\n\t\t\t\t$orderBy: String\n\t\t\t\t$limit: Int\n\t\t\t\t$offset: Int\n\t\t\t) {\n\t\t\t\tstonecropRecords(\n\t\t\t\t\tdoctype: $doctype\n\t\t\t\t\tfilters: $filters\n\t\t\t\t\torderBy: $orderBy\n\t\t\t\t\tlimit: $limit\n\t\t\t\t\toffset: $offset\n\t\t\t\t) {\n\t\t\t\t\tdata\n\t\t\t\t\tcount\n\t\t\t\t}\n\t\t\t}\n\t\t\t`,\n\t\t\t{\n\t\t\t\tdoctype: doctype.name,\n\t\t\t\t...options,\n\t\t\t}\n\t\t)\n\n\t\treturn result.stonecropRecords.data\n\t}\n\n\t/**\n\t * Execute a doctype action\n\t * @param doctype - Doctype reference (name and optional slug)\n\t * @param action - Action name to execute\n\t * @param args - Action arguments\n\t */\n\tasync runAction(\n\t\tdoctype: DoctypeRef,\n\t\taction: string,\n\t\targs?: unknown[]\n\t): Promise<{ success: boolean; data: unknown; error: string | null }> {\n\t\tconst result = await this.query<{\n\t\t\tstonecropAction: { success: boolean; data: unknown; error: string | null }\n\t\t}>(RUN_ACTION_MUTATION, {\n\t\t\tdoctype: doctype.name,\n\t\t\taction,\n\t\t\targs,\n\t\t})\n\n\t\treturn result.stonecropAction\n\t}\n\n\t/**\n\t * Clear the cached doctype metadata.\n\t *\n\t * Call this if the server-side doctype schema has changed and you need\n\t * to fetch fresh metadata (e.g., after adding a new field).\n\t */\n\tclearMetaCache(): void {\n\t\tthis.metaCache.clear()\n\t}\n}\n"],"names":["GET_META_QUERY","RUN_ACTION_MUTATION","GET_ALL_META_QUERY","StonecropClient","options","query","variables","json","mutation","context","cached","result","meta","doctype","recordId","action","args"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,WAAW,EACX,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,CAAA;AAE/B;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACtC,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAED;;;;;;;GAOG;AACH,qBAAa,eAAgB,YAAW,UAAU;IACjD,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,SAAS,CAAsC;gBAE3C,OAAO,EAAE,sBAAsB;IAQ3C;;;;;;OAMG;IACG,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoBxF;;;;;OAKG;IACG,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAI5F;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAsDnE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAkD1C;;;;;;;;;OASG;IACG,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IA4B5G;;;;;;;;OAQG;IACG,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAiCtG;;;;;OAKG;IACG,SAAS,CACd,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,OAAO,EAAE,GACd,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAuBrE;;;;;OAKG;IACH,cAAc,IAAI,IAAI;CAGtB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,WAAW,EACX,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAG9C,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,CAAA;AAE/B;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACtC,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAED;;;;;;;GAOG;AACH,qBAAa,eAAgB,YAAW,UAAU;IACjD,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,SAAS,CAAsC;gBAE3C,OAAO,EAAE,sBAAsB;IAQ3C;;;;;;OAMG;IACG,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoBxF;;;;;OAKG;IACG,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAI5F;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAenE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAU1C;;;;;;;;;OASG;IACG,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IA4B5G;;;;;;;;OAQG;IACG,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAiCtG;;;;;OAKG;IACG,SAAS,CACd,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,OAAO,EAAE,GACd,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAYrE;;;;;OAKG;IACH,cAAc,IAAI,IAAI;CAGtB"}
@@ -1,3 +1,4 @@
1
+ import { GET_META_QUERY, GET_ALL_META_QUERY, RUN_ACTION_MUTATION } from './queries';
1
2
  /**
2
3
  * Client for interacting with Stonecrop GraphQL API.
3
4
  *
@@ -56,45 +57,9 @@ export class StonecropClient {
56
57
  const cached = this.metaCache.get(context.doctype);
57
58
  if (cached)
58
59
  return cached;
59
- const result = await this.query(`
60
- query GetMeta($doctype: String!) {
61
- stonecropMeta(doctype: $doctype) {
62
- name
63
- slug
64
- fields {
65
- fieldname
66
- fieldtype
67
- component
68
- label
69
- width
70
- align
71
- required
72
- readOnly
73
- edit
74
- hidden
75
- default
76
- options
77
- mask
78
- precision
79
- scale
80
- mode
81
- validation
82
- }
83
- workflow {
84
- states
85
- actions {
86
- label
87
- handler
88
- requiredFields
89
- allowedStates
90
- confirm
91
- args
92
- }
93
- }
94
- inherits
95
- }
96
- }
97
- `, { doctype: context.doctype });
60
+ const result = await this.query(GET_META_QUERY, {
61
+ doctype: context.doctype,
62
+ });
98
63
  if (result.stonecropMeta) {
99
64
  this.metaCache.set(context.doctype, result.stonecropMeta);
100
65
  }
@@ -104,45 +69,7 @@ export class StonecropClient {
104
69
  * Get all doctype metadata
105
70
  */
106
71
  async getAllMeta() {
107
- const result = await this.query(`
108
- query GetAllMeta {
109
- stonecropAllMeta {
110
- name
111
- slug
112
- fields {
113
- fieldname
114
- fieldtype
115
- component
116
- label
117
- width
118
- align
119
- required
120
- readOnly
121
- edit
122
- hidden
123
- default
124
- options
125
- mask
126
- precision
127
- scale
128
- mode
129
- validation
130
- }
131
- workflow {
132
- states
133
- actions {
134
- label
135
- handler
136
- requiredFields
137
- allowedStates
138
- confirm
139
- args
140
- }
141
- }
142
- inherits
143
- }
144
- }
145
- `);
72
+ const result = await this.query(GET_ALL_META_QUERY);
146
73
  for (const meta of result.stonecropAllMeta) {
147
74
  this.metaCache.set(meta.name, meta);
148
75
  }
@@ -221,15 +148,7 @@ export class StonecropClient {
221
148
  * @param args - Action arguments
222
149
  */
223
150
  async runAction(doctype, action, args) {
224
- const result = await this.query(`
225
- mutation RunAction($doctype: String!, $action: String!, $args: JSON) {
226
- stonecropAction(doctype: $doctype, action: $action, args: $args) {
227
- success
228
- data
229
- error
230
- }
231
- }
232
- `, {
151
+ const result = await this.query(RUN_ACTION_MUTATION, {
233
152
  doctype: doctype.name,
234
153
  action,
235
154
  args,
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * @public
11
11
  */
12
- export declare const GET_META_QUERY = "\n\tquery GetMeta($doctype: String!) {\n\t\tstonecropMeta(doctype: $doctype) {\n\t\t\tname\n\t\t\tslug\n\t\t\tfields {\n\t\t\t\tfieldname\n\t\t\t\tfieldtype\n\t\t\t\tcomponent\n\t\t\t\tlabel\n\t\t\t\twidth\n\t\t\t\talign\n\t\t\t\trequired\n\t\t\t\treadOnly\n\t\t\t\tedit\n\t\t\t\thidden\n\t\t\t\tdefault\n\t\t\t\toptions\n\t\t\t\tmask\n\t\t\t\tprecision\n\t\t\t\tscale\n\t\t\t\tmode\n\t\t\t\tvalidation\n\t\t\t}\n\t\t\tworkflow {\n\t\t\t\tstates\n\t\t\t\tactions {\n\t\t\t\t\tlabel\n\t\t\t\t\trequiredFields\n\t\t\t\t\tallowedStates\n\t\t\t\t}\n\t\t\t}\n\t\t\tinherits\n\t\t}\n\t}\n";
12
+ export declare const GET_META_QUERY = "\n\tquery GetMeta($doctype: String!) {\n\t\tstonecropMeta(doctype: $doctype) {\n\t\t\tname\n\t\t\tslug\n\t\t\tfields {\n\t\t\t\tkind\n\t\t\t\tfieldname\n\t\t\t\tcomponent\n\t\t\t\tdoctype\n\t\t\t\tlabel\n\t\t\t\twidth\n\t\t\t\talign\n\t\t\t\tedit\n\t\t\t\tmask\n\t\t\t\tformat\n\t\t\t\tmode\n\t\t\t\toptions\n\t\t\t\trequired\n\t\t\t\treadOnly\n\t\t\t\thidden\n\t\t\t\tdefault\n\t\t\t\tvalidation\n\t\t\t\tcardinality\n\t\t\t\tsource\n\t\t\t}\n\t\t\tworkflow {\n\t\t\t\tstates\n\t\t\t\tactions {\n\t\t\t\t\tlabel\n\t\t\t\t\trequiredFields\n\t\t\t\t\tallowedStates\n\t\t\t\t}\n\t\t\t}\n\t\t\tinherits\n\t\t}\n\t}\n";
13
13
  /**
14
14
  * Mutation document for dispatching a workflow action (the server-owned transition).
15
15
  * @public
@@ -19,5 +19,5 @@ export declare const RUN_ACTION_MUTATION = "\n\tmutation RunAction($doctype: Str
19
19
  * Query document for fetching all doctype metadata.
20
20
  * @public
21
21
  */
22
- export declare const GET_ALL_META_QUERY = "\n\tquery GetAllMeta {\n\t\tstonecropAllMeta {\n\t\t\tname\n\t\t\tslug\n\t\t\tfields {\n\t\t\t\tfieldname\n\t\t\t\tfieldtype\n\t\t\t\tcomponent\n\t\t\t\tlabel\n\t\t\t\twidth\n\t\t\t\talign\n\t\t\t\trequired\n\t\t\t\treadOnly\n\t\t\t\tedit\n\t\t\t\thidden\n\t\t\t\tdefault\n\t\t\t\toptions\n\t\t\t\tmask\n\t\t\t\tprecision\n\t\t\t\tscale\n\t\t\t\tmode\n\t\t\t\tvalidation\n\t\t\t}\n\t\t\tworkflow {\n\t\t\t\tstates\n\t\t\t\tactions {\n\t\t\t\t\tlabel\n\t\t\t\t\trequiredFields\n\t\t\t\t\tallowedStates\n\t\t\t\t}\n\t\t\t}\n\t\t\tinherits\n\t\t}\n\t}\n";
22
+ export declare const GET_ALL_META_QUERY = "\n\tquery GetAllMeta {\n\t\tstonecropAllMeta {\n\t\t\tname\n\t\t\tslug\n\t\t\tfields {\n\t\t\t\tkind\n\t\t\t\tfieldname\n\t\t\t\tcomponent\n\t\t\t\tdoctype\n\t\t\t\tlabel\n\t\t\t\twidth\n\t\t\t\talign\n\t\t\t\tedit\n\t\t\t\tmask\n\t\t\t\tformat\n\t\t\t\tmode\n\t\t\t\toptions\n\t\t\t\trequired\n\t\t\t\treadOnly\n\t\t\t\thidden\n\t\t\t\tdefault\n\t\t\t\tvalidation\n\t\t\t\tcardinality\n\t\t\t\tsource\n\t\t\t}\n\t\t\tworkflow {\n\t\t\t\tstates\n\t\t\t\tactions {\n\t\t\t\t\tlabel\n\t\t\t\t\trequiredFields\n\t\t\t\t\tallowedStates\n\t\t\t\t}\n\t\t\t}\n\t\t\tinherits\n\t\t}\n\t}\n";
23
23
  //# sourceMappingURL=queries.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,2kBAmC1B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,6MAQ/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,2iBAmC9B,CAAA"}
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,0mBAqC1B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,6MAQ/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,0kBAqC9B,CAAA"}
@@ -15,23 +15,25 @@ export const GET_META_QUERY = `
15
15
  name
16
16
  slug
17
17
  fields {
18
+ kind
18
19
  fieldname
19
- fieldtype
20
20
  component
21
+ doctype
21
22
  label
22
23
  width
23
24
  align
25
+ edit
26
+ mask
27
+ format
28
+ mode
29
+ options
24
30
  required
25
31
  readOnly
26
- edit
27
32
  hidden
28
33
  default
29
- options
30
- mask
31
- precision
32
- scale
33
- mode
34
34
  validation
35
+ cardinality
36
+ source
35
37
  }
36
38
  workflow {
37
39
  states
@@ -68,23 +70,25 @@ export const GET_ALL_META_QUERY = `
68
70
  name
69
71
  slug
70
72
  fields {
73
+ kind
71
74
  fieldname
72
- fieldtype
73
75
  component
76
+ doctype
74
77
  label
75
78
  width
76
79
  align
80
+ edit
81
+ mask
82
+ format
83
+ mode
84
+ options
77
85
  required
78
86
  readOnly
79
- edit
80
87
  hidden
81
88
  default
82
- options
83
- mask
84
- precision
85
- scale
86
- mode
87
89
  validation
90
+ cardinality
91
+ source
88
92
  }
89
93
  workflow {
90
94
  states
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/graphql-client",
3
- "version": "0.13.14",
3
+ "version": "0.14.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": {
@@ -32,8 +32,8 @@
32
32
  "dependencies": {
33
33
  "graphql": "^16.14.0",
34
34
  "pluralize": "^8.0.0",
35
- "@stonecrop/schema": "0.13.14",
36
- "@stonecrop/stonecrop": "0.13.14"
35
+ "@stonecrop/schema": "0.14.0",
36
+ "@stonecrop/stonecrop": "0.14.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@microsoft/api-documenter": "^7.30.5",
@@ -51,7 +51,8 @@
51
51
  "vitest": "^4.1.5",
52
52
  "vue": "^3.5.33",
53
53
  "vue-router": "^5.0.6",
54
- "stonecrop-rig": "0.7.0"
54
+ "stonecrop-rig": "0.7.0",
55
+ "@stonecrop/graphql-middleware": "0.14.0"
55
56
  },
56
57
  "publishConfig": {
57
58
  "access": "public"
package/src/client.ts CHANGED
@@ -7,6 +7,7 @@ import type {
7
7
  GetRecordsOptions,
8
8
  } from '@stonecrop/schema'
9
9
  import type { GetRecordResult } from './types'
10
+ import { GET_META_QUERY, GET_ALL_META_QUERY, RUN_ACTION_MUTATION } from './queries'
10
11
 
11
12
  export type { DoctypeContext, DoctypeRef }
12
13
  export type { GetRecordResult }
@@ -88,48 +89,9 @@ export class StonecropClient implements DataClient {
88
89
  const cached = this.metaCache.get(context.doctype)
89
90
  if (cached) return cached
90
91
 
91
- const result = await this.query<{ stonecropMeta: DoctypeMeta | null }>(
92
- `
93
- query GetMeta($doctype: String!) {
94
- stonecropMeta(doctype: $doctype) {
95
- name
96
- slug
97
- fields {
98
- fieldname
99
- fieldtype
100
- component
101
- label
102
- width
103
- align
104
- required
105
- readOnly
106
- edit
107
- hidden
108
- default
109
- options
110
- mask
111
- precision
112
- scale
113
- mode
114
- validation
115
- }
116
- workflow {
117
- states
118
- actions {
119
- label
120
- handler
121
- requiredFields
122
- allowedStates
123
- confirm
124
- args
125
- }
126
- }
127
- inherits
128
- }
129
- }
130
- `,
131
- { doctype: context.doctype }
132
- )
92
+ const result = await this.query<{ stonecropMeta: DoctypeMeta | null }>(GET_META_QUERY, {
93
+ doctype: context.doctype,
94
+ })
133
95
 
134
96
  if (result.stonecropMeta) {
135
97
  this.metaCache.set(context.doctype, result.stonecropMeta)
@@ -142,47 +104,7 @@ export class StonecropClient implements DataClient {
142
104
  * Get all doctype metadata
143
105
  */
144
106
  async getAllMeta(): Promise<DoctypeMeta[]> {
145
- const result = await this.query<{ stonecropAllMeta: DoctypeMeta[] }>(
146
- `
147
- query GetAllMeta {
148
- stonecropAllMeta {
149
- name
150
- slug
151
- fields {
152
- fieldname
153
- fieldtype
154
- component
155
- label
156
- width
157
- align
158
- required
159
- readOnly
160
- edit
161
- hidden
162
- default
163
- options
164
- mask
165
- precision
166
- scale
167
- mode
168
- validation
169
- }
170
- workflow {
171
- states
172
- actions {
173
- label
174
- handler
175
- requiredFields
176
- allowedStates
177
- confirm
178
- args
179
- }
180
- }
181
- inherits
182
- }
183
- }
184
- `
185
- )
107
+ const result = await this.query<{ stonecropAllMeta: DoctypeMeta[] }>(GET_ALL_META_QUERY)
186
108
 
187
109
  for (const meta of result.stonecropAllMeta) {
188
110
  this.metaCache.set(meta.name, meta)
@@ -284,22 +206,11 @@ export class StonecropClient implements DataClient {
284
206
  ): Promise<{ success: boolean; data: unknown; error: string | null }> {
285
207
  const result = await this.query<{
286
208
  stonecropAction: { success: boolean; data: unknown; error: string | null }
287
- }>(
288
- `
289
- mutation RunAction($doctype: String!, $action: String!, $args: JSON) {
290
- stonecropAction(doctype: $doctype, action: $action, args: $args) {
291
- success
292
- data
293
- error
294
- }
295
- }
296
- `,
297
- {
298
- doctype: doctype.name,
299
- action,
300
- args,
301
- }
302
- )
209
+ }>(RUN_ACTION_MUTATION, {
210
+ doctype: doctype.name,
211
+ action,
212
+ args,
213
+ })
303
214
 
304
215
  return result.stonecropAction
305
216
  }
package/src/queries.ts ADDED
@@ -0,0 +1,106 @@
1
+ /**
2
+ * GraphQL query documents sent by {@link StonecropClient} to the middleware.
3
+ *
4
+ * These are the client's half of the wire contract with `@stonecrop/graphql-middleware`.
5
+ * They live here as exported constants (rather than inline in the client methods) so the
6
+ * cross-package contract test can validate the exact strings the client sends against the
7
+ * middleware's published SDL — a field the server drops while a query still selects it must
8
+ * fail CI, not production.
9
+ *
10
+ * @public
11
+ */
12
+ export const GET_META_QUERY = `
13
+ query GetMeta($doctype: String!) {
14
+ stonecropMeta(doctype: $doctype) {
15
+ name
16
+ slug
17
+ fields {
18
+ kind
19
+ fieldname
20
+ component
21
+ doctype
22
+ label
23
+ width
24
+ align
25
+ edit
26
+ mask
27
+ format
28
+ mode
29
+ options
30
+ required
31
+ readOnly
32
+ hidden
33
+ default
34
+ validation
35
+ cardinality
36
+ source
37
+ }
38
+ workflow {
39
+ states
40
+ actions {
41
+ label
42
+ requiredFields
43
+ allowedStates
44
+ }
45
+ }
46
+ inherits
47
+ }
48
+ }
49
+ `
50
+
51
+ /**
52
+ * Mutation document for dispatching a workflow action (the server-owned transition).
53
+ * @public
54
+ */
55
+ export const RUN_ACTION_MUTATION = `
56
+ mutation RunAction($doctype: String!, $action: String!, $args: JSON) {
57
+ stonecropAction(doctype: $doctype, action: $action, args: $args) {
58
+ success
59
+ data
60
+ error
61
+ }
62
+ }
63
+ `
64
+
65
+ /**
66
+ * Query document for fetching all doctype metadata.
67
+ * @public
68
+ */
69
+ export const GET_ALL_META_QUERY = `
70
+ query GetAllMeta {
71
+ stonecropAllMeta {
72
+ name
73
+ slug
74
+ fields {
75
+ kind
76
+ fieldname
77
+ component
78
+ doctype
79
+ label
80
+ width
81
+ align
82
+ edit
83
+ mask
84
+ format
85
+ mode
86
+ options
87
+ required
88
+ readOnly
89
+ hidden
90
+ default
91
+ validation
92
+ cardinality
93
+ source
94
+ }
95
+ workflow {
96
+ states
97
+ actions {
98
+ label
99
+ requiredFields
100
+ allowedStates
101
+ }
102
+ }
103
+ inherits
104
+ }
105
+ }
106
+ `