@webda/graphql 4.0.0-beta.6 → 4.0.0-beta.8
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 +5 -4
- package/lib/graphql.service.d.ts +109 -3
- package/lib/graphql.service.d.ts.map +1 -1
- package/lib/graphql.service.js +347 -48
- package/lib/graphql.service.js.map +1 -1
- package/lib/mutations.d.ts +8 -0
- package/lib/mutations.d.ts.map +1 -1
- package/lib/mutations.js +27 -0
- package/lib/mutations.js.map +1 -1
- package/lib/names.d.ts +31 -0
- package/lib/names.d.ts.map +1 -0
- package/lib/names.js +78 -0
- package/lib/names.js.map +1 -0
- package/lib/operations.d.ts +110 -0
- package/lib/operations.d.ts.map +1 -0
- package/lib/operations.js +221 -0
- package/lib/operations.js.map +1 -0
- package/lib/types/any.d.ts.map +1 -1
- package/lib/types/any.js +27 -19
- package/lib/types/any.js.map +1 -1
- package/lib/types/date.d.ts.map +1 -1
- package/lib/types/date.js +4 -2
- package/lib/types/date.js.map +1 -1
- package/package.json +11 -6
- package/webda.module.json +10 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { AsyncQueue, HttpContext, Session, StreamingOperationContext, WebdaError, getOperationStreaming, toPublicChunk } from "@webda/core";
|
|
2
|
+
import { operationError } from "./mutations.js";
|
|
3
|
+
/** Operations the model schema already serves (X, Xs, createX, updateX, deleteX) */
|
|
4
|
+
export const CRUD_METHODS = new Set([
|
|
5
|
+
"modelCreate",
|
|
6
|
+
"modelUpdate",
|
|
7
|
+
"modelPatch",
|
|
8
|
+
"modelDelete",
|
|
9
|
+
"modelGet",
|
|
10
|
+
"modelQuery"
|
|
11
|
+
]);
|
|
12
|
+
/** A valid GraphQL name */
|
|
13
|
+
export const GRAPHQL_NAME = /^[_A-Za-z][_0-9A-Za-z]*$/;
|
|
14
|
+
/** Streamed chunks waiting for the subscriber above which the operation waits */
|
|
15
|
+
const HIGH_WATER = 16;
|
|
16
|
+
/**
|
|
17
|
+
* @param id - operation id
|
|
18
|
+
* @returns its PascalCase name without dots (`TaskService.Summary` → `TaskServiceSummary`)
|
|
19
|
+
*/
|
|
20
|
+
export function operationTypeName(id) {
|
|
21
|
+
return id
|
|
22
|
+
.split(".")
|
|
23
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
|
|
24
|
+
.join("");
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @param id - operation id
|
|
28
|
+
* @returns its GraphQL field name (`TaskService.Summary` → `taskServiceSummary`)
|
|
29
|
+
*/
|
|
30
|
+
export function operationFieldName(id) {
|
|
31
|
+
const name = operationTypeName(id);
|
|
32
|
+
return name.charAt(0).toLowerCase() + name.slice(1);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @param op - operation
|
|
36
|
+
* @returns true when it only reads (REST GET, or MCP readOnly)
|
|
37
|
+
*/
|
|
38
|
+
export function isReadOnlyOperation(op) {
|
|
39
|
+
return ((typeof op.rest === "object" && op.rest?.method?.toLowerCase() === "get") ||
|
|
40
|
+
(typeof op.mcp === "object" && op.mcp?.readOnly === true));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Where an operation is exposed in GraphQL
|
|
44
|
+
* @param id - operation id
|
|
45
|
+
* @param op - operation
|
|
46
|
+
* @returns its placement, undefined when GraphQL does not expose it
|
|
47
|
+
* @throws Error when an explicit placement does not match the streaming mode
|
|
48
|
+
*/
|
|
49
|
+
export function graphqlPlacement(id, op) {
|
|
50
|
+
if (op.hidden || op.graphql === false || CRUD_METHODS.has(op.method)) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const streaming = getOperationStreaming(op);
|
|
54
|
+
if (streaming === "client" || streaming === "bidi") {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
const explicit = typeof op.graphql === "object" ? op.graphql : undefined;
|
|
58
|
+
const forced = explicit?.subscription
|
|
59
|
+
? { kind: "subscription", name: explicit.subscription }
|
|
60
|
+
: explicit?.query
|
|
61
|
+
? { kind: "query", name: explicit.query }
|
|
62
|
+
: explicit?.mutation
|
|
63
|
+
? { kind: "mutation", name: explicit.mutation }
|
|
64
|
+
: undefined;
|
|
65
|
+
if (forced && (forced.kind === "subscription") !== (streaming === "server")) {
|
|
66
|
+
throw new Error(`Operation ${id}: graphql.${forced.kind} does not match its streaming mode (${streaming}); a server-streaming operation is a subscription, the others a query or a mutation`);
|
|
67
|
+
}
|
|
68
|
+
if (forced) {
|
|
69
|
+
return forced;
|
|
70
|
+
}
|
|
71
|
+
if (streaming === "server") {
|
|
72
|
+
return { kind: "subscription", name: operationFieldName(id) };
|
|
73
|
+
}
|
|
74
|
+
return { kind: isReadOnlyOperation(op) ? "query" : "mutation", name: operationFieldName(id) };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A value as clients may see it: plain JSON without `__` keys
|
|
78
|
+
* @param value - an operation result or chunk
|
|
79
|
+
* @returns the copy (null for undefined)
|
|
80
|
+
*/
|
|
81
|
+
export function publicCopy(value) {
|
|
82
|
+
return value === undefined ? null : toPublicChunk(value);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The context of an operation called from GraphQL: the GraphQL request's session and headers, the field arguments as
|
|
86
|
+
* input; a non-streamed result is kept as is (`result`), streamed chunks are queued for the subscription.
|
|
87
|
+
*/
|
|
88
|
+
export class GraphQLOperationContext extends StreamingOperationContext {
|
|
89
|
+
/**
|
|
90
|
+
* @param parent - the GraphQL request context
|
|
91
|
+
* @param input - the operation input (from the field arguments)
|
|
92
|
+
* @param transform - turns a streamed chunk into what the subscriber receives
|
|
93
|
+
*/
|
|
94
|
+
constructor(parent, input, transform = publicCopy) {
|
|
95
|
+
super(parent.getHttpContext?.() ?? new HttpContext("localhost", "POST", "/graphql"));
|
|
96
|
+
this.transform = transform;
|
|
97
|
+
this.queue = new AsyncQueue();
|
|
98
|
+
this.pending = 0;
|
|
99
|
+
this.wakers = [];
|
|
100
|
+
this.finished = false;
|
|
101
|
+
this.setSession(parent.getSession() ?? new Session());
|
|
102
|
+
this.message = Buffer.from(input === undefined ? "" : JSON.stringify(input));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The session comes from the GraphQL request, already loaded
|
|
106
|
+
* @override
|
|
107
|
+
*/
|
|
108
|
+
async init(_force = false) {
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* @override
|
|
113
|
+
*/
|
|
114
|
+
async getRawInput(limit = 10 * 1024 * 1024, _timeout = 60000) {
|
|
115
|
+
return this.message.subarray(0, limit);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @override
|
|
119
|
+
*/
|
|
120
|
+
async getRawInputAsString(limit = 10 * 1024 * 1024, _timeout = 60000, encoding) {
|
|
121
|
+
return this.message.subarray(0, limit).toString(encoding || "utf8");
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* No connection: the subscriber leaving is signalled by cancel()
|
|
125
|
+
* @override
|
|
126
|
+
*/
|
|
127
|
+
get connectionEnded() {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* A non-streamed result is kept as is
|
|
132
|
+
* @override
|
|
133
|
+
*/
|
|
134
|
+
writeResult(output) {
|
|
135
|
+
this.result = output;
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Streamed chunks are queued for the subscriber
|
|
140
|
+
* @override
|
|
141
|
+
* @throws OperationCancelledError when the stream is over
|
|
142
|
+
*/
|
|
143
|
+
sendChunk(chunk) {
|
|
144
|
+
if (this.finished)
|
|
145
|
+
throw new WebdaError.OperationCancelledError();
|
|
146
|
+
this.queue.push(this.transform(chunk));
|
|
147
|
+
this.pending++;
|
|
148
|
+
return this.pending < HIGH_WATER;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Wait for the subscriber to consume the queued chunks (or to leave)
|
|
152
|
+
* @override
|
|
153
|
+
*/
|
|
154
|
+
async waitForDrain() {
|
|
155
|
+
while (!this.isCancelled && this.pending >= HIGH_WATER) {
|
|
156
|
+
await new Promise(resolve => this.wakers.push(resolve));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** The subscriber left: the next write or drain throws, the iterator ends. */
|
|
160
|
+
cancel() {
|
|
161
|
+
super.cancel();
|
|
162
|
+
this.queue.end(true);
|
|
163
|
+
this.wake();
|
|
164
|
+
}
|
|
165
|
+
/** The operation completed. */
|
|
166
|
+
finish() {
|
|
167
|
+
this.finished = true;
|
|
168
|
+
this.queue.end();
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* The operation failed: the subscriber gets the error after the chunks already queued, unless it already left
|
|
172
|
+
* @param error - what the operation threw (mapped like a query error: unexpected ones are hidden)
|
|
173
|
+
*/
|
|
174
|
+
fail(error) {
|
|
175
|
+
this.finished = true;
|
|
176
|
+
if (this.isCancelled && error instanceof WebdaError.OperationCancelledError) {
|
|
177
|
+
// The expected end of an operation whose subscriber left
|
|
178
|
+
this.queue.end();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// Any other error is mapped (and logged when unexpected) even if nobody listens anymore
|
|
182
|
+
const mapped = operationError(error);
|
|
183
|
+
if (!this.isCancelled) {
|
|
184
|
+
this.failure = mapped;
|
|
185
|
+
}
|
|
186
|
+
this.queue.end();
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* @returns the chunks, for a subscription field (return() cancels the operation)
|
|
190
|
+
*/
|
|
191
|
+
chunks() {
|
|
192
|
+
const iterator = {
|
|
193
|
+
next: async () => {
|
|
194
|
+
const item = await this.queue.next();
|
|
195
|
+
if (item.done) {
|
|
196
|
+
if (this.failure !== undefined) {
|
|
197
|
+
const failure = this.failure;
|
|
198
|
+
this.failure = undefined;
|
|
199
|
+
throw failure;
|
|
200
|
+
}
|
|
201
|
+
return item;
|
|
202
|
+
}
|
|
203
|
+
this.pending--;
|
|
204
|
+
this.wake();
|
|
205
|
+
return item;
|
|
206
|
+
},
|
|
207
|
+
return: async () => {
|
|
208
|
+
this.cancel();
|
|
209
|
+
return { value: undefined, done: true };
|
|
210
|
+
},
|
|
211
|
+
[Symbol.asyncIterator]: () => iterator
|
|
212
|
+
};
|
|
213
|
+
return iterator;
|
|
214
|
+
}
|
|
215
|
+
/** Lets a waiting drained() check again */
|
|
216
|
+
wake() {
|
|
217
|
+
for (const waker of this.wakers.splice(0))
|
|
218
|
+
waker();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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"}
|
package/lib/types/any.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"any.d.ts","sourceRoot":"","sources":["../../src/types/any.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"any.d.ts","sourceRoot":"","sources":["../../src/types/any.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA6B,MAAM,SAAS,CAAC;AA4BvE,eAAO,MAAM,aAAa,6BAOxB,CAAC"}
|
package/lib/types/any.js
CHANGED
|
@@ -1,26 +1,34 @@
|
|
|
1
|
-
import { GraphQLScalarType, Kind } from "graphql";
|
|
1
|
+
import { GraphQLScalarType, Kind, valueFromASTUntyped } from "graphql";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* @param value -
|
|
5
|
-
* @returns parsed
|
|
3
|
+
* Read a string as JSON when it looks like a JSON object or array
|
|
4
|
+
* @param value - the string
|
|
5
|
+
* @returns the parsed value, or the string itself
|
|
6
6
|
*/
|
|
7
|
-
function
|
|
8
|
-
|
|
7
|
+
function fromJSONString(value) {
|
|
8
|
+
const text = value.trim();
|
|
9
|
+
if (!text.startsWith("{") && !text.startsWith("[")) {
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(text);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Values pass through unchanged (objects, arrays, numbers, booleans, strings)
|
|
21
|
+
* @param value - value to pass
|
|
22
|
+
* @returns the value, null for undefined
|
|
23
|
+
*/
|
|
24
|
+
function passThrough(value) {
|
|
25
|
+
return value === undefined ? null : value;
|
|
9
26
|
}
|
|
10
27
|
export const AnyScalarType = new GraphQLScalarType({
|
|
11
28
|
name: "Object",
|
|
12
|
-
description: "Arbitrary object",
|
|
13
|
-
parseValue:
|
|
14
|
-
serialize:
|
|
15
|
-
parseLiteral: ast =>
|
|
16
|
-
switch (ast.kind) {
|
|
17
|
-
case Kind.STRING:
|
|
18
|
-
return JSON.parse(ast.value);
|
|
19
|
-
case Kind.OBJECT:
|
|
20
|
-
throw new Error(`Not sure what to do with OBJECT for ObjectScalarType`);
|
|
21
|
-
default:
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
29
|
+
description: "Arbitrary value: object, array, number, boolean or string",
|
|
30
|
+
parseValue: passThrough,
|
|
31
|
+
serialize: passThrough,
|
|
32
|
+
parseLiteral: (ast, variables) => ast.kind === Kind.STRING ? fromJSONString(ast.value) : valueFromASTUntyped(ast, variables)
|
|
25
33
|
});
|
|
26
34
|
//# sourceMappingURL=any.js.map
|
package/lib/types/any.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"any.js","sourceRoot":"","sources":["../../src/types/any.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"any.js","sourceRoot":"","sources":["../../src/types/any.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEvE;;;;GAIG;AACH,SAAS,cAAc,CAAC,KAAa;IACnC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,KAAU;IAC7B,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,iBAAiB,CAAC;IACjD,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,2DAA2D;IACxE,UAAU,EAAE,WAAW;IACvB,SAAS,EAAE,WAAW;IACtB,YAAY,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAC/B,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,EAAE,SAAS,CAAC;CAC7F,CAAC,CAAC"}
|
package/lib/types/date.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/types/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAQ,MAAM,SAAS,CAAC;AAElD,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/types/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAQ,MAAM,SAAS,CAAC;AAElD,eAAO,MAAM,UAAU,iCAyBrB,CAAC"}
|
package/lib/types/date.js
CHANGED
|
@@ -3,8 +3,10 @@ export const DateScalar = new GraphQLScalarType({
|
|
|
3
3
|
name: "Date",
|
|
4
4
|
description: "Date custom scalar type",
|
|
5
5
|
serialize(value) {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
// Stores serializing to JSON return dates as ISO strings or timestamps
|
|
7
|
+
const date = typeof value === "string" || typeof value === "number" ? new Date(value) : value;
|
|
8
|
+
if (date instanceof Date && !isNaN(date.getTime())) {
|
|
9
|
+
return date.toISOString();
|
|
8
10
|
}
|
|
9
11
|
throw Error("GraphQL Date Scalar serializer expected a `Date` object");
|
|
10
12
|
},
|
package/lib/types/date.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/types/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC;IAC9C,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,yBAAyB;IACtC,SAAS,CAAC,KAAK;QACb,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/types/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC;IAC9C,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,yBAAyB;IACtC,SAAS,CAAC,KAAK;QACb,uEAAuE;QACvE,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC9F,IAAI,IAAI,YAAY,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YACnD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5B,CAAC;QACD,MAAM,KAAK,CAAC,yDAAyD,CAAC,CAAC;IACzE,CAAC;IACD,UAAU,CAAC,KAAK;QACd,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,mCAAmC;QAC7D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IACD,YAAY,CAAC,GAAG;QACd,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YAC7B,4DAA4D;YAC5D,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QACD,4CAA4C;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webda/graphql",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.8",
|
|
4
4
|
"description": "GraphQL endpoint for your Webda Application",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -18,12 +18,15 @@
|
|
|
18
18
|
"graphql-ws": "^6.0.8",
|
|
19
19
|
"json-schema": "^0.4.0",
|
|
20
20
|
"ws": "^8.20.0",
|
|
21
|
-
"@webda/
|
|
22
|
-
"@webda/
|
|
23
|
-
"@webda/
|
|
21
|
+
"@webda/core": "4.0.0-beta.8",
|
|
22
|
+
"@webda/utils": "4.0.0-beta.8",
|
|
23
|
+
"@webda/workout": "4.0.0-beta.5",
|
|
24
|
+
"@webda/runtime": "4.0.0-beta.8",
|
|
25
|
+
"@webda/ql": "4.0.0-beta.7"
|
|
24
26
|
},
|
|
25
27
|
"devDependencies": {
|
|
26
28
|
"@types/node": "25.5.0",
|
|
29
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
27
30
|
"c8": "^11.0.0",
|
|
28
31
|
"glob": "^13.0.6",
|
|
29
32
|
"js-beautify": "^1.15.4",
|
|
@@ -32,7 +35,9 @@
|
|
|
32
35
|
"skott": "^0.35.8",
|
|
33
36
|
"source-map-support": "^0.5.21",
|
|
34
37
|
"vite": "^6.0.0",
|
|
35
|
-
"
|
|
38
|
+
"vitest": "^4.0.0",
|
|
39
|
+
"@webda/compiler": "^4.0.0-beta.8",
|
|
40
|
+
"@webda/test": "^4.0.0-beta.7"
|
|
36
41
|
},
|
|
37
42
|
"webda": {
|
|
38
43
|
"namespace": "Webda"
|
|
@@ -59,7 +64,7 @@
|
|
|
59
64
|
"scripts": {
|
|
60
65
|
"build": "webdac build",
|
|
61
66
|
"pretest": "npm run build",
|
|
62
|
-
"test": "
|
|
67
|
+
"test": "vitest run",
|
|
63
68
|
"new-model": "webda init webda:model",
|
|
64
69
|
"new-service": "webda init webda:service",
|
|
65
70
|
"lint": "eslint",
|
package/webda.module.json
CHANGED
|
@@ -20,6 +20,16 @@
|
|
|
20
20
|
"description": "Expose current user in the context with me",
|
|
21
21
|
"type": "boolean"
|
|
22
22
|
},
|
|
23
|
+
"exposeOperations": {
|
|
24
|
+
"default": [
|
|
25
|
+
"*"
|
|
26
|
+
],
|
|
27
|
+
"description": "Operations exposed as GraphQL fields next to the model schema, with the operation transports' patterns:\n`\"*\"`, `\"Service.*\"`, an exact id, `\"!Id\"` to exclude; `[]` exposes no operation",
|
|
28
|
+
"items": {
|
|
29
|
+
"type": "string"
|
|
30
|
+
},
|
|
31
|
+
"type": "array"
|
|
32
|
+
},
|
|
23
33
|
"globalSubscription": {
|
|
24
34
|
"default": false,
|
|
25
35
|
"description": "Expose a aggregation of all available subscriptions",
|