@stonecrop/graphql-client 0.8.9 → 0.8.11

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/index.js CHANGED
@@ -58,3 +58,4 @@ const methods = {
58
58
  },
59
59
  };
60
60
  export { queries, typeDefs, methods };
61
+ export { StonecropClient } from './client';
@@ -0,0 +1,76 @@
1
+ import type { DoctypeMeta, RouteContext } from '@stonecrop/schema';
2
+ export type { RouteContext };
3
+ /**
4
+ * Options for creating a Stonecrop client
5
+ * @public
6
+ */
7
+ export interface StonecropClientOptions {
8
+ /** GraphQL endpoint URL */
9
+ endpoint: string;
10
+ /** Additional HTTP headers to include in requests */
11
+ headers?: Record<string, string>;
12
+ }
13
+ /**
14
+ * Client for interacting with Stonecrop GraphQL API
15
+ * @public
16
+ */
17
+ export declare class StonecropClient {
18
+ private endpoint;
19
+ private headers;
20
+ private metaCache;
21
+ constructor(options: StonecropClientOptions);
22
+ /**
23
+ * Execute a GraphQL query
24
+ * @param query - GraphQL query string
25
+ * @param variables - Query variables
26
+ */
27
+ query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T>;
28
+ /**
29
+ * Execute a GraphQL mutation
30
+ * @param mutation - GraphQL mutation string
31
+ * @param variables - Mutation variables
32
+ */
33
+ mutate<T = unknown>(mutation: string, variables?: Record<string, unknown>): Promise<T>;
34
+ /**
35
+ * Get doctype metadata
36
+ * @param context - Route context containing doctype name
37
+ */
38
+ getMeta(context: RouteContext): Promise<DoctypeMeta | null>;
39
+ /**
40
+ * Get all doctype metadata
41
+ */
42
+ getAllMeta(): Promise<DoctypeMeta[]>;
43
+ /**
44
+ * Get a single record by ID
45
+ * @param doctype - Doctype metadata
46
+ * @param recordId - Record ID to fetch
47
+ */
48
+ getRecord(doctype: DoctypeMeta, recordId: string): Promise<Record<string, unknown> | null>;
49
+ /**
50
+ * Get multiple records with optional filtering and pagination
51
+ * @param doctype - Doctype metadata
52
+ * @param options - Query options (filters, orderBy, limit, offset)
53
+ */
54
+ getRecords(doctype: DoctypeMeta, options?: {
55
+ filters?: Record<string, unknown>;
56
+ orderBy?: string;
57
+ limit?: number;
58
+ offset?: number;
59
+ }): Promise<Record<string, unknown>[]>;
60
+ /**
61
+ * Execute a doctype action
62
+ * @param doctype - Doctype metadata
63
+ * @param action - Action name to execute
64
+ * @param args - Action arguments
65
+ */
66
+ runAction(doctype: DoctypeMeta, action: string, args?: unknown[]): Promise<{
67
+ success: boolean;
68
+ data: unknown;
69
+ error: string | null;
70
+ }>;
71
+ /**
72
+ * Clear the cached doctype metadata
73
+ */
74
+ clearMetaCache(): void;
75
+ }
76
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAElE,YAAY,EAAE,YAAY,EAAE,CAAA;AAE5B;;;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;;;GAGG;AACH,qBAAa,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,SAAS,CAAsC;gBAE3C,OAAO,EAAE,sBAAsB;IAQ3C;;;;OAIG;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;IAmBxF;;;;OAIG;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,YAAY,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IA0CjE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAsC1C;;;;OAIG;IACG,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAiBhG;;;;OAIG;IACG,UAAU,CACf,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjC,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;KACf,GACC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAiCrC;;;;;OAKG;IACG,SAAS,CACd,OAAO,EAAE,WAAW,EACpB,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;;OAEG;IACH,cAAc,IAAI,IAAI;CAGtB"}
@@ -11,6 +11,9 @@ import type { MetaResponse } from './types';
11
11
  declare const methods: {
12
12
  getMeta: (doctype: string, url?: string) => Promise<MetaResponse>;
13
13
  };
14
- export type { Meta, MetaParser, MetaResponse } from './types';
15
14
  export { queries, typeDefs, methods };
15
+ export { StonecropClient } from './client';
16
+ export type { StonecropClientOptions, RouteContext } from './client';
17
+ export type { Meta, MetaParser, MetaResponse } from './types';
18
+ export type { DoctypeMeta } from '@stonecrop/schema';
16
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,QAAQ,MAAM,cAAc,CAAA;AACnC,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,SAAS,CAAA;AAkC7D;;;;;;GAMG;AACH,QAAA,MAAM,OAAO;uBACa,MAAM,QAAQ,MAAM,KAAG,OAAO,CAAC,YAAY,CAAC;CAgBrE,CAAA;AAED,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,QAAQ,MAAM,cAAc,CAAA;AACnC,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,SAAS,CAAA;AAkC7D;;;;;;GAMG;AACH,QAAA,MAAM,OAAO;uBACa,MAAM,QAAQ,MAAM,KAAG,OAAO,CAAC,YAAY,CAAC;CAgBrE,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,YAAY,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACpE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC7D,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/graphql-client",
3
- "version": "0.8.9",
3
+ "version": "0.8.11",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": {
@@ -37,7 +37,8 @@
37
37
  "decimal.js": "^10.6.0",
38
38
  "graphql": "^16.12.0",
39
39
  "graphql-request": "^7.4.0",
40
- "@stonecrop/stonecrop": "0.8.9"
40
+ "@stonecrop/schema": "0.8.11",
41
+ "@stonecrop/stonecrop": "0.8.11"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@eslint/js": "^9.39.2",
@@ -45,6 +46,7 @@
45
46
  "@miragejs/graphql": "^0.1.13",
46
47
  "@rushstack/heft": "^1.2.0",
47
48
  "@vitejs/plugin-vue": "^6.0.3",
49
+ "@vitest/coverage-istanbul": "^4.0.18",
48
50
  "eslint": "^9.39.2",
49
51
  "eslint-config-prettier": "^10.1.8",
50
52
  "eslint-plugin-vue": "^10.6.2",
@@ -53,6 +55,7 @@
53
55
  "typescript": "^5.9.3",
54
56
  "typescript-eslint": "^8.53.0",
55
57
  "vite": "^7.3.1",
58
+ "vitest": "^4.0.18",
56
59
  "vue": "^3.5.28",
57
60
  "vue-router": "^5.0.2",
58
61
  "stonecrop-rig": "0.7.0"
@@ -70,6 +73,9 @@
70
73
  "dev": "vite",
71
74
  "docs": "bash ../common/scripts/run-docs.sh graphql_client",
72
75
  "lint": "eslint .",
73
- "preview": "vite preview"
76
+ "preview": "vite preview",
77
+ "test": "vitest run --coverage.enabled false",
78
+ "test:watch": "vitest watch",
79
+ "test:coverage": "vitest run --coverage"
74
80
  }
75
81
  }
package/src/client.ts ADDED
@@ -0,0 +1,260 @@
1
+ import type { DoctypeMeta, RouteContext } from '@stonecrop/schema'
2
+
3
+ export type { RouteContext }
4
+
5
+ /**
6
+ * Options for creating a Stonecrop client
7
+ * @public
8
+ */
9
+ export interface StonecropClientOptions {
10
+ /** GraphQL endpoint URL */
11
+ endpoint: string
12
+ /** Additional HTTP headers to include in requests */
13
+ headers?: Record<string, string>
14
+ }
15
+
16
+ /**
17
+ * Client for interacting with Stonecrop GraphQL API
18
+ * @public
19
+ */
20
+ export class StonecropClient {
21
+ private endpoint: string
22
+ private headers: Record<string, string>
23
+ private metaCache: Map<string, DoctypeMeta> = new Map()
24
+
25
+ constructor(options: StonecropClientOptions) {
26
+ this.endpoint = options.endpoint
27
+ this.headers = {
28
+ 'Content-Type': 'application/json',
29
+ ...options.headers,
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Execute a GraphQL query
35
+ * @param query - GraphQL query string
36
+ * @param variables - Query variables
37
+ */
38
+ async query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T> {
39
+ const response = await fetch(this.endpoint, {
40
+ method: 'POST',
41
+ headers: this.headers,
42
+ body: JSON.stringify({ query, variables }),
43
+ })
44
+
45
+ const json = (await response.json()) as {
46
+ data?: T
47
+ errors?: Array<{ message: string }>
48
+ }
49
+
50
+ if (json.errors?.length) {
51
+ throw new Error(json.errors[0].message)
52
+ }
53
+
54
+ return json.data as T
55
+ }
56
+
57
+ /**
58
+ * Execute a GraphQL mutation
59
+ * @param mutation - GraphQL mutation string
60
+ * @param variables - Mutation variables
61
+ */
62
+ async mutate<T = unknown>(mutation: string, variables?: Record<string, unknown>): Promise<T> {
63
+ return this.query<T>(mutation, variables)
64
+ }
65
+
66
+ /**
67
+ * Get doctype metadata
68
+ * @param context - Route context containing doctype name
69
+ */
70
+ async getMeta(context: RouteContext): Promise<DoctypeMeta | null> {
71
+ const cached = this.metaCache.get(context.doctype)
72
+ if (cached) return cached
73
+
74
+ const result = await this.query<{ stonecropMeta: DoctypeMeta | null }>(
75
+ `
76
+ query GetMeta($doctype: String!) {
77
+ stonecropMeta(doctype: $doctype) {
78
+ name
79
+ slug
80
+ tableName
81
+ fields {
82
+ fieldname
83
+ fieldtype
84
+ component
85
+ label
86
+ required
87
+ readOnly
88
+ options
89
+ precision
90
+ scale
91
+ }
92
+ workflow {
93
+ states
94
+ actions
95
+ }
96
+ inherits
97
+ listDoctype
98
+ parentDoctype
99
+ }
100
+ }
101
+ `,
102
+ { doctype: context.doctype }
103
+ )
104
+
105
+ if (result.stonecropMeta) {
106
+ this.metaCache.set(context.doctype, result.stonecropMeta)
107
+ }
108
+
109
+ return result.stonecropMeta
110
+ }
111
+
112
+ /**
113
+ * Get all doctype metadata
114
+ */
115
+ async getAllMeta(): Promise<DoctypeMeta[]> {
116
+ const result = await this.query<{ stonecropAllMeta: DoctypeMeta[] }>(
117
+ `
118
+ query GetAllMeta {
119
+ stonecropAllMeta {
120
+ name
121
+ slug
122
+ tableName
123
+ fields {
124
+ fieldname
125
+ fieldtype
126
+ component
127
+ label
128
+ required
129
+ readOnly
130
+ options
131
+ precision
132
+ scale
133
+ }
134
+ workflow {
135
+ states
136
+ actions
137
+ }
138
+ inherits
139
+ listDoctype
140
+ parentDoctype
141
+ }
142
+ }
143
+ `
144
+ )
145
+
146
+ for (const meta of result.stonecropAllMeta) {
147
+ this.metaCache.set(meta.name, meta)
148
+ }
149
+
150
+ return result.stonecropAllMeta
151
+ }
152
+
153
+ /**
154
+ * Get a single record by ID
155
+ * @param doctype - Doctype metadata
156
+ * @param recordId - Record ID to fetch
157
+ */
158
+ async getRecord(doctype: DoctypeMeta, recordId: string): Promise<Record<string, unknown> | null> {
159
+ const result = await this.query<{
160
+ stonecropRecord: { data: Record<string, unknown> | null }
161
+ }>(
162
+ `
163
+ query GetRecord($doctype: String!, $id: String!) {
164
+ stonecropRecord(doctype: $doctype, id: $id) {
165
+ data
166
+ }
167
+ }
168
+ `,
169
+ { doctype: doctype.name, id: recordId }
170
+ )
171
+
172
+ return result.stonecropRecord.data
173
+ }
174
+
175
+ /**
176
+ * Get multiple records with optional filtering and pagination
177
+ * @param doctype - Doctype metadata
178
+ * @param options - Query options (filters, orderBy, limit, offset)
179
+ */
180
+ async getRecords(
181
+ doctype: DoctypeMeta,
182
+ options?: {
183
+ filters?: Record<string, unknown>
184
+ orderBy?: string
185
+ limit?: number
186
+ offset?: number
187
+ }
188
+ ): Promise<Record<string, unknown>[]> {
189
+ const result = await this.query<{
190
+ stonecropRecords: { data: Record<string, unknown>[] }
191
+ }>(
192
+ `
193
+ query GetRecords(
194
+ $doctype: String!
195
+ $filters: JSON
196
+ $orderBy: String
197
+ $limit: Int
198
+ $offset: Int
199
+ ) {
200
+ stonecropRecords(
201
+ doctype: $doctype
202
+ filters: $filters
203
+ orderBy: $orderBy
204
+ limit: $limit
205
+ offset: $offset
206
+ ) {
207
+ data
208
+ count
209
+ }
210
+ }
211
+ `,
212
+ {
213
+ doctype: doctype.name,
214
+ ...options,
215
+ }
216
+ )
217
+
218
+ return result.stonecropRecords.data
219
+ }
220
+
221
+ /**
222
+ * Execute a doctype action
223
+ * @param doctype - Doctype metadata
224
+ * @param action - Action name to execute
225
+ * @param args - Action arguments
226
+ */
227
+ async runAction(
228
+ doctype: DoctypeMeta,
229
+ action: string,
230
+ args?: unknown[]
231
+ ): Promise<{ success: boolean; data: unknown; error: string | null }> {
232
+ const result = await this.query<{
233
+ stonecropAction: { success: boolean; data: unknown; error: string | null }
234
+ }>(
235
+ `
236
+ mutation RunAction($doctype: String!, $action: String!, $args: JSON) {
237
+ stonecropAction(doctype: $doctype, action: $action, args: $args) {
238
+ success
239
+ data
240
+ error
241
+ }
242
+ }
243
+ `,
244
+ {
245
+ doctype: doctype.name,
246
+ action,
247
+ args,
248
+ }
249
+ )
250
+
251
+ return result.stonecropAction
252
+ }
253
+
254
+ /**
255
+ * Clear the cached doctype metadata
256
+ */
257
+ clearMetaCache(): void {
258
+ this.metaCache.clear()
259
+ }
260
+ }
package/src/index.ts CHANGED
@@ -63,5 +63,8 @@ const methods = {
63
63
  },
64
64
  }
65
65
 
66
- export type { Meta, MetaParser, MetaResponse } from './types'
67
66
  export { queries, typeDefs, methods }
67
+ export { StonecropClient } from './client'
68
+ export type { StonecropClientOptions, RouteContext } from './client'
69
+ export type { Meta, MetaParser, MetaResponse } from './types'
70
+ export type { DoctypeMeta } from '@stonecrop/schema'