@stonecrop/graphql-client 0.31.0 → 0.33.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/graphql-client.js +168 -136
- package/dist/graphql-client.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/package.json +30 -26
- package/dist/graphql_client.tsbuildinfo +0 -1
- package/dist/src/client.d.ts +0 -91
- package/dist/src/client.d.ts.map +0 -1
- package/dist/src/client.js +0 -172
- package/dist/src/index.d.ts +0 -4
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -1
- package/dist/src/queries.d.ts +0 -23
- package/dist/src/queries.d.ts.map +0 -1
- package/dist/src/queries.js +0 -122
- package/dist/src/types/index.d.ts +0 -14
- package/dist/src/types/index.d.ts.map +0 -1
- package/dist/src/types/index.js +0 -4
- package/src/client.ts +0 -233
- package/src/index.ts +0 -4
- package/src/queries.ts +0 -124
- package/src/types/index.ts +0 -15
package/dist/src/client.js
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { GET_META_QUERY, GET_ALL_META_QUERY, RUN_ACTION_MUTATION } from './queries';
|
|
2
|
-
/**
|
|
3
|
-
* Client for interacting with Stonecrop GraphQL API.
|
|
4
|
-
*
|
|
5
|
-
* Acts as a transport layer for stonecropRecord/stonecropRecords/stonecropAction.
|
|
6
|
-
*
|
|
7
|
-
* @public
|
|
8
|
-
*/
|
|
9
|
-
export class StonecropClient {
|
|
10
|
-
endpoint;
|
|
11
|
-
headers;
|
|
12
|
-
metaCache = new Map();
|
|
13
|
-
constructor(options) {
|
|
14
|
-
this.endpoint = options.endpoint;
|
|
15
|
-
this.headers = {
|
|
16
|
-
'Content-Type': 'application/json',
|
|
17
|
-
...options.headers,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Execute a GraphQL query against the configured endpoint.
|
|
22
|
-
*
|
|
23
|
-
* @param query - GraphQL query string
|
|
24
|
-
* @param variables - Query variables
|
|
25
|
-
* @throws Error if the GraphQL response contains errors
|
|
26
|
-
*/
|
|
27
|
-
async query(query, variables) {
|
|
28
|
-
const response = await fetch(this.endpoint, {
|
|
29
|
-
method: 'POST',
|
|
30
|
-
headers: this.headers,
|
|
31
|
-
body: JSON.stringify({ query, variables }),
|
|
32
|
-
});
|
|
33
|
-
const json = await response.json();
|
|
34
|
-
if (json.errors?.length) {
|
|
35
|
-
throw new Error(json.errors[0].message);
|
|
36
|
-
}
|
|
37
|
-
if (json.data === undefined) {
|
|
38
|
-
throw new Error('GraphQL response missing data field');
|
|
39
|
-
}
|
|
40
|
-
return json.data;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Execute a GraphQL mutation. Delegates to query() since both use POST.
|
|
44
|
-
*
|
|
45
|
-
* @param mutation - GraphQL mutation string
|
|
46
|
-
* @param variables - Mutation variables
|
|
47
|
-
*/
|
|
48
|
-
async mutate(mutation, variables) {
|
|
49
|
-
return this.query(mutation, variables);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Get doctype metadata
|
|
53
|
-
* @param context - Doctype context containing doctype name
|
|
54
|
-
*/
|
|
55
|
-
async getMeta(context) {
|
|
56
|
-
const cached = this.metaCache.get(context.doctype);
|
|
57
|
-
if (cached)
|
|
58
|
-
return cached;
|
|
59
|
-
const result = await this.query(GET_META_QUERY, {
|
|
60
|
-
doctype: context.doctype,
|
|
61
|
-
});
|
|
62
|
-
if (result.stonecropMeta) {
|
|
63
|
-
this.metaCache.set(context.doctype, result.stonecropMeta);
|
|
64
|
-
}
|
|
65
|
-
return result.stonecropMeta;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Get all doctype metadata
|
|
69
|
-
*/
|
|
70
|
-
async getAllMeta() {
|
|
71
|
-
const result = await this.query(GET_ALL_META_QUERY);
|
|
72
|
-
for (const meta of result.stonecropAllMeta) {
|
|
73
|
-
this.metaCache.set(meta.name, meta);
|
|
74
|
-
}
|
|
75
|
-
return result.stonecropAllMeta;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Get a single record by ID.
|
|
79
|
-
*
|
|
80
|
-
* Routes through the stonecropRecord resolver which handles nested data
|
|
81
|
-
* fetching based on the includeNested option.
|
|
82
|
-
*
|
|
83
|
-
* @param doctype - Doctype reference (name and optional slug)
|
|
84
|
-
* @param recordId - Record ID to fetch
|
|
85
|
-
* @param options - Query options (includeNested, maxDepth)
|
|
86
|
-
*/
|
|
87
|
-
async getRecord(doctype, recordId, options) {
|
|
88
|
-
const result = await this.query(`query GetRecord($doctype: String!, $id: String!, $options: JSON) {
|
|
89
|
-
stonecropRecord(doctype: $doctype, id: $id, options: $options) {
|
|
90
|
-
data
|
|
91
|
-
unknownLinks
|
|
92
|
-
}
|
|
93
|
-
}`, {
|
|
94
|
-
doctype: doctype.name,
|
|
95
|
-
id: recordId,
|
|
96
|
-
options: options?.includeNested
|
|
97
|
-
? {
|
|
98
|
-
includeNested: options.includeNested,
|
|
99
|
-
maxDepth: options.maxDepth,
|
|
100
|
-
}
|
|
101
|
-
: undefined,
|
|
102
|
-
});
|
|
103
|
-
return {
|
|
104
|
-
record: result.stonecropRecord?.data ?? null,
|
|
105
|
-
unknownLinks: result.stonecropRecord?.unknownLinks,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Get multiple records with optional filtering and pagination.
|
|
110
|
-
*
|
|
111
|
-
* Returns flat arrays — the middleware merges connection format (\{ nodes: [...] \})
|
|
112
|
-
* into plain arrays before returning.
|
|
113
|
-
*
|
|
114
|
-
* @param doctype - Doctype reference (name and optional slug)
|
|
115
|
-
* @param options - Query options (filters, orderBy, limit, offset)
|
|
116
|
-
*/
|
|
117
|
-
async getRecords(doctype, options) {
|
|
118
|
-
const result = await this.query(`
|
|
119
|
-
query GetRecords(
|
|
120
|
-
$doctype: String!
|
|
121
|
-
$filters: JSON
|
|
122
|
-
$orderBy: String
|
|
123
|
-
$limit: Int
|
|
124
|
-
$offset: Int
|
|
125
|
-
$includeTotal: Boolean
|
|
126
|
-
) {
|
|
127
|
-
stonecropRecords(
|
|
128
|
-
doctype: $doctype
|
|
129
|
-
filters: $filters
|
|
130
|
-
orderBy: $orderBy
|
|
131
|
-
limit: $limit
|
|
132
|
-
offset: $offset
|
|
133
|
-
includeTotal: $includeTotal
|
|
134
|
-
) {
|
|
135
|
-
data
|
|
136
|
-
hasMore
|
|
137
|
-
count
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
`, {
|
|
141
|
-
doctype: doctype.name,
|
|
142
|
-
...options,
|
|
143
|
-
});
|
|
144
|
-
const { data, hasMore, count } = result.stonecropRecords;
|
|
145
|
-
// `count` is null unless includeTotal was set. Omitting the key rather than passing null
|
|
146
|
-
// through keeps "not asked for" and "asked for, and it is zero" distinguishable.
|
|
147
|
-
return count == null ? { data, hasMore } : { data, hasMore, count };
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Execute a doctype action
|
|
151
|
-
* @param doctype - Doctype reference (name and optional slug)
|
|
152
|
-
* @param action - Action name to execute
|
|
153
|
-
* @param args - Action arguments
|
|
154
|
-
*/
|
|
155
|
-
async runAction(doctype, action, args) {
|
|
156
|
-
const result = await this.query(RUN_ACTION_MUTATION, {
|
|
157
|
-
doctype: doctype.name,
|
|
158
|
-
action,
|
|
159
|
-
args,
|
|
160
|
-
});
|
|
161
|
-
return result.stonecropAction;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Clear the cached doctype metadata.
|
|
165
|
-
*
|
|
166
|
-
* Call this if the server-side doctype schema has changed and you need
|
|
167
|
-
* to fetch fresh metadata (e.g., after adding a new field).
|
|
168
|
-
*/
|
|
169
|
-
clearMetaCache() {
|
|
170
|
-
this.metaCache.clear();
|
|
171
|
-
}
|
|
172
|
-
}
|
package/dist/src/index.d.ts
DELETED
package/dist/src/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAC5F,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA"}
|
package/dist/src/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { StonecropClient } from './client';
|
package/dist/src/queries.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
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 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\tdisplayField\n\t\t\tfields {\n\t\t\t\tkind\n\t\t\t\tfieldname\n\t\t\t\tcomponent\n\t\t\t\tprimaryKey\n\t\t\t\tcomputed\n\t\t\t\tlanguage\n\t\t\t\tdoctype\n\t\t\t\tlabel\n\t\t\t\twidth\n\t\t\t\theight\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\tnextState\n\t\t\t\t\tstateless\n\t\t\t\t\tselfTransition\n\t\t\t\t\tclientHandler\n\t\t\t\t}\n\t\t\t}\n\t\t\tinherits\n\t\t}\n\t}\n";
|
|
13
|
-
/**
|
|
14
|
-
* Mutation document for dispatching a workflow action (the server-owned transition).
|
|
15
|
-
* @public
|
|
16
|
-
*/
|
|
17
|
-
export declare 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";
|
|
18
|
-
/**
|
|
19
|
-
* Query document for fetching all doctype metadata.
|
|
20
|
-
* @public
|
|
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\tdisplayField\n\t\t\tfields {\n\t\t\t\tkind\n\t\t\t\tfieldname\n\t\t\t\tcomponent\n\t\t\t\tprimaryKey\n\t\t\t\tcomputed\n\t\t\t\tlanguage\n\t\t\t\tdoctype\n\t\t\t\tlabel\n\t\t\t\twidth\n\t\t\t\theight\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\tnextState\n\t\t\t\t\tstateless\n\t\t\t\t\tselfTransition\n\t\t\t\t\tclientHandler\n\t\t\t\t}\n\t\t\t}\n\t\t\tinherits\n\t\t}\n\t}\n";
|
|
23
|
-
//# sourceMappingURL=queries.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,myBA8C1B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,6MAQ/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,mwBA8C9B,CAAA"}
|
package/dist/src/queries.js
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
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
|
-
displayField
|
|
18
|
-
fields {
|
|
19
|
-
kind
|
|
20
|
-
fieldname
|
|
21
|
-
component
|
|
22
|
-
primaryKey
|
|
23
|
-
computed
|
|
24
|
-
language
|
|
25
|
-
doctype
|
|
26
|
-
label
|
|
27
|
-
width
|
|
28
|
-
height
|
|
29
|
-
align
|
|
30
|
-
edit
|
|
31
|
-
mask
|
|
32
|
-
format
|
|
33
|
-
mode
|
|
34
|
-
options
|
|
35
|
-
required
|
|
36
|
-
readOnly
|
|
37
|
-
hidden
|
|
38
|
-
default
|
|
39
|
-
validation
|
|
40
|
-
cardinality
|
|
41
|
-
source
|
|
42
|
-
}
|
|
43
|
-
workflow {
|
|
44
|
-
states
|
|
45
|
-
actions {
|
|
46
|
-
label
|
|
47
|
-
requiredFields
|
|
48
|
-
allowedStates
|
|
49
|
-
nextState
|
|
50
|
-
stateless
|
|
51
|
-
selfTransition
|
|
52
|
-
clientHandler
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
inherits
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
`;
|
|
59
|
-
/**
|
|
60
|
-
* Mutation document for dispatching a workflow action (the server-owned transition).
|
|
61
|
-
* @public
|
|
62
|
-
*/
|
|
63
|
-
export const RUN_ACTION_MUTATION = `
|
|
64
|
-
mutation RunAction($doctype: String!, $action: String!, $args: JSON) {
|
|
65
|
-
stonecropAction(doctype: $doctype, action: $action, args: $args) {
|
|
66
|
-
success
|
|
67
|
-
data
|
|
68
|
-
error
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
`;
|
|
72
|
-
/**
|
|
73
|
-
* Query document for fetching all doctype metadata.
|
|
74
|
-
* @public
|
|
75
|
-
*/
|
|
76
|
-
export const GET_ALL_META_QUERY = `
|
|
77
|
-
query GetAllMeta {
|
|
78
|
-
stonecropAllMeta {
|
|
79
|
-
name
|
|
80
|
-
slug
|
|
81
|
-
displayField
|
|
82
|
-
fields {
|
|
83
|
-
kind
|
|
84
|
-
fieldname
|
|
85
|
-
component
|
|
86
|
-
primaryKey
|
|
87
|
-
computed
|
|
88
|
-
language
|
|
89
|
-
doctype
|
|
90
|
-
label
|
|
91
|
-
width
|
|
92
|
-
height
|
|
93
|
-
align
|
|
94
|
-
edit
|
|
95
|
-
mask
|
|
96
|
-
format
|
|
97
|
-
mode
|
|
98
|
-
options
|
|
99
|
-
required
|
|
100
|
-
readOnly
|
|
101
|
-
hidden
|
|
102
|
-
default
|
|
103
|
-
validation
|
|
104
|
-
cardinality
|
|
105
|
-
source
|
|
106
|
-
}
|
|
107
|
-
workflow {
|
|
108
|
-
states
|
|
109
|
-
actions {
|
|
110
|
-
label
|
|
111
|
-
requiredFields
|
|
112
|
-
allowedStates
|
|
113
|
-
nextState
|
|
114
|
-
stateless
|
|
115
|
-
selfTransition
|
|
116
|
-
clientHandler
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
inherits
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
`;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Types for the GraphQL client.
|
|
3
|
-
* @public
|
|
4
|
-
*/
|
|
5
|
-
import type { GetRecordResult as SchemaGetRecordResult } from '@stonecrop/schema';
|
|
6
|
-
/**
|
|
7
|
-
* Result from getRecord - includes the record data and any unknown links requested
|
|
8
|
-
* @public
|
|
9
|
-
*/
|
|
10
|
-
export interface GetRecordResult extends SchemaGetRecordResult {
|
|
11
|
-
/** Link names that were requested but don't exist in the doctype schema */
|
|
12
|
-
unknownLinks?: string[];
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,IAAI,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAEjF;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,qBAAqB;IAC7D,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB"}
|
package/dist/src/types/index.js
DELETED
package/src/client.ts
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
DataClient,
|
|
3
|
-
DoctypeMeta,
|
|
4
|
-
DoctypeContext,
|
|
5
|
-
DoctypeRef,
|
|
6
|
-
GetRecordOptions,
|
|
7
|
-
GetRecordsOptions,
|
|
8
|
-
GetRecordsResult,
|
|
9
|
-
} from '@stonecrop/schema'
|
|
10
|
-
import type { GetRecordResult } from './types'
|
|
11
|
-
import { GET_META_QUERY, GET_ALL_META_QUERY, RUN_ACTION_MUTATION } from './queries'
|
|
12
|
-
|
|
13
|
-
export type { DoctypeContext, DoctypeRef }
|
|
14
|
-
export type { GetRecordResult, GetRecordsResult }
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Options for creating a Stonecrop client
|
|
18
|
-
* @public
|
|
19
|
-
*/
|
|
20
|
-
export interface StonecropClientOptions {
|
|
21
|
-
/** GraphQL endpoint URL */
|
|
22
|
-
endpoint: string
|
|
23
|
-
/** Additional HTTP headers to include in requests */
|
|
24
|
-
headers?: Record<string, string>
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Client for interacting with Stonecrop GraphQL API.
|
|
29
|
-
*
|
|
30
|
-
* Acts as a transport layer for stonecropRecord/stonecropRecords/stonecropAction.
|
|
31
|
-
*
|
|
32
|
-
* @public
|
|
33
|
-
*/
|
|
34
|
-
export class StonecropClient implements DataClient {
|
|
35
|
-
private endpoint: string
|
|
36
|
-
private headers: Record<string, string>
|
|
37
|
-
private metaCache: Map<string, DoctypeMeta> = new Map()
|
|
38
|
-
|
|
39
|
-
constructor(options: StonecropClientOptions) {
|
|
40
|
-
this.endpoint = options.endpoint
|
|
41
|
-
this.headers = {
|
|
42
|
-
'Content-Type': 'application/json',
|
|
43
|
-
...options.headers,
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Execute a GraphQL query against the configured endpoint.
|
|
49
|
-
*
|
|
50
|
-
* @param query - GraphQL query string
|
|
51
|
-
* @param variables - Query variables
|
|
52
|
-
* @throws Error if the GraphQL response contains errors
|
|
53
|
-
*/
|
|
54
|
-
async query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T> {
|
|
55
|
-
const response = await fetch(this.endpoint, {
|
|
56
|
-
method: 'POST',
|
|
57
|
-
headers: this.headers,
|
|
58
|
-
body: JSON.stringify({ query, variables }),
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
const json: { data?: T; errors?: Array<{ message: string }> } = await response.json()
|
|
62
|
-
|
|
63
|
-
if (json.errors?.length) {
|
|
64
|
-
throw new Error(json.errors[0].message)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (json.data === undefined) {
|
|
68
|
-
throw new Error('GraphQL response missing data field')
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return json.data
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Execute a GraphQL mutation. Delegates to query() since both use POST.
|
|
76
|
-
*
|
|
77
|
-
* @param mutation - GraphQL mutation string
|
|
78
|
-
* @param variables - Mutation variables
|
|
79
|
-
*/
|
|
80
|
-
async mutate<T = unknown>(mutation: string, variables?: Record<string, unknown>): Promise<T> {
|
|
81
|
-
return this.query<T>(mutation, variables)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Get doctype metadata
|
|
86
|
-
* @param context - Doctype context containing doctype name
|
|
87
|
-
*/
|
|
88
|
-
async getMeta(context: DoctypeContext): Promise<DoctypeMeta | null> {
|
|
89
|
-
const cached = this.metaCache.get(context.doctype)
|
|
90
|
-
if (cached) return cached
|
|
91
|
-
|
|
92
|
-
const result = await this.query<{ stonecropMeta: DoctypeMeta | null }>(GET_META_QUERY, {
|
|
93
|
-
doctype: context.doctype,
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
if (result.stonecropMeta) {
|
|
97
|
-
this.metaCache.set(context.doctype, result.stonecropMeta)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return result.stonecropMeta
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Get all doctype metadata
|
|
105
|
-
*/
|
|
106
|
-
async getAllMeta(): Promise<DoctypeMeta[]> {
|
|
107
|
-
const result = await this.query<{ stonecropAllMeta: DoctypeMeta[] }>(GET_ALL_META_QUERY)
|
|
108
|
-
|
|
109
|
-
for (const meta of result.stonecropAllMeta) {
|
|
110
|
-
this.metaCache.set(meta.name, meta)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return result.stonecropAllMeta
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Get a single record by ID.
|
|
118
|
-
*
|
|
119
|
-
* Routes through the stonecropRecord resolver which handles nested data
|
|
120
|
-
* fetching based on the includeNested option.
|
|
121
|
-
*
|
|
122
|
-
* @param doctype - Doctype reference (name and optional slug)
|
|
123
|
-
* @param recordId - Record ID to fetch
|
|
124
|
-
* @param options - Query options (includeNested, maxDepth)
|
|
125
|
-
*/
|
|
126
|
-
async getRecord(doctype: DoctypeRef, recordId: string, options?: GetRecordOptions): Promise<GetRecordResult> {
|
|
127
|
-
const result = await this.query<{
|
|
128
|
-
stonecropRecord: { data: Record<string, unknown> | null; unknownLinks?: string[] }
|
|
129
|
-
}>(
|
|
130
|
-
`query GetRecord($doctype: String!, $id: String!, $options: JSON) {
|
|
131
|
-
stonecropRecord(doctype: $doctype, id: $id, options: $options) {
|
|
132
|
-
data
|
|
133
|
-
unknownLinks
|
|
134
|
-
}
|
|
135
|
-
}`,
|
|
136
|
-
{
|
|
137
|
-
doctype: doctype.name,
|
|
138
|
-
id: recordId,
|
|
139
|
-
options: options?.includeNested
|
|
140
|
-
? {
|
|
141
|
-
includeNested: options.includeNested,
|
|
142
|
-
maxDepth: options.maxDepth,
|
|
143
|
-
}
|
|
144
|
-
: undefined,
|
|
145
|
-
}
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
return {
|
|
149
|
-
record: result.stonecropRecord?.data ?? null,
|
|
150
|
-
unknownLinks: result.stonecropRecord?.unknownLinks,
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Get multiple records with optional filtering and pagination.
|
|
156
|
-
*
|
|
157
|
-
* Returns flat arrays — the middleware merges connection format (\{ nodes: [...] \})
|
|
158
|
-
* into plain arrays before returning.
|
|
159
|
-
*
|
|
160
|
-
* @param doctype - Doctype reference (name and optional slug)
|
|
161
|
-
* @param options - Query options (filters, orderBy, limit, offset)
|
|
162
|
-
*/
|
|
163
|
-
async getRecords(doctype: DoctypeRef, options?: GetRecordsOptions): Promise<GetRecordsResult> {
|
|
164
|
-
const result = await this.query<{
|
|
165
|
-
stonecropRecords: { data: Record<string, unknown>[]; hasMore: boolean; count: number | null }
|
|
166
|
-
}>(
|
|
167
|
-
`
|
|
168
|
-
query GetRecords(
|
|
169
|
-
$doctype: String!
|
|
170
|
-
$filters: JSON
|
|
171
|
-
$orderBy: String
|
|
172
|
-
$limit: Int
|
|
173
|
-
$offset: Int
|
|
174
|
-
$includeTotal: Boolean
|
|
175
|
-
) {
|
|
176
|
-
stonecropRecords(
|
|
177
|
-
doctype: $doctype
|
|
178
|
-
filters: $filters
|
|
179
|
-
orderBy: $orderBy
|
|
180
|
-
limit: $limit
|
|
181
|
-
offset: $offset
|
|
182
|
-
includeTotal: $includeTotal
|
|
183
|
-
) {
|
|
184
|
-
data
|
|
185
|
-
hasMore
|
|
186
|
-
count
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
`,
|
|
190
|
-
{
|
|
191
|
-
doctype: doctype.name,
|
|
192
|
-
...options,
|
|
193
|
-
}
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
const { data, hasMore, count } = result.stonecropRecords
|
|
197
|
-
// `count` is null unless includeTotal was set. Omitting the key rather than passing null
|
|
198
|
-
// through keeps "not asked for" and "asked for, and it is zero" distinguishable.
|
|
199
|
-
return count == null ? { data, hasMore } : { data, hasMore, count }
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Execute a doctype action
|
|
204
|
-
* @param doctype - Doctype reference (name and optional slug)
|
|
205
|
-
* @param action - Action name to execute
|
|
206
|
-
* @param args - Action arguments
|
|
207
|
-
*/
|
|
208
|
-
async runAction(
|
|
209
|
-
doctype: DoctypeRef,
|
|
210
|
-
action: string,
|
|
211
|
-
args?: unknown[]
|
|
212
|
-
): Promise<{ success: boolean; data: unknown; error: string | null }> {
|
|
213
|
-
const result = await this.query<{
|
|
214
|
-
stonecropAction: { success: boolean; data: unknown; error: string | null }
|
|
215
|
-
}>(RUN_ACTION_MUTATION, {
|
|
216
|
-
doctype: doctype.name,
|
|
217
|
-
action,
|
|
218
|
-
args,
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
return result.stonecropAction
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Clear the cached doctype metadata.
|
|
226
|
-
*
|
|
227
|
-
* Call this if the server-side doctype schema has changed and you need
|
|
228
|
-
* to fetch fresh metadata (e.g., after adding a new field).
|
|
229
|
-
*/
|
|
230
|
-
clearMetaCache(): void {
|
|
231
|
-
this.metaCache.clear()
|
|
232
|
-
}
|
|
233
|
-
}
|
package/src/index.ts
DELETED