graphile-settings
Version:
graphile settings
196 lines (195 loc) • 8.09 kB
JavaScript
import { BucketProvisionerPreset } from 'graphile-bucket-provisioner-plugin';
import { BulkMutationPreset } from 'graphile-bulk-mutations';
import { ConnectionFilterPreset } from 'graphile-connection-filter';
import { I18nPreset } from 'graphile-i18n';
import { createFolderOperatorFactory, GraphileLtreePreset } from 'graphile-ltree';
import { PgAggregatesPreset } from 'graphile-pg-aggregates';
import { createPostgisOperatorFactory, GraphilePostgisPreset } from 'graphile-postgis';
import { PresignedUrlPreset } from 'graphile-presigned-url-plugin';
import { RealtimeSubscriptionsPreset } from 'graphile-realtime-subscriptions';
import { createMatchesOperatorFactory, createTrgmOperatorFactories, UnifiedSearchPreset } from 'graphile-search';
import { GraphileLlmPreset } from 'graphile-llm';
import { UploadPreset } from 'graphile-upload-plugin';
import { getBucketProvisionerConnection } from '../bucket-provisioner-resolver';
import { ConflictDetectorPreset, EnableAllFilterColumnsPreset, InflectorLoggerPreset, InflektPreset, ManyToManyOptInPreset, MetaSchemaPreset, MinimalPreset, NoUniqueLookupPreset, PgTypeMappingsPreset, RequiredInputPreset } from '../plugins';
import { createBucketNameResolver, createEnsureBucketProvisioned, getAllowedOrigins, getPresignedUrlS3Config } from '../presigned-url-resolver';
import { constructiveUploadFieldDefinitions } from '../upload-resolver';
const DEFAULTS = {
enableAggregates: false,
enablePostgis: true,
enableSearch: true,
enableDirectUploads: true,
enablePresignedUploads: true,
enableManyToMany: true,
enableConnectionFilter: true,
enableLtree: true,
enableLlm: true,
enableRealtime: false,
enableBulk: false,
enableI18n: false
};
/**
* Create a Constructive PostGraphile v5 Preset.
*
* Accepts optional feature flags (`ConstructivePresetOptions`) that map 1-to-1
* with the `database_settings` / `api_settings` tables. When a flag is `true`
* its corresponding plugin preset is included; when `false` it is omitted.
*
* Calling with no arguments produces the same preset as the previous static
* `ConstructivePreset` (everything on except aggregates).
*
* CORE PRESETS (always included):
* - MinimalPreset (PostGraphile without Node/Relay)
* - ConflictDetectorPreset (multi-schema conflict detection)
* - InflektPreset (custom inflection)
* - InflectorLoggerPreset (debugging, INFLECTOR_LOG=1)
* - NoUniqueLookupPreset (primary-key-only lookups)
* - MetaSchemaPreset (_meta introspection)
* - PgTypeMappingsPreset (email, url, etc.)
* - RequiredInputPreset (@requiredInput support)
*
* FLAG-CONTROLLED PRESETS:
* - enableConnectionFilter -> ConnectionFilterPreset, EnableAllFilterColumnsPreset
* - enableManyToMany -> ManyToManyOptInPreset
* - enableSearch -> UnifiedSearchPreset (tsvector, BM25, pg_trgm, pgvector)
* - enablePostgis -> GraphilePostgisPreset
* - enableLtree -> GraphileLtreePreset
* - enableDirectUploads -> UploadPreset
* - enablePresignedUploads -> PresignedUrlPreset, BucketProvisionerPreset
* - enableAggregates -> PgAggregatesPreset (off by default)
* - enableRealtime -> RealtimeSubscriptionsPreset (off by default)
* - enableBulk -> BulkMutationPreset (off by default)
* - enableI18n -> I18nPreset (off by default)
* - enableLlm -> GraphileLlmPreset (auto-embed unifiedSearch, vector text fields)
*
* RELATION FILTERS (when enableConnectionFilter is true):
* - Forward: filter child by parent
* - Backward: filter parent by children
*
* USAGE:
* ```typescript
* import { createConstructivePreset, makePgService } from 'graphile-settings';
*
* // All defaults (same as previous static ConstructivePreset)
* const preset = {
* extends: [createConstructivePreset()],
* pgServices: [makePgService({ connectionString, schemas })],
* };
*
* // With database_settings feature flags
* const preset = {
* extends: [createConstructivePreset({ enableAggregates: true, enablePostgis: false })],
* pgServices: [makePgService({ connectionString, schemas })],
* };
* ```
*/
export function createConstructivePreset(options) {
const opts = { ...DEFAULTS, ...options };
// ----- extends array -----
const presets = [
// Core (always on)
MinimalPreset,
ConflictDetectorPreset,
InflektPreset,
InflectorLoggerPreset,
NoUniqueLookupPreset,
MetaSchemaPreset,
PgTypeMappingsPreset,
RequiredInputPreset
];
if (opts.enableConnectionFilter) {
presets.push(ConnectionFilterPreset({ connectionFilterRelations: true }), EnableAllFilterColumnsPreset);
}
if (opts.enableManyToMany) {
presets.push(ManyToManyOptInPreset);
}
if (opts.enableSearch) {
presets.push(UnifiedSearchPreset({ fullTextScalarName: 'FullText', tsConfig: 'english' }));
}
if (opts.enablePostgis) {
presets.push(GraphilePostgisPreset);
}
if (opts.enableLtree) {
presets.push(GraphileLtreePreset);
}
if (opts.enableDirectUploads) {
presets.push(UploadPreset({
uploadFieldDefinitions: constructiveUploadFieldDefinitions,
maxFileSize: 10 * 1024 * 1024 // 10MB
}));
}
if (opts.enablePresignedUploads) {
presets.push(PresignedUrlPreset({
s3: getPresignedUrlS3Config,
resolveBucketName: createBucketNameResolver(),
ensureBucketProvisioned: createEnsureBucketProvisioned()
}), BucketProvisionerPreset({
connection: getBucketProvisionerConnection,
allowedOrigins: getAllowedOrigins()
}));
}
if (opts.enableAggregates) {
presets.push(PgAggregatesPreset);
}
if (opts.enableRealtime) {
presets.push(RealtimeSubscriptionsPreset());
}
if (opts.enableBulk) {
presets.push(BulkMutationPreset());
}
if (opts.enableI18n) {
presets.push(I18nPreset());
}
if (opts.enableLlm) {
presets.push(GraphileLlmPreset());
}
// ----- connectionFilterOperatorFactories -----
// Only include operator factories for features that are actually enabled.
// graphile-config replaces (not concatenates) arrays when merging presets,
// so we collect all active factories into a single top-level array.
const operatorFactories = [];
if (opts.enableConnectionFilter) {
if (opts.enableSearch) {
operatorFactories.push(createMatchesOperatorFactory('FullText', 'english'), createTrgmOperatorFactories());
}
if (opts.enablePostgis) {
operatorFactories.push(createPostgisOperatorFactory());
}
if (opts.enableLtree) {
operatorFactories.push(createFolderOperatorFactory());
}
}
// ----- disablePlugins -----
// When connection filter is enabled it replaces the built-in condition arg.
const disablePlugins = [];
if (opts.enableConnectionFilter) {
disablePlugins.push('PgConditionArgumentPlugin', 'PgConditionCustomFieldsPlugin');
}
// ----- schema options -----
const schema = {};
if (opts.enableConnectionFilter) {
schema.connectionFilterComputedColumns = false;
schema.connectionFilterSetofFunctions = false;
schema.connectionFilterLogicalOperators = true;
schema.connectionFilterArrays = true;
if (operatorFactories.length > 0) {
schema.connectionFilterOperatorFactories = operatorFactories;
}
}
const preset = {
extends: presets
};
if (disablePlugins.length > 0) {
preset.disablePlugins = disablePlugins;
}
if (Object.keys(schema).length > 0) {
preset.schema = schema;
}
return preset;
}
/**
* Default Constructive preset -- everything enabled except aggregates.
* Backwards-compatible: identical to the previous static ConstructivePreset.
*/
export const ConstructivePreset = createConstructivePreset();
export default ConstructivePreset;