@m1212e/rumble 0.27.0 → 0.27.4
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 +94 -70
- package/out/client/generate.cjs +1 -1
- package/out/client/generate.d.cts +0 -2
- package/out/client/generate.d.cts.map +1 -1
- package/out/client/generate.d.mts +0 -2
- package/out/client/generate.d.mts.map +1 -1
- package/out/client/generate.mjs +1 -2
- package/out/client.cjs +7 -14
- package/out/client.cjs.map +1 -1
- package/out/client.d.cts +19 -28
- package/out/client.d.cts.map +1 -1
- package/out/client.d.mts +19 -28
- package/out/client.d.mts.map +1 -1
- package/out/client.mjs +7 -14
- package/out/client.mjs.map +1 -1
- package/out/{generate-D0CKBths.cjs → generate-Btr_u0Lr.cjs} +4 -7
- package/out/{generate-D0CKBths.cjs.map → generate-Btr_u0Lr.cjs.map} +1 -1
- package/out/{generate-BySnFVve.mjs → generate-Dzf2klR2.mjs} +4 -7
- package/out/{generate-BySnFVve.mjs.map → generate-Dzf2klR2.mjs.map} +1 -1
- package/out/index.cjs +250 -171
- package/out/index.cjs.map +1 -1
- package/out/index.d.cts +56 -300
- package/out/index.d.cts.map +1 -1
- package/out/index.d.mts +59 -303
- package/out/index.d.mts.map +1 -1
- package/out/index.mjs +252 -173
- package/out/index.mjs.map +1 -1
- package/package.json +15 -12
package/README.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# rumble
|
|
2
|
+
|
|
2
3
|
rumble is a combined ability and graphql builder built around [drizzle](https://orm.drizzle.team/docs/overview) and [pothos](https://pothos-graphql.dev/docs/plugins/drizzle), inspired by [CASL](https://casl.js.org/v6/en/). It takes much of the required configuration off your shoulders and makes creating a GraphQL (or event REST via [SOFA](https://the-guild.dev/graphql/sofa-api)) api very easy! Additionally it offers strong support for real time data via GraphQL subscriptions!
|
|
3
4
|
|
|
4
5
|
> Please note that drizzle hasn't reached a full stable release yet and, as shown in the warning [here](https://pothos-graphql.dev/docs/plugins/drizzle), this is not stable yet.
|
|
@@ -10,6 +11,7 @@ rumble is a combined ability and graphql builder built around [drizzle](https://
|
|
|
10
11
|
> Comes with a fully TS based client to consume any GraphQL API. See the client docs at the end to learn about usage with rumble and independent usage with any GraphQL API.
|
|
11
12
|
|
|
12
13
|
## Getting started
|
|
14
|
+
|
|
13
15
|
The following example is an excerpt from the example setup you can find [here](./example). If you are interested in a real world app thats using rumble (and is still work in progress) please see [CHASE](https://github.com/DeutscheModelUnitedNations/munify-chase).
|
|
14
16
|
|
|
15
17
|
First, install rumble into your project:
|
|
@@ -24,8 +26,8 @@ import * as relations from "./db/relations";
|
|
|
24
26
|
import { rumble } from "@m1212e/rumble";
|
|
25
27
|
|
|
26
28
|
export const db = drizzle(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
"postgres://postgres:postgres@localhost:5432/postgres",
|
|
30
|
+
{ schema, relations },
|
|
29
31
|
);
|
|
30
32
|
|
|
31
33
|
const { abilityBuilder } = rumble({ db });
|
|
@@ -35,9 +37,11 @@ const { abilityBuilder } = rumble({ db });
|
|
|
35
37
|
The rumble creator returns some functions which you can use to implement your api. The concepts rumble uses are described in the following sections:
|
|
36
38
|
|
|
37
39
|
## Abilities
|
|
40
|
+
|
|
38
41
|
Abilities are the way you define who can do things in your app. You can imagine an ability as `a thing that is allowed`. Abilities can be very wide and applied in general or precisely and narrowly scoped to very specific conditions. You can create abilities with the `abilityBuilder` function returned from the rumble initiator. There are three kinds of abilities:
|
|
39
42
|
|
|
40
43
|
### Wildcard
|
|
44
|
+
|
|
41
45
|
Wildcard abilities allow everyone to do a thing. The `allow` call takes a single `action` or an array of `action` strings. You can customize the available actions when calling the rumble initializer.
|
|
42
46
|
```ts
|
|
43
47
|
// everyone can read posts
|
|
@@ -48,46 +52,51 @@ abilityBuilder.posts.allow(["read", "write"]);
|
|
|
48
52
|
```
|
|
49
53
|
|
|
50
54
|
### Condition Object
|
|
51
|
-
|
|
55
|
+
|
|
56
|
+
Condition object abilities allow a thing under a certain, fixed condition which does not change. **Note, that the object has the same type as a drizzle query call.**
|
|
52
57
|
```ts
|
|
53
58
|
// everyone can read published posts
|
|
54
59
|
abilityBuilder.posts.allow("read").when({
|
|
55
|
-
|
|
60
|
+
where: { published: true },
|
|
56
61
|
});
|
|
57
62
|
```
|
|
58
63
|
|
|
59
64
|
### Condition Function
|
|
65
|
+
|
|
60
66
|
Condition functions are functions that return condition objects. They are called each time an evaluation takes place and can dynamically decide if something should be allowed or not. They receive the request context as a parameter to decide e.g. based on cookies or headers if something is allowed or not.
|
|
61
67
|
```ts
|
|
62
68
|
// only the author can update posts
|
|
63
69
|
abilityBuilder.posts
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
.allow(["update", "delete"])
|
|
71
|
+
.when(({ userId }) => ({ where: { authorId: userId } }));
|
|
66
72
|
|
|
67
73
|
abilityBuilder.posts.allow("read").when(async ({ userId }) => ({
|
|
68
|
-
|
|
74
|
+
where: { teamId: { in: await permissions.teamsOf(userId) } },
|
|
69
75
|
}));
|
|
70
|
-
|
|
71
76
|
```
|
|
72
77
|
|
|
73
78
|
### Application level filters
|
|
79
|
+
|
|
74
80
|
In some cases you can't implement all your checks via a database query filter. Say, for example, you want to query an external api which handles your authorization, before you return the data to the user. This can be done with application layer filters. They can be set very similar to abilities:
|
|
75
81
|
```ts
|
|
76
82
|
abilityBuilder.users.filter("read").by(({ context, entities }) => {
|
|
77
|
-
|
|
83
|
+
// const allowed = await queryExternalAuthorizationService(context.user, entities);
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
// we could filter the list to only return the entities the user is allowed to see
|
|
86
|
+
// even mapping to prevent leakage of certain fields is possible
|
|
87
|
+
return entities;
|
|
82
88
|
});
|
|
83
89
|
```
|
|
84
90
|
The default implementation helpers automatically respect and call the filters, if you set any. Filters work in addition to abilities. They run on the completed query, which in most cases has had an ability applied, hence abilities have higher priority than filters. If you need to apply a filter to a manually implemented object, please use the `applyFilters` config field as shown in the example project.
|
|
85
91
|
|
|
86
92
|
|
|
87
93
|
### Column masks and filter arguments
|
|
94
|
+
|
|
88
95
|
An ability may grant columns only on the rows its `where` matches. The other rows are returned without them:
|
|
89
96
|
```ts
|
|
90
|
-
abilityBuilder.users
|
|
97
|
+
abilityBuilder.users
|
|
98
|
+
.allow("read")
|
|
99
|
+
.when(({ userId }) => ({ where: { id: userId } })); // everything on the own row
|
|
91
100
|
abilityBuilder.users.allow("read").when({ columns: { id: true, name: true } }); // the rest on any other
|
|
92
101
|
```
|
|
93
102
|
Masking happens after the query ran, but a `where` or `orderBy` argument is applied by the database to the real values: `users(where: { email: { eq: "a@b.c" } })` would reveal whose email that is. The default helpers (`query`, `countQuery` and the generated relations) therefore restrict these arguments to what the caller may read:
|
|
@@ -99,26 +108,28 @@ Masking happens after the query ran, but a `where` or `orderBy` argument is appl
|
|
|
99
108
|
In your own resolvers, pass client arguments through `guardFilterInput(ctx.abilities, table, action, { where, orderBy })` before merging them. Filters you build yourself are not restricted.
|
|
100
109
|
|
|
101
110
|
### Applying abilities
|
|
111
|
+
|
|
102
112
|
As you might have noticed, abilities resolve around drizzle query filters. This means, that we can use them to query the database with filters applied that directly restrict what the user is allowed to see, update and retrieve.
|
|
103
113
|
```ts
|
|
104
114
|
schemaBuilder.queryFields((t) => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
115
|
+
return {
|
|
116
|
+
posts: t.drizzleField({
|
|
117
|
+
type: [PostRef],
|
|
118
|
+
resolve: async (query, root, args, ctx, info) => {
|
|
119
|
+
return db.query.posts.findMany(
|
|
120
|
+
// here we apply our filter (filter() is async, so remember to await it)
|
|
121
|
+
query((await ctx.abilities.posts.filter("read")).query.many),
|
|
122
|
+
);
|
|
123
|
+
},
|
|
124
|
+
}),
|
|
125
|
+
};
|
|
116
126
|
});
|
|
117
127
|
```
|
|
118
128
|
|
|
119
129
|
> The `filter()` call returns an object with `query` and `sql` fields. Depending on if you are using the drizzle query or and SQL based API (like update or delete), you need to apply different filters. Same goes for the `query.many` and `query.single` fields.
|
|
120
130
|
|
|
121
131
|
#### Applying filters
|
|
132
|
+
|
|
122
133
|
Applying filters on objects is done automatically if you use the helpers. If you manually implement an object ref, you can use the `applyFilters` config field to ensure the filters run as expected:
|
|
123
134
|
```ts
|
|
124
135
|
const PostRef = schemaBuilder.drizzleObject("posts", {
|
|
@@ -133,75 +144,80 @@ const PostRef = schemaBuilder.drizzleObject("posts", {
|
|
|
133
144
|
```
|
|
134
145
|
|
|
135
146
|
## Context & Configuration
|
|
147
|
+
|
|
136
148
|
The `rumble` initiator offers various configuration options which you can pass. Most importantly, the `context` provider function which creates the request context that is passed to your abilities and resolvers.
|
|
137
149
|
```ts
|
|
138
150
|
rumble({
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
151
|
+
db,
|
|
152
|
+
context(request) {
|
|
153
|
+
return {
|
|
154
|
+
// here you could instead read some cookies or HTTP headers to retrieve an actual userId
|
|
155
|
+
userId: 2,
|
|
156
|
+
};
|
|
157
|
+
},
|
|
146
158
|
});
|
|
147
159
|
```
|
|
148
160
|
> `rumble` offers more config options, use intellisense or take a look at [the rumble input type](lib/types/rumbleInput.ts) if you want to know more.
|
|
149
161
|
|
|
150
162
|
## Helpers
|
|
163
|
+
|
|
151
164
|
Rumble offers various helpers to make it easy and fast to implement your api. Ofcourse you can write your api by hand using the provided `schemaBuilder` from the rumble initiator, but since this might get repetitive, the provided helpers automate a lot of this work for you while also automatically applying the concepts of rumble directly into your api.
|
|
152
165
|
|
|
153
166
|
### whereArg
|
|
167
|
+
|
|
154
168
|
`whereArg` is a helper to implement query arguments for filtering the results of a query for certain results. In many cases you would implement arguments for a query with something as `matchUsername: t.arg.string()` which is supposed to restrict the query to users which have that username. The whereArg helper implements such a filter tailored to the specific entity which you then can directly pass on to the database query.
|
|
155
169
|
```ts
|
|
156
170
|
const WhereArgs = whereArg({
|
|
157
|
-
|
|
171
|
+
table: "posts",
|
|
158
172
|
});
|
|
159
173
|
|
|
160
174
|
schemaBuilder.queryFields((t) => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
return {
|
|
176
|
+
postsFiltered: t.drizzleField({
|
|
177
|
+
type: [PostRef],
|
|
178
|
+
args: {
|
|
179
|
+
// here we set our generated type as type for the where argument
|
|
180
|
+
where: t.arg({ type: WhereArgs }),
|
|
181
|
+
},
|
|
182
|
+
resolve: async (query, root, args, ctx, info) => {
|
|
183
|
+
return db.query.posts.findMany(
|
|
184
|
+
query(
|
|
185
|
+
// here we apply the ability filter
|
|
186
|
+
(await ctx.abilities.users.filter("read"))
|
|
187
|
+
// we can merge one time filters into the permission filter for this specific request
|
|
188
|
+
.merge({ where: args.where }).query.many,
|
|
189
|
+
),
|
|
190
|
+
);
|
|
191
|
+
},
|
|
192
|
+
}),
|
|
193
|
+
};
|
|
180
194
|
});
|
|
181
195
|
```
|
|
182
196
|
|
|
183
197
|
### object
|
|
198
|
+
|
|
184
199
|
`object` is a helper to implement an object with relations. Don't worry about abilities, they are automatically applied. The helper returns the object reference which you can use in the rest of your api, for an example on how to use a type, see the above code snippet (`type: [PostRef],`).
|
|
185
200
|
```ts
|
|
186
201
|
const UserRef = object({
|
|
187
|
-
|
|
202
|
+
table: "users",
|
|
188
203
|
});
|
|
189
204
|
```
|
|
190
205
|
|
|
191
206
|
### query
|
|
207
|
+
|
|
192
208
|
The `query` helper is even simpler. It implements a `findFirst` and `findMany` query for the specified entity named as singular and plural of the entities name.
|
|
193
209
|
```ts
|
|
194
210
|
query({
|
|
195
|
-
|
|
211
|
+
table: "users",
|
|
196
212
|
});
|
|
197
|
-
|
|
198
213
|
```
|
|
199
214
|
|
|
200
215
|
### pubsub
|
|
216
|
+
|
|
201
217
|
In case you want to use subscriptions, `rumble` has got you covered! The rumble helpers all use the `smart subscriptions plugin` from `pothos`. The `pubsub` helper lets you easily hook into the subscription notification logic.
|
|
202
218
|
```ts
|
|
203
219
|
const { updated, created, removed } = pubsub({
|
|
204
|
-
|
|
220
|
+
table: "users",
|
|
205
221
|
});
|
|
206
222
|
```
|
|
207
223
|
Now just call the functions whenever your application does the respective action and your subscriptions will get notified:
|
|
@@ -223,15 +239,17 @@ All `query` and `object` helper implementations will automatically update and wo
|
|
|
223
239
|
> The rumble initiator lets you configure the subscription notifiers in case you want to use an external service like redis for your pubsub notifications instead of the internal default one
|
|
224
240
|
|
|
225
241
|
### enum_
|
|
242
|
+
|
|
226
243
|
The `enum_` helper is a little different to the others, as it will get called internally automatically if another helpers like `object` or `arg` detects an enum field. In most cases you should be good without calling it manually but in case you would like to have a reference to an enum object, you can get it from this helper.
|
|
227
244
|
```ts
|
|
228
245
|
const enumRef = enum_({
|
|
229
|
-
|
|
246
|
+
tsName: "moodEnum",
|
|
230
247
|
});
|
|
231
248
|
```
|
|
232
249
|
> The enum parameter allows other fields to be used to reference an enum. This is largely due to how this is used internally. Because of the way how drizzle handles enums, we are not able to provide type safety with enums. In case you actually need to use it, the above way is the recommended approach.
|
|
233
250
|
|
|
234
251
|
### Enable search
|
|
252
|
+
|
|
235
253
|
> Search is currently only supported in postgres!
|
|
236
254
|
|
|
237
255
|
rumble and its helpers offer out of the box search capabilities. You can activate this functionality by passing the `search` parameter to the `createRumble` function.
|
|
@@ -258,9 +276,12 @@ This will add a search field to all list queries and many relations created by t
|
|
|
258
276
|
Additionally, a search distance will be returned for each result if the search argument is used (null otherwise). The results are returned sorted by their distance with the best matching fields in the first place. The search will respect all text fields (IDs included) on the table, you always search for all text columns at once. Matches in multiple columns stack and therefore result in a better matching score. So if you search for "alice" and there is a user with the name "Alice" and an email "alice@example.com", the two matching columns will result in a better score than e.g. "al007@example.com"/"Alice".
|
|
259
277
|
> If you have abilities in place which prevent a caller from accessing certain columns, the search will not respect those columns to prevent leaking information.
|
|
260
278
|
#### Pro tip: Indexing
|
|
279
|
+
|
|
261
280
|
In case your table grows large, it can be a good idea to create an index to increase performance. Under the hood, searching uses the [pg_trgm](https://www.postgresql.org/docs/current/pgtrgm.html#PGTRGM-INDEX) extension. To create indexes for our searchable columns, we can adjust our drizzle schema accordingly:
|
|
262
281
|
```ts
|
|
263
|
-
export const user = pgTable(
|
|
282
|
+
export const user = pgTable(
|
|
283
|
+
"user",
|
|
284
|
+
{
|
|
264
285
|
id: text()
|
|
265
286
|
.$defaultFn(() => nanoid())
|
|
266
287
|
.primaryKey(),
|
|
@@ -268,14 +289,14 @@ export const user = pgTable('user', {
|
|
|
268
289
|
name: text().notNull(),
|
|
269
290
|
},
|
|
270
291
|
(table) => [
|
|
271
|
-
index(
|
|
272
|
-
.using(
|
|
292
|
+
index("user_id_trgm")
|
|
293
|
+
.using("gin", sql`${table.id} gin_trgm_ops`)
|
|
273
294
|
.concurrently(),
|
|
274
|
-
index(
|
|
275
|
-
.using(
|
|
295
|
+
index("user_email_trgm")
|
|
296
|
+
.using("gin", sql`${table.email} gin_trgm_ops`)
|
|
276
297
|
.concurrently(),
|
|
277
|
-
index(
|
|
278
|
-
.using(
|
|
298
|
+
index("user_name_trgm")
|
|
299
|
+
.using("gin", sql`${table.name} gin_trgm_ops`)
|
|
279
300
|
.concurrently(),
|
|
280
301
|
],
|
|
281
302
|
);
|
|
@@ -295,23 +316,25 @@ Another important aspect to consider when using indexes is that the PostgreSQL i
|
|
|
295
316
|
Please also note that `GIST` indexes are also supported by `pg_trgm` but will oftentimes not be useable for the sorting since a lot of columns are accumulated in the query which causes the query planner to not use them. Feel free to experiment with different index types and configurations to find the best fit for your specific use case.
|
|
296
317
|
|
|
297
318
|
### and more...
|
|
319
|
+
|
|
298
320
|
See [the example file](./example/src/main.ts) or clone it and let intellisense guide you. Rumble offers various other helpers which might become handy!
|
|
299
321
|
|
|
300
322
|
## Running the server
|
|
323
|
+
|
|
301
324
|
In case you directly want to run a server from your rumble instance, you can do so by using the `createYoga` function. It returns a graphql `yoga` instance which can be used to provide a graphql api in [a multitude of ways](https://the-guild.dev/graphql/yoga-server/docs/integrations/z-other-environments).
|
|
302
325
|
```ts
|
|
303
326
|
import { createServer } from "node:http";
|
|
304
327
|
const server = createServer(createYoga());
|
|
305
328
|
server.listen(3000, () => {
|
|
306
|
-
|
|
329
|
+
console.info("Visit http://localhost:3000/graphql");
|
|
307
330
|
});
|
|
308
|
-
|
|
309
331
|
```
|
|
310
332
|
> `createYoga` sends no CORS headers unless you pass `cors` (Yoga's own default would reflect any origin with credentials, which lets other websites use a visitor's cookie session). An API that browsers on other origins call needs `cors: { origin: ["https://app.example.org"], credentials: true }`.
|
|
311
333
|
>
|
|
312
334
|
> If you hit `Query depth limit of N exceeded` (or alias/directive/token limit) errors in production, pass `armorConfig` through to relax the [graphql-armor](https://github.com/Escape-Technologies/graphql-armor) defaults — e.g. `createYoga({ armorConfig: { maxDepth: { n: 20 } } })`. `armorConfig` is forwarded verbatim to `EnvelopArmorPlugin(...)` and is only applied when `enableApiDocs` is `false` (i.e. in production).
|
|
313
335
|
|
|
314
336
|
## Usage & client generation
|
|
337
|
+
|
|
315
338
|
You can use the GraphQL api with any client you like. However, rumble provides a generation api which can output a TypeScript client from a rumble instance. To perform a generation, use the exported function from your rumble instance like this:
|
|
316
339
|
```ts
|
|
317
340
|
|
|
@@ -344,8 +367,8 @@ An example usage might look like this:
|
|
|
344
367
|
import { client } from "./generated-client/client";
|
|
345
368
|
|
|
346
369
|
const users = client.liveQuery.users({
|
|
347
|
-
|
|
348
|
-
|
|
370
|
+
id: true,
|
|
371
|
+
name: true,
|
|
349
372
|
});
|
|
350
373
|
|
|
351
374
|
users.subscribe((s) => s?.at(0));
|
|
@@ -357,19 +380,20 @@ If you would like to ensure that there is data present before subscribing to upd
|
|
|
357
380
|
```ts
|
|
358
381
|
// this waits for the first value to arrive
|
|
359
382
|
const users = await client.liveQuery.users({
|
|
360
|
-
|
|
361
|
-
|
|
383
|
+
id: true,
|
|
384
|
+
name: true,
|
|
362
385
|
});
|
|
363
386
|
|
|
364
387
|
// this will guaranteed to have a value set
|
|
365
388
|
users.subscribe((s) => s?.at(0));
|
|
366
389
|
|
|
367
390
|
// you can directly access the values of an awaited result
|
|
368
|
-
console.log(users.firstName)
|
|
391
|
+
console.log(users.firstName);
|
|
369
392
|
```
|
|
370
393
|
|
|
371
394
|
> As of `v0.16.12` the client has special support for the svelte reactive state system (runes). If you run a live query which deploys a subscription inside a svelte effect context, you will get reactivity without subscribing to anything right out of the box. Please see [here](https://github.com/DeutscheModelUnitedNations/munify-chase/blob/f70c4484a92551b564c70603ebfd48d5b8cac637/src/lib/api/customClient.ts#L12) and [here](https://github.com/DeutscheModelUnitedNations/munify-chase/blob/f70c4484a92551b564c70603ebfd48d5b8cac637/src/routes/app/(launcher)/%2Bpage.svelte#L9C9-L9C23) for real world examples.
|
|
372
395
|
### Alternative decoupled client generation
|
|
396
|
+
|
|
373
397
|
As an alternative to use the client generator with a fully instanciated rumble instance, you can also import the `generateFromSchema` function from rumble and pass it a standard `GraphQLSchema` object to generate the client:
|
|
374
398
|
```ts
|
|
375
399
|
import { generateFromSchema } from "@m1212e/rumble/client/generate";
|
package/out/client/generate.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { GraphQLSchema } from "graphql";
|
|
2
|
-
//#region lib/client/generate/generate.d.ts
|
|
3
2
|
export declare function generateFromSchema({ outputPath, schema, rumbleImportPath, apiUrl, useExternalUrqlClient, removeExisting, forceReactivity, autoIncludeIdField }: {
|
|
4
3
|
schema: GraphQLSchema;
|
|
5
4
|
outputPath: string;
|
|
@@ -10,5 +9,4 @@ export declare function generateFromSchema({ outputPath, schema, rumbleImportPat
|
|
|
10
9
|
forceReactivity?: boolean;
|
|
11
10
|
autoIncludeIdField?: string | boolean;
|
|
12
11
|
}): Promise<void>;
|
|
13
|
-
//#endregion
|
|
14
12
|
//# sourceMappingURL=generate.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.cts","names":[],"sources":["../../lib/client/generate/generate.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.cts","names":[],"sources":["../../lib/client/generate/generate.ts"],"mappings":";wBAoBsB,qBACpB,YACA,QACA,kBACA,QACA,uBACA,gBACA,iBACA;EAEA,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA;EACA;IACD"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { GraphQLSchema } from "graphql";
|
|
2
|
-
//#region lib/client/generate/generate.d.ts
|
|
3
2
|
export declare function generateFromSchema({ outputPath, schema, rumbleImportPath, apiUrl, useExternalUrqlClient, removeExisting, forceReactivity, autoIncludeIdField }: {
|
|
4
3
|
schema: GraphQLSchema;
|
|
5
4
|
outputPath: string;
|
|
@@ -10,5 +9,4 @@ export declare function generateFromSchema({ outputPath, schema, rumbleImportPat
|
|
|
10
9
|
forceReactivity?: boolean;
|
|
11
10
|
autoIncludeIdField?: string | boolean;
|
|
12
11
|
}): Promise<void>;
|
|
13
|
-
//#endregion
|
|
14
12
|
//# sourceMappingURL=generate.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.mts","names":[],"sources":["../../lib/client/generate/generate.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.mts","names":[],"sources":["../../lib/client/generate/generate.ts"],"mappings":";wBAoBsB,qBACpB,YACA,QACA,kBACA,QACA,uBACA,gBACA,iBACA;EAEA,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA;EACA;IACD"}
|
package/out/client/generate.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { generateFromSchema };
|
|
1
|
+
export { t as generateFromSchema } from "../generate-Dzf2klR2.mjs";
|
package/out/client.cjs
CHANGED
|
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
let es_toolkit = require("es-toolkit");
|
|
3
3
|
let graphql_scalars = require("graphql-scalars");
|
|
4
4
|
let wonka = require("wonka");
|
|
5
|
-
|
|
5
|
+
// lib/client/request.ts
|
|
6
6
|
let createSubscriber = () => () => {};
|
|
7
7
|
const svelteReactivityReady = import("svelte/reactivity").then((m) => {
|
|
8
8
|
createSubscriber = m.createSubscriber;
|
|
@@ -304,8 +304,7 @@ function serializePrimitive(arg) {
|
|
|
304
304
|
if (typeof arg === "symbol" || typeof arg === "function") throw new Error(`Cannot stringify a ${typeof arg} to send as gql arg`);
|
|
305
305
|
throw new Error("Cannot stringify an unknown type");
|
|
306
306
|
}
|
|
307
|
-
|
|
308
|
-
//#region lib/client/liveQuery.ts
|
|
307
|
+
// lib/client/liveQuery.ts
|
|
309
308
|
function makeLiveQuery({ urqlClient, availableSubscriptions, forceReactivity, schema, autoIncludeIdField }) {
|
|
310
309
|
return new Proxy({}, { get: (_target, prop) => {
|
|
311
310
|
return (input) => {
|
|
@@ -321,8 +320,7 @@ function makeLiveQuery({ urqlClient, availableSubscriptions, forceReactivity, sc
|
|
|
321
320
|
};
|
|
322
321
|
} });
|
|
323
322
|
}
|
|
324
|
-
|
|
325
|
-
//#region lib/client/mutation.ts
|
|
323
|
+
// lib/client/mutation.ts
|
|
326
324
|
function makeMutation({ urqlClient, schema, autoIncludeIdField }) {
|
|
327
325
|
return new Proxy({}, { get: (_target, prop) => {
|
|
328
326
|
return (input) => {
|
|
@@ -336,8 +334,7 @@ function makeMutation({ urqlClient, schema, autoIncludeIdField }) {
|
|
|
336
334
|
};
|
|
337
335
|
} });
|
|
338
336
|
}
|
|
339
|
-
|
|
340
|
-
//#region lib/helpers/deepMap.ts
|
|
337
|
+
// lib/helpers/deepMap.ts
|
|
341
338
|
/**
|
|
342
339
|
* Recursively applies a mapping function to every value in a nested structure.
|
|
343
340
|
*
|
|
@@ -385,8 +382,7 @@ function mapValuesDeep(input, fn) {
|
|
|
385
382
|
};
|
|
386
383
|
return recurse(input);
|
|
387
384
|
}
|
|
388
|
-
|
|
389
|
-
//#region lib/client/nativeDateExchange.ts
|
|
385
|
+
// lib/client/nativeDateExchange.ts
|
|
390
386
|
const dateIsoRegex = /^\d{4}-\d{2}-\d{2}(?:[Tt ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:[Zz]|[+-]\d{2}:\d{2})?)?$/;
|
|
391
387
|
const nativeDateExchange = ({ client: _client, forward }) => {
|
|
392
388
|
return (operations$) => {
|
|
@@ -402,8 +398,7 @@ const nativeDateExchange = ({ client: _client, forward }) => {
|
|
|
402
398
|
}));
|
|
403
399
|
};
|
|
404
400
|
};
|
|
405
|
-
|
|
406
|
-
//#region lib/client/query.ts
|
|
401
|
+
// lib/client/query.ts
|
|
407
402
|
function makeQuery({ urqlClient, forceReactivity, schema, autoIncludeIdField }) {
|
|
408
403
|
return new Proxy({}, { get: (_target, prop) => {
|
|
409
404
|
return (input) => {
|
|
@@ -419,8 +414,7 @@ function makeQuery({ urqlClient, forceReactivity, schema, autoIncludeIdField })
|
|
|
419
414
|
};
|
|
420
415
|
} });
|
|
421
416
|
}
|
|
422
|
-
|
|
423
|
-
//#region lib/client/subscription.ts
|
|
417
|
+
// lib/client/subscription.ts
|
|
424
418
|
function makeSubscription({ urqlClient, schema, autoIncludeIdField }) {
|
|
425
419
|
return new Proxy({}, { get: (_target, prop) => {
|
|
426
420
|
return (input) => {
|
|
@@ -434,7 +428,6 @@ function makeSubscription({ urqlClient, schema, autoIncludeIdField }) {
|
|
|
434
428
|
};
|
|
435
429
|
} });
|
|
436
430
|
}
|
|
437
|
-
//#endregion
|
|
438
431
|
exports.makeLiveQuery = makeLiveQuery;
|
|
439
432
|
exports.makeMutation = makeMutation;
|
|
440
433
|
exports.makeQuery = makeQuery;
|