@m1212e/rumble 0.16.15 → 0.16.17
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/out/index.cjs +113 -41
- package/out/index.cjs.map +1 -1
- package/out/index.d.cts +41 -27
- package/out/index.d.cts.map +1 -1
- package/out/index.d.mts +41 -27
- package/out/index.d.mts.map +1 -1
- package/out/index.mjs +112 -41
- package/out/index.mjs.map +1 -1
- package/package.json +5 -1
package/out/index.cjs
CHANGED
|
@@ -31,6 +31,7 @@ const require_generate = require('./generate-9zSO5f7n.cjs');
|
|
|
31
31
|
let graphql = require("graphql");
|
|
32
32
|
let _escape_tech_graphql_armor = require("@escape.tech/graphql-armor");
|
|
33
33
|
let _graphql_yoga_plugin_disable_introspection = require("@graphql-yoga/plugin-disable-introspection");
|
|
34
|
+
let _pothos_tracing_opentelemetry = require("@pothos/tracing-opentelemetry");
|
|
34
35
|
let es_toolkit = require("es-toolkit");
|
|
35
36
|
let graphql_yoga = require("graphql-yoga");
|
|
36
37
|
let sofa_api = require("sofa-api");
|
|
@@ -47,6 +48,8 @@ let _pothos_plugin_drizzle = require("@pothos/plugin-drizzle");
|
|
|
47
48
|
_pothos_plugin_drizzle = __toESM(_pothos_plugin_drizzle);
|
|
48
49
|
let _pothos_plugin_smart_subscriptions = require("@pothos/plugin-smart-subscriptions");
|
|
49
50
|
_pothos_plugin_smart_subscriptions = __toESM(_pothos_plugin_smart_subscriptions);
|
|
51
|
+
let _pothos_plugin_tracing = require("@pothos/plugin-tracing");
|
|
52
|
+
_pothos_plugin_tracing = __toESM(_pothos_plugin_tracing);
|
|
50
53
|
let graphql_scalars = require("graphql-scalars");
|
|
51
54
|
|
|
52
55
|
//#region lib/types/rumbleError.ts
|
|
@@ -374,7 +377,7 @@ Warning! No abilities have been registered for
|
|
|
374
377
|
but has been accessed. This will block everything. If this is intended, you can ignore this warning. If not, please ensure that you register the ability in your ability builder.
|
|
375
378
|
`);
|
|
376
379
|
}, 1e3);
|
|
377
|
-
const createAbilityBuilder = ({ db, actions, defaultLimit }) => {
|
|
380
|
+
const createAbilityBuilder = ({ db, actions, defaultLimit, otel }) => {
|
|
378
381
|
let hasBeenBuilt = false;
|
|
379
382
|
const createBuilderForTable = () => {
|
|
380
383
|
const queryFilters = /* @__PURE__ */ new Map();
|
|
@@ -506,27 +509,49 @@ const createAbilityBuilder = ({ db, actions, defaultLimit }) => {
|
|
|
506
509
|
}
|
|
507
510
|
return { withContext: (userContext) => {
|
|
508
511
|
return { filter: (action) => {
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
512
|
+
const assembleAbilities = (span) => {
|
|
513
|
+
const filters = queryFilters.get(action);
|
|
514
|
+
if (filters === "unrestricted") {
|
|
515
|
+
span?.setAttribute("abilities.status", "unrestricted");
|
|
516
|
+
return transformToResponse();
|
|
517
|
+
}
|
|
518
|
+
if (!filters) {
|
|
519
|
+
span?.setAttribute("abilities.status", "blocked_everything");
|
|
520
|
+
nothingRegisteredWarningLogger(tableName.toString(), action);
|
|
521
|
+
return transformToResponse(blockEverythingFilter);
|
|
522
|
+
}
|
|
523
|
+
const dynamicResults = new Array(dynamicQueryFilters[action].length);
|
|
524
|
+
let filtersReturned = 0;
|
|
525
|
+
for (let i = 0; i < dynamicQueryFilters[action].length; i++) {
|
|
526
|
+
const func = dynamicQueryFilters[action][i];
|
|
527
|
+
const result = func(userContext);
|
|
528
|
+
if (result === "allow") return transformToResponse();
|
|
529
|
+
if (result === void 0) continue;
|
|
530
|
+
dynamicResults[filtersReturned++] = result;
|
|
531
|
+
}
|
|
532
|
+
dynamicResults.length = filtersReturned;
|
|
533
|
+
span?.setAttribute("abilities.dynamic", dynamicResults.length);
|
|
534
|
+
span?.setAttribute("abilities.static", simpleQueryFilters[action].length);
|
|
535
|
+
const allQueryFilters = [...simpleQueryFilters[action], ...dynamicResults];
|
|
536
|
+
span?.setAttribute("abilities.total", allQueryFilters.length);
|
|
537
|
+
if (allQueryFilters.length === 0) {
|
|
538
|
+
span?.setAttribute("abilities.status", "blocked_everything");
|
|
539
|
+
return transformToResponse(blockEverythingFilter);
|
|
540
|
+
}
|
|
541
|
+
const mergedFilters = allQueryFilters.length === 1 ? allQueryFilters[0] : allQueryFilters.reduce((a, b) => {
|
|
542
|
+
return mergeFilters(a, b);
|
|
543
|
+
}, {});
|
|
544
|
+
span?.setAttribute("abilities.status", "applied");
|
|
545
|
+
return transformToResponse(mergedFilters);
|
|
546
|
+
};
|
|
547
|
+
if (otel?.tracer) return otel.tracer.startActiveSpan(`prepare_query_abilities_${action}`, (span) => {
|
|
548
|
+
try {
|
|
549
|
+
return assembleAbilities(span);
|
|
550
|
+
} finally {
|
|
551
|
+
span.end();
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
else return assembleAbilities();
|
|
530
555
|
} };
|
|
531
556
|
} };
|
|
532
557
|
};
|
|
@@ -949,6 +974,10 @@ async function initSearchIfApplicable(input) {
|
|
|
949
974
|
const dbName = (await input.db.execute(drizzle_orm.sql`SELECT current_database()`)).rows[0].current_database;
|
|
950
975
|
await input.db.execute(drizzle_orm.sql.raw(`ALTER DATABASE ${dbName} SET pg_trgm.similarity_threshold = ${threshold};`));
|
|
951
976
|
}
|
|
977
|
+
if (input.search?.cpu_operator_cost) {
|
|
978
|
+
if (typeof input.search.cpu_operator_cost !== "number") throw new Error(`CPU operator cost must be a number`);
|
|
979
|
+
if (input.search.cpu_operator_cost <= 0) throw new Error(`CPU operator cost must be a positive number`);
|
|
980
|
+
}
|
|
952
981
|
}
|
|
953
982
|
/**
|
|
954
983
|
* Performs adjustments to the query args to issue a full text search in case the
|
|
@@ -1274,8 +1303,8 @@ const createQueryImplementer = ({ db, schemaBuilder, search, whereArgImplementer
|
|
|
1274
1303
|
if (mappedArgs.orderBy) filter.orderBy = mappedArgs.orderBy;
|
|
1275
1304
|
const queryInstance = query(filter);
|
|
1276
1305
|
if (filter.columns) queryInstance.columns = filter.columns;
|
|
1277
|
-
if (search?.cpu_operator_cost) return db.transaction(async (tx) => {
|
|
1278
|
-
if (isPostgresDB(tx)) await tx.execute(drizzle_orm.sql`SET
|
|
1306
|
+
if (search?.enabled && args.search && args.search.length > 0 && search?.cpu_operator_cost) return db.transaction(async (tx) => {
|
|
1307
|
+
if (isPostgresDB(tx)) await tx.execute(drizzle_orm.sql.raw(`SET cpu_operator_cost = ${search.cpu_operator_cost};`));
|
|
1279
1308
|
else console.info("Database dialect is not postgresql, cannot set cpu_operator_cost.");
|
|
1280
1309
|
return tx.query[table].findMany(queryInstance);
|
|
1281
1310
|
});
|
|
@@ -1427,22 +1456,43 @@ const applyFilters = async ({ filters, entities, context }) => {
|
|
|
1427
1456
|
//#region lib/runtimeFiltersPlugin/runtimeFiltersPlugin.ts
|
|
1428
1457
|
const applyFiltersKey = "applyFilters";
|
|
1429
1458
|
var RuntimeFiltersPlugin = class extends _pothos_core.BasePlugin {
|
|
1459
|
+
tracer;
|
|
1460
|
+
onTypeConfig(typeConfig) {
|
|
1461
|
+
this.tracer = this.builder.options.otelTracer;
|
|
1462
|
+
return typeConfig;
|
|
1463
|
+
}
|
|
1430
1464
|
wrapResolve(resolver, fieldConfig) {
|
|
1431
1465
|
return async (parent, args, context, info) => {
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1466
|
+
const runFilters = async (span) => {
|
|
1467
|
+
let filters;
|
|
1468
|
+
const fieldType = fieldConfig?.type;
|
|
1469
|
+
if (fieldType.kind === "List") filters = fieldType.type?.ref.currentConfig.pothosOptions[applyFiltersKey];
|
|
1470
|
+
else if (fieldType.kind === "Object") filters = fieldType.ref.currentConfig.pothosOptions[applyFiltersKey];
|
|
1471
|
+
if (!filters || !Array.isArray(filters) || filters.length === 0) {
|
|
1472
|
+
span?.setAttribute("filters.status", "unrestricted");
|
|
1473
|
+
return resolver(parent, args, context, info);
|
|
1474
|
+
}
|
|
1475
|
+
const resolved = await resolver(parent, args, context, info);
|
|
1476
|
+
const allResolvedValues = Array.isArray(resolved) ? resolved : [resolved];
|
|
1477
|
+
const allFilters = Array.isArray(filters) ? filters : [filters];
|
|
1478
|
+
span?.setAttribute("filters.total", allFilters.length);
|
|
1479
|
+
const allowed = await applyFilters({
|
|
1480
|
+
filters: allFilters,
|
|
1481
|
+
entities: allResolvedValues,
|
|
1482
|
+
context
|
|
1483
|
+
});
|
|
1484
|
+
span?.setAttribute("filters.allowed", allowed.length);
|
|
1485
|
+
if (Array.isArray(resolved)) return allowed;
|
|
1486
|
+
return allowed[0] ?? null;
|
|
1487
|
+
};
|
|
1488
|
+
if (this.tracer) return this.tracer.startActiveSpan(`apply_filters_${fieldConfig.name}`, async (span) => {
|
|
1489
|
+
try {
|
|
1490
|
+
return await runFilters();
|
|
1491
|
+
} finally {
|
|
1492
|
+
span.end();
|
|
1493
|
+
}
|
|
1443
1494
|
});
|
|
1444
|
-
|
|
1445
|
-
return allowed[0] ?? null;
|
|
1495
|
+
else return runFilters();
|
|
1446
1496
|
};
|
|
1447
1497
|
}
|
|
1448
1498
|
};
|
|
@@ -1456,7 +1506,8 @@ function registerRuntimeFiltersPlugin() {
|
|
|
1456
1506
|
|
|
1457
1507
|
//#endregion
|
|
1458
1508
|
//#region lib/schemaBuilder.ts
|
|
1459
|
-
const createSchemaBuilder = ({ db, disableDefaultObjects, pubsub, pothosConfig }) => {
|
|
1509
|
+
const createSchemaBuilder = ({ db, disableDefaultObjects, pubsub, pothosConfig, otel }) => {
|
|
1510
|
+
const createSpan = otel?.tracer ? (0, _pothos_tracing_opentelemetry.createOpenTelemetryWrapper)(otel.tracer, otel.options) : void 0;
|
|
1460
1511
|
registerRuntimeFiltersPlugin();
|
|
1461
1512
|
const schemaBuilder = new _pothos_core.default({
|
|
1462
1513
|
...pothosConfig,
|
|
@@ -1464,6 +1515,7 @@ const createSchemaBuilder = ({ db, disableDefaultObjects, pubsub, pothosConfig }
|
|
|
1464
1515
|
pluginName,
|
|
1465
1516
|
_pothos_plugin_drizzle.default,
|
|
1466
1517
|
_pothos_plugin_smart_subscriptions.default,
|
|
1518
|
+
_pothos_plugin_tracing.default,
|
|
1467
1519
|
...pothosConfig?.plugins ?? []
|
|
1468
1520
|
],
|
|
1469
1521
|
drizzle: {
|
|
@@ -1479,7 +1531,12 @@ const createSchemaBuilder = ({ db, disableDefaultObjects, pubsub, pothosConfig }
|
|
|
1479
1531
|
smartSubscriptions: { ...(0, _pothos_plugin_smart_subscriptions.subscribeOptionsFromIterator)((name, _context) => {
|
|
1480
1532
|
return pubsub.subscribe(name);
|
|
1481
1533
|
}) },
|
|
1482
|
-
defaultFieldNullability: false
|
|
1534
|
+
defaultFieldNullability: false,
|
|
1535
|
+
tracing: {
|
|
1536
|
+
default: otel?.tracer ? (config) => (0, _pothos_plugin_tracing.isRootField)(config) : () => false,
|
|
1537
|
+
wrap: createSpan ? (resolver, options) => createSpan(resolver, options) : (resolver) => resolver
|
|
1538
|
+
},
|
|
1539
|
+
otelTracer: otel?.tracer
|
|
1483
1540
|
});
|
|
1484
1541
|
schemaBuilder.addScalarType("JSON", graphql_scalars.JSONResolver);
|
|
1485
1542
|
schemaBuilder.addScalarType("Date", graphql_scalars.DateResolver);
|
|
@@ -1515,7 +1572,7 @@ export const db = drizzle(
|
|
|
1515
1572
|
"postgres://postgres:postgres@localhost:5432/postgres",
|
|
1516
1573
|
{
|
|
1517
1574
|
relations, // <--- add this line
|
|
1518
|
-
schema,
|
|
1575
|
+
schema,
|
|
1519
1576
|
},
|
|
1520
1577
|
);
|
|
1521
1578
|
|
|
@@ -1578,7 +1635,22 @@ export const db = drizzle(
|
|
|
1578
1635
|
return (0, graphql_yoga.createYoga)({
|
|
1579
1636
|
...args,
|
|
1580
1637
|
graphiql: enableApiDocs,
|
|
1581
|
-
plugins: [
|
|
1638
|
+
plugins: [
|
|
1639
|
+
...args?.plugins ?? [],
|
|
1640
|
+
...enableApiDocs ? [] : [(0, _graphql_yoga_plugin_disable_introspection.useDisableIntrospection)(), (0, _escape_tech_graphql_armor.EnvelopArmorPlugin)()],
|
|
1641
|
+
rumbleInput.otel?.tracer ? { onExecute: ({ setExecuteFn, executeFn }) => {
|
|
1642
|
+
setExecuteFn((options) => rumbleInput.otel.tracer.startActiveSpan(_pothos_tracing_opentelemetry.SpanNames.EXECUTE, { attributes: { [_pothos_tracing_opentelemetry.AttributeNames.OPERATION_NAME]: options.operationName ?? "anonymous" } }, async (span) => {
|
|
1643
|
+
try {
|
|
1644
|
+
return await executeFn(options);
|
|
1645
|
+
} catch (error) {
|
|
1646
|
+
span.recordException(error);
|
|
1647
|
+
throw error;
|
|
1648
|
+
} finally {
|
|
1649
|
+
span.end();
|
|
1650
|
+
}
|
|
1651
|
+
}));
|
|
1652
|
+
} } : false
|
|
1653
|
+
].filter(Boolean),
|
|
1582
1654
|
schema: builtSchema(),
|
|
1583
1655
|
context
|
|
1584
1656
|
});
|