@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/out/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
2
|
+
// \0rolldown/runtime.js
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -20,23 +20,22 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
20
20
|
value: mod,
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
|
-
|
|
24
|
-
const require_generate = require("./generate-D0CKBths.cjs");
|
|
23
|
+
const require_generate = require("./generate-Btr_u0Lr.cjs");
|
|
25
24
|
let drizzle_orm = require("drizzle-orm");
|
|
26
25
|
let graphql = require("graphql");
|
|
27
26
|
let es_toolkit = require("es-toolkit");
|
|
28
27
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
29
28
|
let _opentelemetry_semantic_conventions_incubating = require("@opentelemetry/semantic-conventions/incubating");
|
|
30
29
|
let _pothos_tracing_opentelemetry = require("@pothos/tracing-opentelemetry");
|
|
30
|
+
let drizzle_orm_mysql_core = require("drizzle-orm/mysql-core");
|
|
31
|
+
let drizzle_orm_pg_core = require("drizzle-orm/pg-core");
|
|
32
|
+
let drizzle_orm_sqlite_core = require("drizzle-orm/sqlite-core");
|
|
31
33
|
let _escape_tech_graphql_armor = require("@escape.tech/graphql-armor");
|
|
32
34
|
let _graphql_yoga_plugin_disable_introspection = require("@graphql-yoga/plugin-disable-introspection");
|
|
33
35
|
let graphql_yoga = require("graphql-yoga");
|
|
34
36
|
let drizzle_orm_casing = require("drizzle-orm/casing");
|
|
35
|
-
let drizzle_orm_pg_core = require("drizzle-orm/pg-core");
|
|
36
|
-
let drizzle_orm_mysql_core = require("drizzle-orm/mysql-core");
|
|
37
37
|
let pluralize = require("pluralize");
|
|
38
38
|
pluralize = __toESM(pluralize, 1);
|
|
39
|
-
let drizzle_orm_sqlite_core = require("drizzle-orm/sqlite-core");
|
|
40
39
|
let _pothos_core = require("@pothos/core");
|
|
41
40
|
_pothos_core = __toESM(_pothos_core, 1);
|
|
42
41
|
let _pothos_plugin_drizzle = require("@pothos/plugin-drizzle");
|
|
@@ -52,7 +51,7 @@ let dataloader = require("dataloader");
|
|
|
52
51
|
dataloader = __toESM(dataloader, 1);
|
|
53
52
|
let zod = require("zod");
|
|
54
53
|
let libphonenumber_js = require("libphonenumber-js");
|
|
55
|
-
|
|
54
|
+
// lib/types/rumbleError.ts
|
|
56
55
|
/**
|
|
57
56
|
* An error that gets raised by rumble whenever something does not go according to plan.
|
|
58
57
|
* Mostly internals, configuration errors or other unexpected things.
|
|
@@ -69,8 +68,7 @@ var RumbleError = class extends Error {
|
|
|
69
68
|
* E.g. the assert helpers issue these.
|
|
70
69
|
*/
|
|
71
70
|
var RumbleErrorSafe = class extends graphql.GraphQLError {};
|
|
72
|
-
|
|
73
|
-
//#region lib/helpers/tableHelpers.ts
|
|
71
|
+
// lib/helpers/tableHelpers.ts
|
|
74
72
|
const indexCache = /* @__PURE__ */ new WeakMap();
|
|
75
73
|
function buildIndex(db) {
|
|
76
74
|
const byTsName = /* @__PURE__ */ new Map();
|
|
@@ -139,8 +137,7 @@ function tableHelper({ db, table }) {
|
|
|
139
137
|
foundRelation: entry.foundRelation
|
|
140
138
|
};
|
|
141
139
|
}
|
|
142
|
-
|
|
143
|
-
//#region lib/helpers/mergeFilters.ts
|
|
140
|
+
// lib/helpers/mergeFilters.ts
|
|
144
141
|
const EmptyFilter$1 = Symbol.for("drizzle:EmptyFilter");
|
|
145
142
|
/**
|
|
146
143
|
* Normalizes drizzle-orm's `EmptyFilter` sentinel to `undefined` so it's
|
|
@@ -184,8 +181,7 @@ function mergeFilters(filterA, filterB, mode = "AND") {
|
|
|
184
181
|
with: mergeRecords(filterA?.with, filterB?.with)
|
|
185
182
|
};
|
|
186
183
|
}
|
|
187
|
-
|
|
188
|
-
//#region lib/helpers/sanitizeFilterValue.ts
|
|
184
|
+
// lib/helpers/sanitizeFilterValue.ts
|
|
189
185
|
const EmptyFilter = Symbol.for("drizzle:EmptyFilter");
|
|
190
186
|
function isPlainObject(value) {
|
|
191
187
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -198,17 +194,16 @@ function sanitizeFilterValue(value) {
|
|
|
198
194
|
if (isPlainObject(value)) return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, sanitizeFilterValue(entry)]));
|
|
199
195
|
return value;
|
|
200
196
|
}
|
|
201
|
-
|
|
202
|
-
//#region lib/abilityBuilder/keys.ts
|
|
197
|
+
// lib/abilityBuilder/keys.ts
|
|
203
198
|
const ACTION_FLAG_KEY = "__rumble_action";
|
|
204
199
|
const columnFlagKey = (group) => `__rumble_columns_${group}`;
|
|
205
200
|
const columnMaskKey = Symbol.for("rumble:columnMask");
|
|
206
201
|
const columnVisibilityKey = Symbol.for("rumble:columnVisibility");
|
|
207
202
|
const guardInputKey = Symbol.for("rumble:guardInput");
|
|
208
203
|
const resolvedFilterKey = Symbol.for("rumble:resolvedFilter");
|
|
204
|
+
const refreshAbilitiesKey = Symbol.for("rumble:refreshAbilities");
|
|
209
205
|
const requestStateKey = Symbol.for("rumble:requestState");
|
|
210
|
-
|
|
211
|
-
//#region lib/abilityBuilder/requestState.ts
|
|
206
|
+
// lib/abilityBuilder/requestState.ts
|
|
212
207
|
function createRequestState() {
|
|
213
208
|
return {
|
|
214
209
|
masked: /* @__PURE__ */ new WeakMap(),
|
|
@@ -223,16 +218,7 @@ function attachRequestState(abilities, state) {
|
|
|
223
218
|
function requestStateOf(abilities) {
|
|
224
219
|
return abilities?.[requestStateKey];
|
|
225
220
|
}
|
|
226
|
-
|
|
227
|
-
//#region lib/abilityBuilder/columnMask.ts
|
|
228
|
-
function referencesRelation(filter, relations) {
|
|
229
|
-
if (!filter || typeof filter !== "object") return false;
|
|
230
|
-
return Object.entries(filter).some(([key, value]) => {
|
|
231
|
-
if (key === "AND" || key === "OR") return value.some((v) => referencesRelation(v, relations));
|
|
232
|
-
if (key === "NOT") return referencesRelation(value, relations);
|
|
233
|
-
return key in relations;
|
|
234
|
-
});
|
|
235
|
-
}
|
|
221
|
+
// lib/abilityBuilder/columnMask.ts
|
|
236
222
|
function selectedColumns(columns, allColumns) {
|
|
237
223
|
if (!columns) return new Set(allColumns);
|
|
238
224
|
const entries = Object.entries(columns).filter(([, v]) => v !== void 0);
|
|
@@ -291,12 +277,7 @@ function conditionalGroups(rules, guaranteed) {
|
|
|
291
277
|
function createColumnAccessResolver({ db, actions }, tableSchema) {
|
|
292
278
|
const allColumnNames = Object.keys(tableSchema.columns);
|
|
293
279
|
const primaryKeyNames = Object.keys(tableSchema.primaryKey);
|
|
294
|
-
const primaryKeyName = primaryKeyNames[0];
|
|
295
280
|
const toSQL = (table, wheres) => (0, drizzle_orm.or)(...wheres.map((where) => (0, drizzle_orm.relationsFilterToSQL)(table, sanitizeFilterValue(where), tableSchema.relations, db._.relations)));
|
|
296
|
-
const uncorrelated = (table, wheres, group) => {
|
|
297
|
-
const inner = (0, drizzle_orm.aliasedTable)(tableSchema.table, `rumble_columns_${group}`);
|
|
298
|
-
return drizzle_orm.sql`exists ${db.select({ pk: inner[primaryKeyName] }).from(inner).where(drizzle_orm.sql`${inner[primaryKeyName]} = ${table[primaryKeyName]} and (${toSQL(inner, wheres)})`)}`;
|
|
299
|
-
};
|
|
300
281
|
return function resolveColumnAccess(action, filters) {
|
|
301
282
|
const rules = filters.map((f) => ({
|
|
302
283
|
where: realWhere(f?.where),
|
|
@@ -327,11 +308,7 @@ function createColumnAccessResolver({ db, actions }, tableSchema) {
|
|
|
327
308
|
const actionIndex = drizzle_orm.sql.raw(String(actions.indexOf(action)));
|
|
328
309
|
const extras = { [ACTION_FLAG_KEY]: () => drizzle_orm.sql`${actionIndex}` };
|
|
329
310
|
groups.forEach(({ wheres }, group) => {
|
|
330
|
-
|
|
331
|
-
extras[mask.flags[group]] = (table) => {
|
|
332
|
-
const condition = relational ? uncorrelated(table, wheres, group) : toSQL(table, wheres);
|
|
333
|
-
return drizzle_orm.sql`case when ${condition} then 1 else 0 end`;
|
|
334
|
-
};
|
|
311
|
+
extras[mask.flags[group]] = (table) => drizzle_orm.sql`case when ${toSQL(table, wheres)} then 1 else 0 end`;
|
|
335
312
|
});
|
|
336
313
|
return {
|
|
337
314
|
columns,
|
|
@@ -414,8 +391,7 @@ function createColumnMasker({ actions }, tables) {
|
|
|
414
391
|
columnsHidden
|
|
415
392
|
};
|
|
416
393
|
}
|
|
417
|
-
|
|
418
|
-
//#region lib/helpers/sqlTypes/types.ts
|
|
394
|
+
// lib/helpers/sqlTypes/types.ts
|
|
419
395
|
/**
|
|
420
396
|
* Strips parameter suffixes like `(256)`, `(10,2)` and timezone modifiers
|
|
421
397
|
* (`with time zone`, `without time zone`) from raw getSQLType() output so
|
|
@@ -522,8 +498,7 @@ function isBytesSQLTypeString(sqlType) {
|
|
|
522
498
|
return bytesSQLTypeStrings.includes(sqlType);
|
|
523
499
|
}
|
|
524
500
|
const UnknownTypeRumbleError = (sqlType, additionalInfo) => new RumbleError(`RumbleError: Unknown SQL type '${sqlType}'. Please open an issue (https://github.com/m1212e/rumble/issues) so it can be added. (${additionalInfo})`);
|
|
525
|
-
|
|
526
|
-
//#region lib/helpers/sqlTypes/distinctValuesFromSQLType.ts
|
|
501
|
+
// lib/helpers/sqlTypes/distinctValuesFromSQLType.ts
|
|
527
502
|
function createDistinctValuesFromSQLType(sqlType) {
|
|
528
503
|
if (isIntLikeSQLTypeString(sqlType)) return {
|
|
529
504
|
value1: 1,
|
|
@@ -559,8 +534,7 @@ function createDistinctValuesFromSQLType(sqlType) {
|
|
|
559
534
|
};
|
|
560
535
|
throw UnknownTypeRumbleError(sqlType, "Distinct");
|
|
561
536
|
}
|
|
562
|
-
|
|
563
|
-
//#region lib/helpers/telemetry.ts
|
|
537
|
+
// lib/helpers/telemetry.ts
|
|
564
538
|
const SPAN_EXECUTE = _pothos_tracing_opentelemetry.SpanNames.EXECUTE;
|
|
565
539
|
/** @pothos/tracing-opentelemetry's SpanNames enum has no subscribe member. */
|
|
566
540
|
const SPAN_SUBSCRIBE = "graphql.subscribe";
|
|
@@ -584,6 +558,7 @@ const ATTR_ABILITIES_STATUS = "rumble.abilities.status";
|
|
|
584
558
|
const ATTR_ABILITIES_STATIC = "rumble.abilities.static";
|
|
585
559
|
const ATTR_ABILITIES_DYNAMIC = "rumble.abilities.dynamic";
|
|
586
560
|
const ATTR_ABILITIES_TOTAL = "rumble.abilities.total";
|
|
561
|
+
const ATTR_ABILITIES_RESOLVED = "rumble.abilities.resolved";
|
|
587
562
|
const ATTR_FILTERS_TOTAL = "rumble.filters.total";
|
|
588
563
|
const ATTR_FILTERS_ALLOWED = "rumble.filters.allowed";
|
|
589
564
|
const ATTR_SUBSCRIPTION_EVENT_INDEX = "rumble.subscription.event_index";
|
|
@@ -734,8 +709,7 @@ function startTimer() {
|
|
|
734
709
|
function durationMs(start) {
|
|
735
710
|
return Math.round((performance.now() - start) * 100) / 100;
|
|
736
711
|
}
|
|
737
|
-
|
|
738
|
-
//#region lib/abilityBuilder/filterResponse.ts
|
|
712
|
+
// lib/abilityBuilder/filterResponse.ts
|
|
739
713
|
/**
|
|
740
714
|
* The limit of a find many call. An injected merge limit wins unless the
|
|
741
715
|
* ability limit is lower, otherwise the default limit caps the ability limit.
|
|
@@ -800,16 +774,125 @@ function createFilterResponder({ db, defaultLimit }, tableSchema) {
|
|
|
800
774
|
return ret;
|
|
801
775
|
};
|
|
802
776
|
}
|
|
803
|
-
|
|
804
|
-
//#region lib/abilityBuilder/queryFilter.ts
|
|
777
|
+
// lib/abilityBuilder/queryFilter.ts
|
|
805
778
|
function isDynamicQueryFilter(filter) {
|
|
806
779
|
return typeof filter === "function";
|
|
807
780
|
}
|
|
808
781
|
function isStaticQueryFilter(filter) {
|
|
809
782
|
return typeof filter !== "function";
|
|
810
783
|
}
|
|
811
|
-
|
|
812
|
-
|
|
784
|
+
// lib/helpers/determineDialectFromSchema.ts
|
|
785
|
+
const dialectCache = /* @__PURE__ */ new WeakMap();
|
|
786
|
+
function determineDBDialectFromSchema(schema) {
|
|
787
|
+
const cached = dialectCache.get(schema);
|
|
788
|
+
if (cached) return cached;
|
|
789
|
+
const found = /* @__PURE__ */ new Set();
|
|
790
|
+
for (const table of Object.values(schema).map((t) => t.table)) {
|
|
791
|
+
if (!table || typeof table !== "object") continue;
|
|
792
|
+
if ((0, drizzle_orm.is)(table, drizzle_orm_pg_core.PgTable)) found.add("postgres");
|
|
793
|
+
else if ((0, drizzle_orm.is)(table, drizzle_orm_mysql_core.MySqlTable)) found.add("mysql");
|
|
794
|
+
else if ((0, drizzle_orm.is)(table, drizzle_orm_sqlite_core.SQLiteTable)) found.add("sqlite");
|
|
795
|
+
}
|
|
796
|
+
const dialects = Array.from(found);
|
|
797
|
+
if (dialects.length === 1) {
|
|
798
|
+
const only = dialects[0];
|
|
799
|
+
dialectCache.set(schema, only);
|
|
800
|
+
return only;
|
|
801
|
+
}
|
|
802
|
+
if (dialects.length === 0) throw new Error("No tables found in schema, could not determine dialect");
|
|
803
|
+
throw new Error(`Multiple dialects found in schema: ${dialects.join(", ")}`);
|
|
804
|
+
}
|
|
805
|
+
function isPostgresDB(db) {
|
|
806
|
+
return determineDBDialectFromSchema(db._.relations) === "postgres";
|
|
807
|
+
}
|
|
808
|
+
// lib/abilityBuilder/resolveRules.ts
|
|
809
|
+
const DEFAULT_MAX_RESOLVED_IDS = 500;
|
|
810
|
+
/**
|
|
811
|
+
* Whether the where names a relation of the table, so it renders as (nested)
|
|
812
|
+
* `exists` subqueries.
|
|
813
|
+
*/
|
|
814
|
+
function referencesRelation(filter, relations) {
|
|
815
|
+
if (!filter || typeof filter !== "object") return false;
|
|
816
|
+
return Object.entries(filter).some(([key, value]) => {
|
|
817
|
+
if (key === "AND" || key === "OR") return value.some((v) => referencesRelation(v, relations));
|
|
818
|
+
if (key === "NOT") return referencesRelation(value, relations);
|
|
819
|
+
return key in relations;
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Creates the function replacing the relational rules of a table by the
|
|
824
|
+
* primary keys they match, resolved with one query per call.
|
|
825
|
+
*
|
|
826
|
+
* A relational rule ("the users whose delegation the caller supervises")
|
|
827
|
+
* renders as a chain of correlated `exists` subqueries, once in the row filter
|
|
828
|
+
* and once more in every column flag, at every place the table is nested in a
|
|
829
|
+
* query. Planning such a statement costs the database tens of megabytes. For a
|
|
830
|
+
* given caller the rule matches a fixed set of rows though, so this looks them
|
|
831
|
+
* up once (`select pk from table where <rule>`) and the rule becomes
|
|
832
|
+
* `pk in (...)`, which costs the planner nothing. Rules matching more than
|
|
833
|
+
* `maxIds` rows stay relational, so broad rules do not turn into huge lists.
|
|
834
|
+
*
|
|
835
|
+
* Returns undefined when disabled or the table has no single primary key.
|
|
836
|
+
*/
|
|
837
|
+
function createRuleResolver(settings, tableSchema) {
|
|
838
|
+
const config = settings.resolveRelationalRules;
|
|
839
|
+
const primaryKeys = Object.keys(tableSchema.primaryKey);
|
|
840
|
+
if (!config?.enabled || primaryKeys.length !== 1) return void 0;
|
|
841
|
+
const maxIds = config.maxIds ?? DEFAULT_MAX_RESOLVED_IDS;
|
|
842
|
+
const primaryKeyName = primaryKeys[0];
|
|
843
|
+
const db = settings.db;
|
|
844
|
+
const table = tableSchema.table;
|
|
845
|
+
const dialect = determineDBDialectFromSchema(db._.relations);
|
|
846
|
+
const unionAll = {
|
|
847
|
+
postgres: drizzle_orm_pg_core.unionAll,
|
|
848
|
+
sqlite: drizzle_orm_sqlite_core.unionAll,
|
|
849
|
+
mysql: drizzle_orm_mysql_core.unionAll
|
|
850
|
+
}[dialect];
|
|
851
|
+
const listFilter = (ids) => dialect === "postgres" ? { RAW: (aliased) => drizzle_orm.sql`${aliased[primaryKeyName]} = any(${drizzle_orm.sql.param(ids)})` } : { [primaryKeyName]: { in: ids } };
|
|
852
|
+
/** The primary keys matching the rule, tagged with the rule's index. */
|
|
853
|
+
const matches = (where, rule) => {
|
|
854
|
+
const limited = db.select({
|
|
855
|
+
pk: table[primaryKeyName],
|
|
856
|
+
rule: drizzle_orm.sql.raw(String(rule)).as("rule")
|
|
857
|
+
}).from(table).where((0, drizzle_orm.relationsFilterToSQL)(table, sanitizeFilterValue(where), tableSchema.relations, db._.relations)).limit(maxIds + 1).as(`rumble_rule_${rule}`);
|
|
858
|
+
return db.select({
|
|
859
|
+
pk: limited.pk,
|
|
860
|
+
rule: limited.rule
|
|
861
|
+
}).from(limited);
|
|
862
|
+
};
|
|
863
|
+
const whereOf = (filter) => realWhere(filter?.where);
|
|
864
|
+
return async function resolveRules(filters) {
|
|
865
|
+
const relational = filters.flatMap((filter, index) => referencesRelation(whereOf(filter), tableSchema.relations) ? [index] : []);
|
|
866
|
+
if (relational.length === 0) return {
|
|
867
|
+
filters,
|
|
868
|
+
resolved: 0
|
|
869
|
+
};
|
|
870
|
+
const queries = relational.map((index) => matches(whereOf(filters[index]), index));
|
|
871
|
+
const rows = await (queries.length === 1 ? queries[0] : unionAll(...queries));
|
|
872
|
+
const idsPerRule = new Map(relational.map((index) => [index, []]));
|
|
873
|
+
for (const row of rows) idsPerRule.get(Number(row.rule)).push(row.pk);
|
|
874
|
+
let resolved = 0;
|
|
875
|
+
const result = [];
|
|
876
|
+
filters.forEach((filter, index) => {
|
|
877
|
+
const ids = idsPerRule.get(index);
|
|
878
|
+
if (!ids || ids.length > maxIds) {
|
|
879
|
+
result.push(filter);
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
resolved++;
|
|
883
|
+
if (ids.length === 0) return;
|
|
884
|
+
result.push({
|
|
885
|
+
...filter,
|
|
886
|
+
where: listFilter(ids)
|
|
887
|
+
});
|
|
888
|
+
});
|
|
889
|
+
return {
|
|
890
|
+
filters: result,
|
|
891
|
+
resolved
|
|
892
|
+
};
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
// lib/helpers/errorLogging.ts
|
|
813
896
|
function hasMessage(error) {
|
|
814
897
|
return typeof error === "object" && error !== null && "message" in error;
|
|
815
898
|
}
|
|
@@ -840,8 +923,7 @@ function errorsLogField(errors) {
|
|
|
840
923
|
function errorLogField(error) {
|
|
841
924
|
return errorsLogField([error]);
|
|
842
925
|
}
|
|
843
|
-
|
|
844
|
-
//#region lib/abilityBuilder/telemetry.ts
|
|
926
|
+
// lib/abilityBuilder/telemetry.ts
|
|
845
927
|
const makeNothingRegisteredWarner = (config, logger) => (0, es_toolkit.debounce)((model, action) => {
|
|
846
928
|
const msg = `No abilities registered for ${model}/${action} — blocking everything. Register the ability or ignore this warning if intentional.`;
|
|
847
929
|
if (logger) logger.warn({
|
|
@@ -889,8 +971,7 @@ function traceAbilityPreparation({ otel, log, telemetryConfig }, tableName, acti
|
|
|
889
971
|
});
|
|
890
972
|
return run();
|
|
891
973
|
}
|
|
892
|
-
|
|
893
|
-
//#region lib/abilityBuilder/tableAbilities.ts
|
|
974
|
+
// lib/abilityBuilder/tableAbilities.ts
|
|
894
975
|
/**
|
|
895
976
|
* filter() is async. Without type checking (plain JS, `any`) a forgotten await would
|
|
896
977
|
* hand the promise itself to drizzle
|
|
@@ -948,7 +1029,23 @@ const createTableAbilities = (settings, tableName, queryFilters) => {
|
|
|
948
1029
|
const blockEverythingFilter = createBlockEverythingFilter(String(tableName), tableSchema);
|
|
949
1030
|
const resolveColumnAccess = createColumnAccessResolver(settings, tableSchema);
|
|
950
1031
|
const transformToResponse = createFilterResponder(settings, tableSchema);
|
|
951
|
-
const
|
|
1032
|
+
const resolveRules = createRuleResolver(settings, tableSchema);
|
|
1033
|
+
const evaluateDynamicFilters = (userContext, action) => Promise.all(dynamicQueryFilters[action].map((func) => func(userContext)));
|
|
1034
|
+
/** The response for the rules applying to the caller: their OR, columns and flags. */
|
|
1035
|
+
const respondWithFilters = (action, allQueryFilters) => {
|
|
1036
|
+
const mergedFilters = allQueryFilters.length === 1 ? { ...allQueryFilters[0] } : allQueryFilters.reduce((a, b) => {
|
|
1037
|
+
return mergeFilters(a, b, "OR");
|
|
1038
|
+
});
|
|
1039
|
+
const { columns, extras, mask, visibility } = resolveColumnAccess(action, allQueryFilters);
|
|
1040
|
+
if (columns) mergedFilters.columns = columns;
|
|
1041
|
+
else delete mergedFilters.columns;
|
|
1042
|
+
if (extras) mergedFilters.extras = {
|
|
1043
|
+
...mergedFilters.extras,
|
|
1044
|
+
...extras
|
|
1045
|
+
};
|
|
1046
|
+
return transformToResponse(mergedFilters, mask, visibility);
|
|
1047
|
+
};
|
|
1048
|
+
const assembleAbilities = async (action, attributes, evaluate) => {
|
|
952
1049
|
const filters = queryFilters.get(action);
|
|
953
1050
|
if (filters === "unrestricted") {
|
|
954
1051
|
attributes[ATTR_ABILITIES_STATUS] = "unrestricted";
|
|
@@ -959,7 +1056,7 @@ const createTableAbilities = (settings, tableName, queryFilters) => {
|
|
|
959
1056
|
settings.warnNothingRegistered(String(tableName), action);
|
|
960
1057
|
return transformToResponse(blockEverythingFilter);
|
|
961
1058
|
}
|
|
962
|
-
const rawResults = await
|
|
1059
|
+
const rawResults = await evaluate();
|
|
963
1060
|
if (rawResults.includes("allow")) {
|
|
964
1061
|
attributes[ATTR_ABILITIES_STATUS] = "unrestricted";
|
|
965
1062
|
return transformToResponse();
|
|
@@ -967,28 +1064,32 @@ const createTableAbilities = (settings, tableName, queryFilters) => {
|
|
|
967
1064
|
const dynamicResults = rawResults.filter((r) => r !== void 0).map(withRestrictingWhere);
|
|
968
1065
|
attributes[ATTR_ABILITIES_DYNAMIC] = dynamicResults.length;
|
|
969
1066
|
attributes[ATTR_ABILITIES_STATIC] = simpleQueryFilters[action].length;
|
|
970
|
-
|
|
1067
|
+
let allQueryFilters = [...simpleQueryFilters[action], ...dynamicResults];
|
|
971
1068
|
attributes[ATTR_ABILITIES_TOTAL] = allQueryFilters.length;
|
|
1069
|
+
if (resolveRules && allQueryFilters.length > 0) {
|
|
1070
|
+
const resolution = await resolveRules(allQueryFilters);
|
|
1071
|
+
allQueryFilters = resolution.filters;
|
|
1072
|
+
attributes[ATTR_ABILITIES_RESOLVED] = resolution.resolved;
|
|
1073
|
+
}
|
|
972
1074
|
if (allQueryFilters.length === 0) {
|
|
973
1075
|
attributes[ATTR_ABILITIES_STATUS] = "blocked_everything";
|
|
974
1076
|
return transformToResponse(blockEverythingFilter);
|
|
975
1077
|
}
|
|
976
|
-
const mergedFilters = allQueryFilters.length === 1 ? { ...allQueryFilters[0] } : allQueryFilters.reduce((a, b) => {
|
|
977
|
-
return mergeFilters(a, b, "OR");
|
|
978
|
-
});
|
|
979
|
-
const { columns, extras, mask, visibility } = resolveColumnAccess(action, allQueryFilters);
|
|
980
|
-
if (columns) mergedFilters.columns = columns;
|
|
981
|
-
else delete mergedFilters.columns;
|
|
982
|
-
if (extras) mergedFilters.extras = {
|
|
983
|
-
...mergedFilters.extras,
|
|
984
|
-
...extras
|
|
985
|
-
};
|
|
986
1078
|
attributes[ATTR_ABILITIES_STATUS] = "applied";
|
|
987
|
-
return
|
|
1079
|
+
return respondWithFilters(action, allQueryFilters);
|
|
988
1080
|
};
|
|
989
1081
|
return { withContext: (userContext) => {
|
|
990
|
-
const
|
|
991
|
-
const
|
|
1082
|
+
const evaluated = /* @__PURE__ */ new Map();
|
|
1083
|
+
const evaluate = (action) => {
|
|
1084
|
+
let results = evaluated.get(action);
|
|
1085
|
+
if (!results) {
|
|
1086
|
+
results = evaluateDynamicFilters(userContext, action);
|
|
1087
|
+
evaluated.set(action, results);
|
|
1088
|
+
}
|
|
1089
|
+
return results;
|
|
1090
|
+
};
|
|
1091
|
+
const prepare = (action) => traceAbilityPreparation(settings, String(tableName), action, (attributes) => assembleAbilities(action, attributes, () => evaluate(action)));
|
|
1092
|
+
let cache = /* @__PURE__ */ new Map();
|
|
992
1093
|
const resolved = /* @__PURE__ */ new Map();
|
|
993
1094
|
const abilities = { filter: (action) => {
|
|
994
1095
|
let prepared = cache.get(action);
|
|
@@ -1000,11 +1101,13 @@ const createTableAbilities = (settings, tableName, queryFilters) => {
|
|
|
1000
1101
|
return prepared;
|
|
1001
1102
|
} };
|
|
1002
1103
|
abilities[resolvedFilterKey] = (action) => resolved.get(action);
|
|
1104
|
+
abilities[refreshAbilitiesKey] = () => {
|
|
1105
|
+
if (resolveRules) cache = /* @__PURE__ */ new Map();
|
|
1106
|
+
};
|
|
1003
1107
|
return abilities;
|
|
1004
1108
|
} };
|
|
1005
1109
|
};
|
|
1006
|
-
|
|
1007
|
-
//#region lib/abilityBuilder/inputGuard.ts
|
|
1110
|
+
// lib/abilityBuilder/inputGuard.ts
|
|
1008
1111
|
/** The ts names of the columns a relation joins on, on either side. */
|
|
1009
1112
|
function relationColumnKeys(db, table, columns) {
|
|
1010
1113
|
const known = tableHelper({
|
|
@@ -1137,8 +1240,7 @@ async function relationExposure(abilities, table, action, columns) {
|
|
|
1137
1240
|
const guard = abilities[guardInputKey];
|
|
1138
1241
|
return guard ? guard.exposed(table, action, columns) : [];
|
|
1139
1242
|
}
|
|
1140
|
-
|
|
1141
|
-
//#region lib/abilityBuilder/tableBuilder.ts
|
|
1243
|
+
// lib/abilityBuilder/tableBuilder.ts
|
|
1142
1244
|
/**
|
|
1143
1245
|
* Creates the registration API (allow/filter) of a single table.
|
|
1144
1246
|
*/
|
|
@@ -1222,9 +1324,20 @@ when: (queryFilter) => {
|
|
|
1222
1324
|
}
|
|
1223
1325
|
};
|
|
1224
1326
|
};
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1327
|
+
// lib/abilityBuilder/refresh.ts
|
|
1328
|
+
/**
|
|
1329
|
+
* Starts a new snapshot of the resolved relational rules of every table, see
|
|
1330
|
+
* `resolveRelationalRules`. Rumble calls this whenever a root field starts to
|
|
1331
|
+
* resolve. Call it yourself in a resolver that writes rows and then reads them
|
|
1332
|
+
* through a table whose rules it already resolved before the write. A no-op
|
|
1333
|
+
* unless rules are resolved.
|
|
1334
|
+
*/
|
|
1335
|
+
function refreshAbilities(abilities) {
|
|
1336
|
+
if (!abilities) return;
|
|
1337
|
+
for (const table of Object.values(abilities)) table?.[refreshAbilitiesKey]?.();
|
|
1338
|
+
}
|
|
1339
|
+
// lib/abilityBuilder/index.ts
|
|
1340
|
+
const createAbilityBuilder = ({ db, actions, defaultLimit, resolveRelationalRules, otel, logger: loggerConfig }) => {
|
|
1228
1341
|
const log = loggerConfig?.enabled ? loggerConfig.logger : void 0;
|
|
1229
1342
|
const telemetryConfig = {
|
|
1230
1343
|
otel,
|
|
@@ -1234,6 +1347,7 @@ const createAbilityBuilder = ({ db, actions, defaultLimit, otel, logger: loggerC
|
|
|
1234
1347
|
db,
|
|
1235
1348
|
actions,
|
|
1236
1349
|
defaultLimit,
|
|
1350
|
+
resolveRelationalRules,
|
|
1237
1351
|
otel,
|
|
1238
1352
|
telemetryConfig,
|
|
1239
1353
|
log,
|
|
@@ -1300,8 +1414,7 @@ const createAbilityBuilder = ({ db, actions, defaultLimit, otel, logger: loggerC
|
|
|
1300
1414
|
}
|
|
1301
1415
|
};
|
|
1302
1416
|
};
|
|
1303
|
-
|
|
1304
|
-
//#region lib/helpers/asserts.ts
|
|
1417
|
+
// lib/helpers/asserts.ts
|
|
1305
1418
|
/**
|
|
1306
1419
|
*
|
|
1307
1420
|
* Helper function to map a drizzle findFirst query result,
|
|
@@ -1380,8 +1493,7 @@ const assertFirstEntryExists = (value) => {
|
|
|
1380
1493
|
if (!v) throw new RumbleErrorSafe("Value not found but required (firstEntry)");
|
|
1381
1494
|
return v;
|
|
1382
1495
|
};
|
|
1383
|
-
|
|
1384
|
-
//#region lib/helpers/mapNullFieldsToUndefined.ts
|
|
1496
|
+
// lib/helpers/mapNullFieldsToUndefined.ts
|
|
1385
1497
|
/**
|
|
1386
1498
|
* Helper to map null fields to undefined
|
|
1387
1499
|
* @param obj The object to map
|
|
@@ -1443,11 +1555,9 @@ where: { id: user.id },
|
|
|
1443
1555
|
function mapNullFieldsToUndefined(obj) {
|
|
1444
1556
|
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, value === null ? void 0 : value]));
|
|
1445
1557
|
}
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
//#endregion
|
|
1450
|
-
//#region lib/args/orderArg.ts
|
|
1558
|
+
// package.json
|
|
1559
|
+
var version = "0.27.4";
|
|
1560
|
+
// lib/args/orderArg.ts
|
|
1451
1561
|
const makeDefaultName$1 = (dbName) => `${(0, es_toolkit.capitalize)((0, drizzle_orm_casing.toCamelCase)(dbName.toString()))}OrderInputArgument`;
|
|
1452
1562
|
const createOrderArgImplementer = ({ db, schemaBuilder }) => {
|
|
1453
1563
|
const referenceStorage = /* @__PURE__ */ new Map();
|
|
@@ -1478,8 +1588,7 @@ const createOrderArgImplementer = ({ db, schemaBuilder }) => {
|
|
|
1478
1588
|
};
|
|
1479
1589
|
return orderArgImplementer;
|
|
1480
1590
|
};
|
|
1481
|
-
|
|
1482
|
-
//#region lib/enum.ts
|
|
1591
|
+
// lib/enum.ts
|
|
1483
1592
|
/**
|
|
1484
1593
|
* Checks if a column is a database enum column (Postgres or MySQL).
|
|
1485
1594
|
*/
|
|
@@ -1539,8 +1648,7 @@ const createEnumImplementer = ({ schema, schemaBuilder }) => {
|
|
|
1539
1648
|
};
|
|
1540
1649
|
return enumImplementer;
|
|
1541
1650
|
};
|
|
1542
|
-
|
|
1543
|
-
//#region lib/helpers/sqlTypes/mapSQLTypeToTSType.ts
|
|
1651
|
+
// lib/helpers/sqlTypes/mapSQLTypeToTSType.ts
|
|
1544
1652
|
function mapSQLTypeToGraphQLType({ sqlType, fieldName }) {
|
|
1545
1653
|
if (/^enum\(/.test(sqlType)) return "String";
|
|
1546
1654
|
const normalized = normalizeSQLType(sqlType);
|
|
@@ -1562,8 +1670,7 @@ function mapSQLTypeToGraphQLType({ sqlType, fieldName }) {
|
|
|
1562
1670
|
if (ret !== void 0) return ret;
|
|
1563
1671
|
throw UnknownTypeRumbleError(sqlType, "SQL to GQL");
|
|
1564
1672
|
}
|
|
1565
|
-
|
|
1566
|
-
//#region lib/args/whereArg.ts
|
|
1673
|
+
// lib/args/whereArg.ts
|
|
1567
1674
|
const makeDefaultName = (dbName) => `${(0, es_toolkit.capitalize)((0, drizzle_orm_casing.toCamelCase)(dbName.toString()))}WhereInputArgument`;
|
|
1568
1675
|
const createWhereArgImplementer = ({ db, schemaBuilder, enumImplementer }) => {
|
|
1569
1676
|
const referenceStorage = /* @__PURE__ */ new Map();
|
|
@@ -1788,8 +1895,7 @@ const createWhereArgImplementer = ({ db, schemaBuilder, enumImplementer }) => {
|
|
|
1788
1895
|
};
|
|
1789
1896
|
return whereArgImplementer;
|
|
1790
1897
|
};
|
|
1791
|
-
|
|
1792
|
-
//#region lib/client/client.ts
|
|
1898
|
+
// lib/client/client.ts
|
|
1793
1899
|
const clientCreatorImplementer = ({ builtSchema }) => {
|
|
1794
1900
|
const clientCreator = async ({ apiUrl, outputPath, rumbleImportPath, useExternalUrqlClient, removeExisting, forceReactivity, autoIncludeIdField = false }) => {
|
|
1795
1901
|
if (process.env.NODE_ENV !== "development") console.warn(`Running rumble client generation in non development mode. Are you sure this is correct? Called with arguments: ${JSON.stringify({
|
|
@@ -1813,8 +1919,7 @@ const clientCreatorImplementer = ({ builtSchema }) => {
|
|
|
1813
1919
|
};
|
|
1814
1920
|
return clientCreator;
|
|
1815
1921
|
};
|
|
1816
|
-
|
|
1817
|
-
//#region lib/context.ts
|
|
1922
|
+
// lib/context.ts
|
|
1818
1923
|
const createContextFunction = ({ context: makeUserContext, abilityBuilder }) => {
|
|
1819
1924
|
const builtAbilityBuilder = (0, es_toolkit.once)(() => abilityBuilder._.build());
|
|
1820
1925
|
return async (req) => {
|
|
@@ -1825,8 +1930,7 @@ const createContextFunction = ({ context: makeUserContext, abilityBuilder }) =>
|
|
|
1825
1930
|
};
|
|
1826
1931
|
};
|
|
1827
1932
|
};
|
|
1828
|
-
|
|
1829
|
-
//#region lib/helpers/protoMapper.ts
|
|
1933
|
+
// lib/helpers/protoMapper.ts
|
|
1830
1934
|
function deepSetProto(obj, proto = Object.prototype, seen = /* @__PURE__ */ new WeakSet()) {
|
|
1831
1935
|
if (obj === null || typeof obj !== "object") return;
|
|
1832
1936
|
if (seen.has(obj)) return;
|
|
@@ -1840,8 +1944,7 @@ function deepSetProto(obj, proto = Object.prototype, seen = /* @__PURE__ */ new
|
|
|
1840
1944
|
Object.setPrototypeOf(obj, proto);
|
|
1841
1945
|
for (const key of Object.keys(obj)) deepSetProto(obj[key], proto, seen);
|
|
1842
1946
|
}
|
|
1843
|
-
|
|
1844
|
-
//#region lib/countQuery.ts
|
|
1947
|
+
// lib/countQuery.ts
|
|
1845
1948
|
const createCountQueryImplementer = ({ db, schemaBuilder, whereArgImplementer, makePubSubInstance }) => {
|
|
1846
1949
|
return ({ table, listAction = "read", isAllowed }) => {
|
|
1847
1950
|
const WhereArg = whereArgImplementer({ table });
|
|
@@ -1881,8 +1984,7 @@ const createCountQueryImplementer = ({ db, schemaBuilder, whereArgImplementer, m
|
|
|
1881
1984
|
});
|
|
1882
1985
|
};
|
|
1883
1986
|
};
|
|
1884
|
-
|
|
1885
|
-
//#region lib/helpers/sofaOpenAPIWebhookDocs.ts
|
|
1987
|
+
// lib/helpers/sofaOpenAPIWebhookDocs.ts
|
|
1886
1988
|
const sofaOpenAPIWebhookDocs = {
|
|
1887
1989
|
paths: {
|
|
1888
1990
|
"/webhook": { post: {
|
|
@@ -1966,8 +2068,7 @@ const sofaOpenAPIWebhookDocs = {
|
|
|
1966
2068
|
}
|
|
1967
2069
|
} }
|
|
1968
2070
|
};
|
|
1969
|
-
|
|
1970
|
-
//#region lib/helpers/tracing.ts
|
|
2071
|
+
// lib/helpers/tracing.ts
|
|
1971
2072
|
function isAsyncIterable(value) {
|
|
1972
2073
|
return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
|
|
1973
2074
|
}
|
|
@@ -2155,8 +2256,7 @@ function buildTracedSubscribe(subscribeFn, rumbleInput, transport) {
|
|
|
2155
2256
|
});
|
|
2156
2257
|
};
|
|
2157
2258
|
}
|
|
2158
|
-
|
|
2159
|
-
//#region lib/helpers/sqlTypes/mapDrizzleTypeToGraphQlType.ts
|
|
2259
|
+
// lib/helpers/sqlTypes/mapDrizzleTypeToGraphQlType.ts
|
|
2160
2260
|
function buildPothosResponseTypeFromGraphQLType({ builder, sqlType, fieldName, nullable, isArray }) {
|
|
2161
2261
|
const gqlType = mapSQLTypeToGraphQLType({
|
|
2162
2262
|
sqlType,
|
|
@@ -2204,33 +2304,7 @@ function buildPothosResponseTypeFromGraphQLType({ builder, sqlType, fieldName, n
|
|
|
2204
2304
|
default: throw new RumbleError(`Unsupported object type ${gqlType} for column ${fieldName}`);
|
|
2205
2305
|
}
|
|
2206
2306
|
}
|
|
2207
|
-
|
|
2208
|
-
//#region lib/helpers/determineDialectFromSchema.ts
|
|
2209
|
-
const dialectCache = /* @__PURE__ */ new WeakMap();
|
|
2210
|
-
function determineDBDialectFromSchema(schema) {
|
|
2211
|
-
const cached = dialectCache.get(schema);
|
|
2212
|
-
if (cached) return cached;
|
|
2213
|
-
const found = /* @__PURE__ */ new Set();
|
|
2214
|
-
for (const table of Object.values(schema).map((t) => t.table)) {
|
|
2215
|
-
if (!table || typeof table !== "object") continue;
|
|
2216
|
-
if ((0, drizzle_orm.is)(table, drizzle_orm_pg_core.PgTable)) found.add("postgres");
|
|
2217
|
-
else if ((0, drizzle_orm.is)(table, drizzle_orm_mysql_core.MySqlTable)) found.add("mysql");
|
|
2218
|
-
else if ((0, drizzle_orm.is)(table, drizzle_orm_sqlite_core.SQLiteTable)) found.add("sqlite");
|
|
2219
|
-
}
|
|
2220
|
-
const dialects = Array.from(found);
|
|
2221
|
-
if (dialects.length === 1) {
|
|
2222
|
-
const only = dialects[0];
|
|
2223
|
-
dialectCache.set(schema, only);
|
|
2224
|
-
return only;
|
|
2225
|
-
}
|
|
2226
|
-
if (dialects.length === 0) throw new Error("No tables found in schema, could not determine dialect");
|
|
2227
|
-
throw new Error(`Multiple dialects found in schema: ${dialects.join(", ")}`);
|
|
2228
|
-
}
|
|
2229
|
-
function isPostgresDB(db) {
|
|
2230
|
-
return determineDBDialectFromSchema(db._.relations) === "postgres";
|
|
2231
|
-
}
|
|
2232
|
-
//#endregion
|
|
2233
|
-
//#region lib/search.ts
|
|
2307
|
+
// lib/search.ts
|
|
2234
2308
|
async function initSearchIfApplicable(input) {
|
|
2235
2309
|
const log = input.logger?.enabled ? input.logger.logger : void 0;
|
|
2236
2310
|
if (!isPostgresDB(input.db)) {
|
|
@@ -2290,8 +2364,7 @@ function adjustQueryArgsForSearch({ search, args, tableSchema, abilities }) {
|
|
|
2290
2364
|
}), drizzle_orm.sql.raw(" OR "))})` }] };
|
|
2291
2365
|
}
|
|
2292
2366
|
}
|
|
2293
|
-
|
|
2294
|
-
//#region lib/object.ts
|
|
2367
|
+
// lib/object.ts
|
|
2295
2368
|
const isProbablyAConfigObject = (t) => {
|
|
2296
2369
|
if (typeof t !== "object") return false;
|
|
2297
2370
|
if (Object.keys(t).some((k) => [
|
|
@@ -2519,8 +2592,7 @@ const createObjectImplementer = ({ db, search, otel, logger: loggerConfig, schem
|
|
|
2519
2592
|
});
|
|
2520
2593
|
};
|
|
2521
2594
|
};
|
|
2522
|
-
|
|
2523
|
-
//#region lib/pubsub.ts
|
|
2595
|
+
// lib/pubsub.ts
|
|
2524
2596
|
const SUBSCRIPTION_NOTIFIER_RUMBLE_PREFIX = "RUMBLE_SUBSCRIPTION_NOTIFICATION";
|
|
2525
2597
|
const SUBSCRIPTION_NOTIFIER_REMOVED = "REMOVED";
|
|
2526
2598
|
const SUBSCRIPTION_NOTIFIER_UPDATED = "UPDATED";
|
|
@@ -2595,8 +2667,7 @@ const createPubSubInstance = ({ subscriptions }) => {
|
|
|
2595
2667
|
makePubSubInstance
|
|
2596
2668
|
};
|
|
2597
2669
|
};
|
|
2598
|
-
|
|
2599
|
-
//#region lib/query.ts
|
|
2670
|
+
// lib/query.ts
|
|
2600
2671
|
const createQueryImplementer = ({ db, schemaBuilder, search, otel, logger: loggerConfig, whereArgImplementer, orderArgImplementer, makePubSubInstance }) => {
|
|
2601
2672
|
const registeredQueryFieldNames = /* @__PURE__ */ new Set();
|
|
2602
2673
|
const telemetryConfig = {
|
|
@@ -2711,8 +2782,7 @@ const createQueryImplementer = ({ db, schemaBuilder, search, otel, logger: logge
|
|
|
2711
2782
|
});
|
|
2712
2783
|
};
|
|
2713
2784
|
};
|
|
2714
|
-
|
|
2715
|
-
//#region lib/args/whereArgsImplementer.ts
|
|
2785
|
+
// lib/args/whereArgsImplementer.ts
|
|
2716
2786
|
function implementDefaultWhereInputArgs(schemaBuilder) {
|
|
2717
2787
|
const IntWhereInputArgument = schemaBuilder.inputRef("IntWhereInputArgument").implement({ fields: (t) => ({
|
|
2718
2788
|
eq: t.int(),
|
|
@@ -2964,16 +3034,14 @@ function implementDefaultWhereInputArgs(schemaBuilder) {
|
|
|
2964
3034
|
NOT: t.field({ type: DateTimeWhereInputArgument })
|
|
2965
3035
|
}) });
|
|
2966
3036
|
}
|
|
2967
|
-
|
|
2968
|
-
//#region lib/helpers/objectTypeOptions.ts
|
|
3037
|
+
// lib/helpers/objectTypeOptions.ts
|
|
2969
3038
|
function objectTypeOptionsOfField(buildCache, fieldConfig) {
|
|
2970
3039
|
const type = fieldConfig.type;
|
|
2971
3040
|
const ref = type.kind === "List" ? type.type.kind === "Object" ? type.type.ref : void 0 : type.kind === "Object" ? type.ref : void 0;
|
|
2972
3041
|
if (!ref) return void 0;
|
|
2973
3042
|
return buildCache.getTypeConfig(ref, "Object").pothosOptions;
|
|
2974
3043
|
}
|
|
2975
|
-
|
|
2976
|
-
//#region lib/helpers/registerPlugin.ts
|
|
3044
|
+
// lib/helpers/registerPlugin.ts
|
|
2977
3045
|
const registered = /* @__PURE__ */ new Set();
|
|
2978
3046
|
function registerPluginOnce(name, plugin) {
|
|
2979
3047
|
if (registered.has(name)) return;
|
|
@@ -2981,15 +3049,13 @@ function registerPluginOnce(name, plugin) {
|
|
|
2981
3049
|
_pothos_core.default.registerPlugin(name, plugin);
|
|
2982
3050
|
registered.add(name);
|
|
2983
3051
|
}
|
|
2984
|
-
|
|
2985
|
-
//#region lib/columnMaskPlugin/maskTypes.ts
|
|
3052
|
+
// lib/columnMaskPlugin/maskTypes.ts
|
|
2986
3053
|
const maskColumnsKey = "maskColumns";
|
|
2987
3054
|
const maskColumnsActionKey = "maskColumnsAction";
|
|
2988
3055
|
const maskPrimaryKeysKey = "maskPrimaryKeys";
|
|
2989
3056
|
const maskRelationsKey = "maskRelations";
|
|
2990
3057
|
const columnMaskPluginName = "ColumnMaskPlugin";
|
|
2991
|
-
|
|
2992
|
-
//#region lib/columnMaskPlugin/columnMaskPlugin.ts
|
|
3058
|
+
// lib/columnMaskPlugin/columnMaskPlugin.ts
|
|
2993
3059
|
var ColumnMaskPlugin = class extends _pothos_core.BasePlugin {
|
|
2994
3060
|
wrapResolve(resolver, fieldConfig) {
|
|
2995
3061
|
return this.maskResult(this.maskRelation(this.maskPrimaryKey(resolver, fieldConfig), fieldConfig), fieldConfig);
|
|
@@ -3028,8 +3094,7 @@ var ColumnMaskPlugin = class extends _pothos_core.BasePlugin {
|
|
|
3028
3094
|
function registerColumnMaskPlugin() {
|
|
3029
3095
|
registerPluginOnce(columnMaskPluginName, ColumnMaskPlugin);
|
|
3030
3096
|
}
|
|
3031
|
-
|
|
3032
|
-
//#region lib/helpers/abilityAwareClient.ts
|
|
3097
|
+
// lib/helpers/abilityAwareClient.ts
|
|
3033
3098
|
function createAbilityAwareClient({ db, abilityBuilder }) {
|
|
3034
3099
|
return (context) => {
|
|
3035
3100
|
const apis = /* @__PURE__ */ new Map();
|
|
@@ -3073,11 +3138,31 @@ function createAbilityAwareClient({ db, abilityBuilder }) {
|
|
|
3073
3138
|
} });
|
|
3074
3139
|
};
|
|
3075
3140
|
}
|
|
3076
|
-
|
|
3077
|
-
|
|
3141
|
+
// lib/refreshAbilitiesPlugin/refreshAbilitiesPlugin.ts
|
|
3142
|
+
const refreshAbilitiesPluginName = "RefreshAbilitiesPlugin";
|
|
3143
|
+
/**
|
|
3144
|
+
* Starts a new snapshot of the resolved relational rules whenever a root
|
|
3145
|
+
* field (query, mutation or subscription event) starts to resolve, see
|
|
3146
|
+
* `resolveRelationalRules`. A mutation's second root field sees what the first
|
|
3147
|
+
* wrote, and a live query refetching sees the rows related to the caller by
|
|
3148
|
+
* now. A no-op unless rules are resolved.
|
|
3149
|
+
*/
|
|
3150
|
+
var RefreshAbilitiesPlugin = class extends _pothos_core.BasePlugin {
|
|
3151
|
+
wrapResolve(resolver, fieldConfig) {
|
|
3152
|
+
const { kind } = this.buildCache.getTypeConfig(fieldConfig.parentType);
|
|
3153
|
+
if (kind !== "Query" && kind !== "Mutation" && kind !== "Subscription") return resolver;
|
|
3154
|
+
return (parent, args, context, info) => {
|
|
3155
|
+
refreshAbilities(context?.abilities);
|
|
3156
|
+
return resolver(parent, args, context, info);
|
|
3157
|
+
};
|
|
3158
|
+
}
|
|
3159
|
+
};
|
|
3160
|
+
function registerRefreshAbilitiesPlugin() {
|
|
3161
|
+
registerPluginOnce(refreshAbilitiesPluginName, RefreshAbilitiesPlugin);
|
|
3162
|
+
}
|
|
3163
|
+
// lib/runtimeFiltersPlugin/filterTypes.ts
|
|
3078
3164
|
const pluginName = "RuntimeFiltersPlugin";
|
|
3079
|
-
|
|
3080
|
-
//#region lib/runtimeFiltersPlugin/runtimeFiltersPlugin.ts
|
|
3165
|
+
// lib/runtimeFiltersPlugin/runtimeFiltersPlugin.ts
|
|
3081
3166
|
const applyFiltersKey = "applyFilters";
|
|
3082
3167
|
var RuntimeFiltersPlugin = class extends _pothos_core.BasePlugin {
|
|
3083
3168
|
tracer;
|
|
@@ -3179,8 +3264,7 @@ var RuntimeFiltersPlugin = class extends _pothos_core.BasePlugin {
|
|
|
3179
3264
|
function registerRuntimeFiltersPlugin() {
|
|
3180
3265
|
registerPluginOnce(pluginName, RuntimeFiltersPlugin);
|
|
3181
3266
|
}
|
|
3182
|
-
|
|
3183
|
-
//#region lib/scalars/addressData.ts
|
|
3267
|
+
// lib/scalars/addressData.ts
|
|
3184
3268
|
/*! Address data derived from Google's Address Data Service (https://github.com/google/libaddressinput),
|
|
3185
3269
|
* licensed under CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/).
|
|
3186
3270
|
* Changes: reduced to required fields, postal code patterns and examples, and regions with
|
|
@@ -8992,8 +9076,7 @@ const addressData = {
|
|
|
8992
9076
|
},
|
|
8993
9077
|
ZW: { require: "AC" }
|
|
8994
9078
|
};
|
|
8995
|
-
|
|
8996
|
-
//#region lib/scalars/addressValidation.ts
|
|
9079
|
+
// lib/scalars/addressValidation.ts
|
|
8997
9080
|
const REQUIRED_FIELD_PATHS = {
|
|
8998
9081
|
A: "streetAddress",
|
|
8999
9082
|
C: "locality",
|
|
@@ -9123,8 +9206,7 @@ const addressValidationSchema = zod.z.object({
|
|
|
9123
9206
|
message: issue.message
|
|
9124
9207
|
});
|
|
9125
9208
|
});
|
|
9126
|
-
|
|
9127
|
-
//#region lib/scalars/address.ts
|
|
9209
|
+
// lib/scalars/address.ts
|
|
9128
9210
|
function implementDefaultAddressTypes(schemaBuilder) {
|
|
9129
9211
|
return {
|
|
9130
9212
|
Address: schemaBuilder.objectRef("Address").implement({
|
|
@@ -9150,8 +9232,7 @@ function implementDefaultAddressTypes(schemaBuilder) {
|
|
|
9150
9232
|
})
|
|
9151
9233
|
};
|
|
9152
9234
|
}
|
|
9153
|
-
|
|
9154
|
-
//#region lib/scalars/emailAddress.ts
|
|
9235
|
+
// lib/scalars/emailAddress.ts
|
|
9155
9236
|
/**
|
|
9156
9237
|
* Validates an email address using graphql-scalars' own format check, then lowercases it, exactly
|
|
9157
9238
|
* as the `EmailAddress` scalar does. Exported for values that do not arrive as GraphQL input,
|
|
@@ -9177,8 +9258,7 @@ const EmailAddressResolver = new graphql.GraphQLScalarType({
|
|
|
9177
9258
|
return normalizeEmailAddress(ast.value);
|
|
9178
9259
|
}
|
|
9179
9260
|
});
|
|
9180
|
-
|
|
9181
|
-
//#region lib/scalars/personName.ts
|
|
9261
|
+
// lib/scalars/personName.ts
|
|
9182
9262
|
const MAX_LENGTH = 200;
|
|
9183
9263
|
const NAME_REGEX = /^[\p{L}\p{M}]+(?:(?:[ '-]|\.\x20?)[\p{L}\p{M}]+)*\.?$/u;
|
|
9184
9264
|
const APOSTROPHE_VARIANTS = /[\u2018\u2019\u02BC\u00B4\u0060]/gu;
|
|
@@ -9207,8 +9287,7 @@ const PersonNameResolver = new graphql.GraphQLScalarType({
|
|
|
9207
9287
|
return normalizePersonName(ast.value);
|
|
9208
9288
|
}
|
|
9209
9289
|
});
|
|
9210
|
-
|
|
9211
|
-
//#region lib/scalars/phoneNumber.ts
|
|
9290
|
+
// lib/scalars/phoneNumber.ts
|
|
9212
9291
|
/**
|
|
9213
9292
|
* Parses and validates a phone number using libphonenumber-js (Google's phone number metadata),
|
|
9214
9293
|
* which checks real per-country validity (length, area code plausibility, ...) rather than just
|
|
@@ -9245,16 +9324,17 @@ const PhoneNumberResolver = new graphql.GraphQLScalarType({
|
|
|
9245
9324
|
return parsePhoneNumber(ast.value);
|
|
9246
9325
|
}
|
|
9247
9326
|
});
|
|
9248
|
-
|
|
9249
|
-
//#region lib/schemaBuilder.ts
|
|
9327
|
+
// lib/schemaBuilder.ts
|
|
9250
9328
|
const createSchemaBuilder = ({ db, pubsub, pothosConfig, otel, logger, validation, abilityBuilder }) => {
|
|
9251
9329
|
const createSpan = otel?.enabled && otel.tracer ? (0, _pothos_tracing_opentelemetry.createOpenTelemetryWrapper)(otel.tracer, otel.options) : void 0;
|
|
9252
9330
|
registerRuntimeFiltersPlugin();
|
|
9253
9331
|
registerColumnMaskPlugin();
|
|
9332
|
+
registerRefreshAbilitiesPlugin();
|
|
9254
9333
|
const schemaBuilder = new _pothos_core.default({
|
|
9255
9334
|
...pothosConfig,
|
|
9256
9335
|
plugins: [
|
|
9257
9336
|
columnMaskPluginName,
|
|
9337
|
+
refreshAbilitiesPluginName,
|
|
9258
9338
|
pluginName,
|
|
9259
9339
|
_pothos_plugin_drizzle.default,
|
|
9260
9340
|
_pothos_plugin_smart_subscriptions.default,
|
|
@@ -9330,8 +9410,7 @@ const createSchemaBuilder = ({ db, pubsub, pothosConfig, otel, logger, validatio
|
|
|
9330
9410
|
schemaBuilder.mutationType({});
|
|
9331
9411
|
return { schemaBuilder };
|
|
9332
9412
|
};
|
|
9333
|
-
|
|
9334
|
-
//#region lib/rumble.ts
|
|
9413
|
+
// lib/rumble.ts
|
|
9335
9414
|
/**
|
|
9336
9415
|
* Mirrors sofa's own default error handler: it derives the HTTP status from
|
|
9337
9416
|
* `extensions.http` and returns the errors as JSON. rumble only adds telemetry
|
|
@@ -9659,7 +9738,6 @@ export const r = rumble({
|
|
|
9659
9738
|
buildSchema: builtSchema
|
|
9660
9739
|
};
|
|
9661
9740
|
};
|
|
9662
|
-
//#endregion
|
|
9663
9741
|
exports.RumbleError = RumbleError;
|
|
9664
9742
|
exports.RumbleErrorSafe = RumbleErrorSafe;
|
|
9665
9743
|
exports.addressChecks = addressChecks;
|
|
@@ -9677,6 +9755,7 @@ exports.normalizeAddress = normalizeAddress;
|
|
|
9677
9755
|
exports.normalizeEmailAddress = normalizeEmailAddress;
|
|
9678
9756
|
exports.normalizePersonName = normalizePersonName;
|
|
9679
9757
|
exports.parsePhoneNumber = parsePhoneNumber;
|
|
9758
|
+
exports.refreshAbilities = refreshAbilities;
|
|
9680
9759
|
exports.rumble = rumble;
|
|
9681
9760
|
exports.validateAddress = validateAddress;
|
|
9682
9761
|
|