graphile-settings 3.1.1 → 4.0.0

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.
Files changed (102) hide show
  1. package/README.md +170 -85
  2. package/esm/index.d.ts +37 -0
  3. package/esm/index.js +54 -103
  4. package/esm/plugins/conflict-detector.d.ts +7 -0
  5. package/esm/plugins/conflict-detector.js +55 -0
  6. package/esm/plugins/custom-inflector.d.ts +9 -0
  7. package/esm/plugins/custom-inflector.js +382 -0
  8. package/esm/plugins/enable-all-filter-columns.d.ts +60 -0
  9. package/esm/plugins/enable-all-filter-columns.js +85 -0
  10. package/esm/plugins/index.d.ts +19 -0
  11. package/esm/plugins/index.js +26 -0
  12. package/esm/plugins/inflector-logger.d.ts +7 -0
  13. package/esm/plugins/inflector-logger.js +215 -0
  14. package/esm/plugins/many-to-many-preset.d.ts +62 -0
  15. package/esm/plugins/many-to-many-preset.js +86 -0
  16. package/esm/plugins/meta-schema/cache.d.ts +4 -0
  17. package/esm/plugins/meta-schema/cache.js +7 -0
  18. package/esm/plugins/meta-schema/constraint-meta-builders.d.ts +13 -0
  19. package/esm/plugins/meta-schema/constraint-meta-builders.js +51 -0
  20. package/esm/plugins/meta-schema/graphql-meta-field.d.ts +4 -0
  21. package/esm/plugins/meta-schema/graphql-meta-field.js +201 -0
  22. package/esm/plugins/meta-schema/inflection-utils.d.ts +4 -0
  23. package/esm/plugins/meta-schema/inflection-utils.js +20 -0
  24. package/esm/plugins/meta-schema/name-meta-builders.d.ts +4 -0
  25. package/esm/plugins/meta-schema/name-meta-builders.js +38 -0
  26. package/esm/plugins/meta-schema/plugin.d.ts +2 -0
  27. package/esm/plugins/meta-schema/plugin.js +23 -0
  28. package/esm/plugins/meta-schema/relation-meta-builders.d.ts +8 -0
  29. package/esm/plugins/meta-schema/relation-meta-builders.js +115 -0
  30. package/esm/plugins/meta-schema/table-meta-builder.d.ts +2 -0
  31. package/esm/plugins/meta-schema/table-meta-builder.js +69 -0
  32. package/esm/plugins/meta-schema/table-meta-context.d.ts +13 -0
  33. package/esm/plugins/meta-schema/table-meta-context.js +11 -0
  34. package/esm/plugins/meta-schema/table-resource-utils.d.ts +12 -0
  35. package/esm/plugins/meta-schema/table-resource-utils.js +50 -0
  36. package/esm/plugins/meta-schema/type-mappings.d.ts +3 -0
  37. package/esm/plugins/meta-schema/type-mappings.js +75 -0
  38. package/esm/plugins/meta-schema/types.d.ts +206 -0
  39. package/esm/plugins/meta-schema/types.js +1 -0
  40. package/esm/plugins/meta-schema.d.ts +19 -0
  41. package/esm/plugins/meta-schema.js +20 -0
  42. package/esm/plugins/minimal-preset.d.ts +7 -0
  43. package/esm/plugins/minimal-preset.js +42 -0
  44. package/esm/plugins/pg-type-mappings.d.ts +41 -0
  45. package/esm/plugins/pg-type-mappings.js +122 -0
  46. package/esm/plugins/primary-key-only.d.ts +96 -0
  47. package/esm/plugins/primary-key-only.js +143 -0
  48. package/esm/presets/constructive-preset.d.ts +40 -0
  49. package/esm/presets/constructive-preset.js +137 -0
  50. package/esm/presets/index.d.ts +7 -0
  51. package/esm/presets/index.js +7 -0
  52. package/index.d.ts +37 -3
  53. package/index.js +56 -129
  54. package/package.json +16 -22
  55. package/plugins/conflict-detector.d.ts +7 -0
  56. package/plugins/conflict-detector.js +58 -0
  57. package/plugins/custom-inflector.d.ts +9 -0
  58. package/plugins/custom-inflector.js +385 -0
  59. package/plugins/enable-all-filter-columns.d.ts +60 -0
  60. package/plugins/enable-all-filter-columns.js +88 -0
  61. package/plugins/index.d.ts +19 -0
  62. package/plugins/index.js +56 -0
  63. package/plugins/inflector-logger.d.ts +7 -0
  64. package/plugins/inflector-logger.js +218 -0
  65. package/plugins/many-to-many-preset.d.ts +62 -0
  66. package/plugins/many-to-many-preset.js +89 -0
  67. package/plugins/meta-schema/cache.d.ts +4 -0
  68. package/plugins/meta-schema/cache.js +12 -0
  69. package/plugins/meta-schema/constraint-meta-builders.d.ts +13 -0
  70. package/plugins/meta-schema/constraint-meta-builders.js +58 -0
  71. package/plugins/meta-schema/graphql-meta-field.d.ts +4 -0
  72. package/plugins/meta-schema/graphql-meta-field.js +204 -0
  73. package/plugins/meta-schema/inflection-utils.d.ts +4 -0
  74. package/plugins/meta-schema/inflection-utils.js +25 -0
  75. package/plugins/meta-schema/name-meta-builders.d.ts +4 -0
  76. package/plugins/meta-schema/name-meta-builders.js +43 -0
  77. package/plugins/meta-schema/plugin.d.ts +2 -0
  78. package/plugins/meta-schema/plugin.js +26 -0
  79. package/plugins/meta-schema/relation-meta-builders.d.ts +8 -0
  80. package/plugins/meta-schema/relation-meta-builders.js +120 -0
  81. package/plugins/meta-schema/table-meta-builder.d.ts +2 -0
  82. package/plugins/meta-schema/table-meta-builder.js +72 -0
  83. package/plugins/meta-schema/table-meta-context.d.ts +13 -0
  84. package/plugins/meta-schema/table-meta-context.js +15 -0
  85. package/plugins/meta-schema/table-resource-utils.d.ts +12 -0
  86. package/plugins/meta-schema/table-resource-utils.js +60 -0
  87. package/plugins/meta-schema/type-mappings.d.ts +3 -0
  88. package/plugins/meta-schema/type-mappings.js +79 -0
  89. package/plugins/meta-schema/types.d.ts +206 -0
  90. package/plugins/meta-schema/types.js +2 -0
  91. package/plugins/meta-schema.d.ts +19 -0
  92. package/plugins/meta-schema.js +20 -0
  93. package/plugins/minimal-preset.d.ts +7 -0
  94. package/plugins/minimal-preset.js +45 -0
  95. package/plugins/pg-type-mappings.d.ts +41 -0
  96. package/plugins/pg-type-mappings.js +128 -0
  97. package/plugins/primary-key-only.d.ts +96 -0
  98. package/plugins/primary-key-only.js +147 -0
  99. package/presets/constructive-preset.d.ts +40 -0
  100. package/presets/constructive-preset.js +140 -0
  101. package/presets/index.d.ts +7 -0
  102. package/presets/index.js +11 -0
@@ -0,0 +1,4 @@
1
+ import type { InflectionMeta, MetaBuild, PgCodec, PgTableResource, PgUnique, QueryMeta } from './types';
2
+ export declare function resolveTableType(build: MetaBuild, codec: PgCodec): string;
3
+ export declare function buildInflectionMeta(resource: PgTableResource, tableType: string, build: MetaBuild): InflectionMeta;
4
+ export declare function buildQueryMeta(resource: PgTableResource, uniques: PgUnique[], tableType: string, build: MetaBuild): QueryMeta;
@@ -0,0 +1,38 @@
1
+ import { fallbackTableType, safeInflection } from './inflection-utils';
2
+ export function resolveTableType(build, codec) {
3
+ return safeInflection(() => build.inflection.tableType(codec), fallbackTableType(codec.name));
4
+ }
5
+ export function buildInflectionMeta(resource, tableType, build) {
6
+ const inflection = build.inflection;
7
+ return {
8
+ tableType,
9
+ allRows: safeInflection(() => inflection.allRows?.(resource), `${tableType.toLowerCase()}s`),
10
+ connection: safeInflection(() => inflection.connectionType?.(tableType), `${tableType}Connection`),
11
+ edge: safeInflection(() => inflection.edgeType?.(tableType), `${tableType}Edge`),
12
+ filterType: safeInflection(() => inflection.filterType?.(tableType), `${tableType}Filter`),
13
+ orderByType: safeInflection(() => inflection.orderByType?.(tableType), `${tableType}OrderBy`),
14
+ conditionType: safeInflection(() => inflection.conditionType?.(tableType), `${tableType}Condition`),
15
+ patchType: safeInflection(() => inflection.patchType?.(tableType), `${tableType}Patch`),
16
+ createInputType: safeInflection(() => inflection.createInputType?.(resource), `Create${tableType}Input`),
17
+ createPayloadType: safeInflection(() => inflection.createPayloadType?.(resource), `Create${tableType}Payload`),
18
+ updatePayloadType: safeInflection(() => inflection.updatePayloadType?.(resource), `Update${tableType}Payload`),
19
+ deletePayloadType: safeInflection(() => inflection.deletePayloadType?.(resource), `Delete${tableType}Payload`),
20
+ };
21
+ }
22
+ export function buildQueryMeta(resource, uniques, tableType, build) {
23
+ const inflection = build.inflection;
24
+ const hasPrimaryKey = uniques.some((unique) => unique.isPrimary);
25
+ return {
26
+ all: safeInflection(() => inflection.allRows?.(resource), `${tableType.toLowerCase()}s`),
27
+ one: hasPrimaryKey
28
+ ? safeInflection(() => inflection.tableFieldName?.(resource), tableType.toLowerCase())
29
+ : null,
30
+ create: safeInflection(() => inflection.createField?.(resource), `create${tableType}`),
31
+ update: hasPrimaryKey
32
+ ? safeInflection(() => inflection.updateByKeys?.(resource), `update${tableType}`)
33
+ : null,
34
+ delete: hasPrimaryKey
35
+ ? safeInflection(() => inflection.deleteByKeys?.(resource), `delete${tableType}`)
36
+ : null,
37
+ };
38
+ }
@@ -0,0 +1,2 @@
1
+ import type { GraphileConfig } from 'graphile-config';
2
+ export declare const MetaSchemaPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,23 @@
1
+ import { getCachedTablesMeta, setCachedTablesMeta } from './cache';
2
+ import { extendQueryWithMetaField } from './graphql-meta-field';
3
+ import { collectTablesMeta } from './table-meta-builder';
4
+ export const MetaSchemaPlugin = {
5
+ name: 'MetaSchemaPlugin',
6
+ version: '1.0.0',
7
+ description: 'Exposes _meta query for database schema introspection',
8
+ schema: {
9
+ hooks: {
10
+ init(input, rawBuild) {
11
+ const build = rawBuild;
12
+ setCachedTablesMeta(collectTablesMeta(build));
13
+ return input;
14
+ },
15
+ GraphQLObjectType_fields(rawFields, _rawBuild, rawContext) {
16
+ const context = rawContext;
17
+ if (context.Self?.name !== 'Query')
18
+ return rawFields;
19
+ return extendQueryWithMetaField(rawFields, getCachedTablesMeta());
20
+ },
21
+ },
22
+ },
23
+ };
@@ -0,0 +1,8 @@
1
+ import { type BuildContext } from './table-meta-context';
2
+ import type { BelongsToRelation, HasRelation, ManyToManyRelation, PgAttribute, PgCodec, PgRelation, PgTableResource, PgUnique } from './types';
3
+ export declare function buildBelongsToRelations(codec: PgCodec, attributes: Record<string, PgAttribute>, uniques: PgUnique[], relations: Record<string, PgRelation>, context: BuildContext): BelongsToRelation[];
4
+ export declare function buildReverseRelations(codec: PgCodec, attributes: Record<string, PgAttribute>, relations: Record<string, PgRelation>, context: BuildContext): {
5
+ hasOne: HasRelation[];
6
+ hasMany: HasRelation[];
7
+ };
8
+ export declare function buildManyToManyRelations(resource: PgTableResource, codec: PgCodec, context: BuildContext): ManyToManyRelation[];
@@ -0,0 +1,115 @@
1
+ import { safeInflection } from './inflection-utils';
2
+ import { buildForeignKeyConstraint, } from './constraint-meta-builders';
3
+ import { buildFieldList } from './table-meta-context';
4
+ import { getRelation, getResourceCodec, getUniques, sameAttributes, } from './table-resource-utils';
5
+ function isRecord(value) {
6
+ return typeof value === 'object' && value !== null;
7
+ }
8
+ export function buildBelongsToRelations(codec, attributes, uniques, relations, context) {
9
+ const belongsTo = [];
10
+ for (const [relationName, relation] of Object.entries(relations)) {
11
+ if (relation.isReferencee !== false)
12
+ continue;
13
+ const localAttributes = relation.localAttributes || [];
14
+ const isUnique = uniques.some((unique) => sameAttributes(unique.attributes, localAttributes));
15
+ belongsTo.push({
16
+ fieldName: relationName,
17
+ isUnique,
18
+ type: relation.remoteResource?.codec?.name || null,
19
+ keys: buildFieldList(localAttributes, codec, attributes, context),
20
+ references: { name: relation.remoteResource?.codec?.name || 'unknown' },
21
+ });
22
+ }
23
+ return belongsTo;
24
+ }
25
+ export function buildReverseRelations(codec, attributes, relations, context) {
26
+ const hasOne = [];
27
+ const hasMany = [];
28
+ for (const [relationName, relation] of Object.entries(relations)) {
29
+ if (relation.isReferencee !== true)
30
+ continue;
31
+ const remoteUniques = getUniques(relation.remoteResource || {});
32
+ const remoteAttributes = relation.remoteAttributes || [];
33
+ const isUnique = remoteUniques.some((unique) => sameAttributes(unique.attributes, remoteAttributes));
34
+ const meta = {
35
+ fieldName: relationName,
36
+ isUnique,
37
+ type: relation.remoteResource?.codec?.name || null,
38
+ keys: buildFieldList(relation.localAttributes || [], codec, attributes, context),
39
+ referencedBy: { name: relation.remoteResource?.codec?.name || 'unknown' },
40
+ };
41
+ if (isUnique) {
42
+ hasOne.push(meta);
43
+ }
44
+ else {
45
+ hasMany.push(meta);
46
+ }
47
+ }
48
+ return { hasOne, hasMany };
49
+ }
50
+ function isManyToManyDetails(value) {
51
+ if (!isRecord(value))
52
+ return false;
53
+ return (isRecord(value.leftTable) &&
54
+ isRecord(value.junctionTable) &&
55
+ isRecord(value.rightTable) &&
56
+ typeof value.leftRelationName === 'string' &&
57
+ typeof value.rightRelationName === 'string');
58
+ }
59
+ function parseManyToManyRelationships(value) {
60
+ if (!Array.isArray(value))
61
+ return [];
62
+ return value.filter(isManyToManyDetails);
63
+ }
64
+ function getManyToManyRelationships(build, tableResource, codec) {
65
+ const relationshipsByResource = build.pgManyToManyRealtionshipsByResource;
66
+ if (!(relationshipsByResource instanceof Map))
67
+ return [];
68
+ const direct = parseManyToManyRelationships(relationshipsByResource.get(tableResource));
69
+ if (direct.length > 0)
70
+ return direct;
71
+ for (const [leftTable, relationships] of relationshipsByResource.entries()) {
72
+ const details = parseManyToManyRelationships(relationships);
73
+ if (details.length === 0 || !isRecord(leftTable))
74
+ continue;
75
+ if (leftTable.codec === codec) {
76
+ return details;
77
+ }
78
+ }
79
+ return [];
80
+ }
81
+ function buildManyToManyRelation(details, context) {
82
+ const leftCodec = getResourceCodec(details.leftTable);
83
+ const junctionCodec = getResourceCodec(details.junctionTable);
84
+ const rightCodec = getResourceCodec(details.rightTable);
85
+ if (!leftCodec || !junctionCodec || !rightCodec)
86
+ return null;
87
+ const leftRelation = getRelation(details.leftTable, details.leftRelationName);
88
+ const junctionRightRelation = getRelation(details.junctionTable, details.rightRelationName);
89
+ if (!leftRelation || !junctionRightRelation)
90
+ return null;
91
+ const leftJunctionAttributes = leftRelation.remoteAttributes || [];
92
+ const leftTableAttributes = leftRelation.localAttributes || [];
93
+ const rightJunctionAttributes = junctionRightRelation.localAttributes || [];
94
+ const rightTableAttributes = junctionRightRelation.remoteAttributes || [];
95
+ const relationFieldName = safeInflection(() => context.build.inflection._manyToManyRelation?.(details), details.rightRelationName || rightCodec.name || null);
96
+ const junctionLeftConstraint = buildForeignKeyConstraint(details.leftRelationName || `${junctionCodec.name}_${leftCodec.name}_fkey`, junctionCodec, junctionCodec.attributes, leftJunctionAttributes, leftCodec, leftCodec.attributes, leftTableAttributes, context);
97
+ const junctionRightConstraint = buildForeignKeyConstraint(details.rightRelationName || `${junctionCodec.name}_${rightCodec.name}_fkey`, junctionCodec, junctionCodec.attributes, rightJunctionAttributes, rightCodec, rightCodec.attributes, rightTableAttributes, context);
98
+ return {
99
+ fieldName: relationFieldName,
100
+ type: rightCodec.name || null,
101
+ junctionTable: { name: junctionCodec.name || 'unknown' },
102
+ junctionLeftConstraint,
103
+ junctionLeftKeyAttributes: buildFieldList(leftJunctionAttributes, junctionCodec, junctionCodec.attributes, context),
104
+ junctionRightConstraint,
105
+ junctionRightKeyAttributes: buildFieldList(rightJunctionAttributes, junctionCodec, junctionCodec.attributes, context),
106
+ leftKeyAttributes: buildFieldList(leftTableAttributes, leftCodec, leftCodec.attributes, context),
107
+ rightKeyAttributes: buildFieldList(rightTableAttributes, rightCodec, rightCodec.attributes, context),
108
+ rightTable: { name: rightCodec.name || 'unknown' },
109
+ };
110
+ }
111
+ export function buildManyToManyRelations(resource, codec, context) {
112
+ return getManyToManyRelationships(context.build, resource, codec)
113
+ .map((details) => buildManyToManyRelation(details, context))
114
+ .filter((relation) => relation !== null);
115
+ }
@@ -0,0 +1,2 @@
1
+ import type { MetaBuild, TableMeta } from './types';
2
+ export declare function collectTablesMeta(build: MetaBuild): TableMeta[];
@@ -0,0 +1,69 @@
1
+ import { buildForeignKeyConstraints, buildIndexes, buildPrimaryKey, buildUniqueConstraints, } from './constraint-meta-builders';
2
+ import { buildInflectionMeta, buildQueryMeta, resolveTableType } from './name-meta-builders';
3
+ import { buildBelongsToRelations, buildManyToManyRelations, buildReverseRelations, } from './relation-meta-builders';
4
+ import { buildFieldMeta } from './type-mappings';
5
+ import { createBuildContext, } from './table-meta-context';
6
+ import { getConfiguredSchemas, getRelations, getSchemaName, getUniques, isTableResource, } from './table-resource-utils';
7
+ function buildTableMeta(resource, schemaName, context) {
8
+ const codec = resource.codec;
9
+ const attributes = codec.attributes;
10
+ const uniques = getUniques(resource);
11
+ const relations = getRelations(resource);
12
+ const fields = Object.entries(attributes).map(([attrName, attr]) => buildFieldMeta(context.inflectAttr(attrName, codec), attr, context.build));
13
+ const indexes = buildIndexes(codec, attributes, uniques, context);
14
+ const primaryKey = buildPrimaryKey(codec, attributes, uniques, context);
15
+ const uniqueConstraints = buildUniqueConstraints(codec, attributes, uniques, context);
16
+ const foreignKeyConstraints = buildForeignKeyConstraints(codec, attributes, relations, context);
17
+ const constraints = {
18
+ primaryKey,
19
+ unique: uniqueConstraints,
20
+ foreignKey: foreignKeyConstraints,
21
+ };
22
+ const belongsTo = buildBelongsToRelations(codec, attributes, uniques, relations, context);
23
+ const { hasOne, hasMany } = buildReverseRelations(codec, attributes, relations, context);
24
+ const manyToMany = buildManyToManyRelations(resource, codec, context);
25
+ const relationsMeta = {
26
+ belongsTo,
27
+ has: [...hasOne, ...hasMany],
28
+ hasOne,
29
+ hasMany,
30
+ manyToMany,
31
+ };
32
+ const tableType = resolveTableType(context.build, codec);
33
+ return {
34
+ name: tableType,
35
+ schemaName,
36
+ fields,
37
+ indexes,
38
+ constraints,
39
+ foreignKeyConstraints,
40
+ primaryKeyConstraints: primaryKey ? [primaryKey] : [],
41
+ uniqueConstraints,
42
+ relations: relationsMeta,
43
+ inflection: buildInflectionMeta(resource, tableType, context.build),
44
+ query: buildQueryMeta(resource, uniques, tableType, context.build),
45
+ };
46
+ }
47
+ export function collectTablesMeta(build) {
48
+ const configuredSchemas = getConfiguredSchemas(build);
49
+ const context = createBuildContext(build);
50
+ const seenCodecs = new Set();
51
+ const tablesMeta = [];
52
+ for (const resource of Object.values(build.input.pgRegistry.pgResources || {})) {
53
+ if (!isTableResource(resource))
54
+ continue;
55
+ const codec = resource.codec;
56
+ if (seenCodecs.has(codec))
57
+ continue;
58
+ seenCodecs.add(codec);
59
+ const schemaName = getSchemaName(resource);
60
+ if (!schemaName)
61
+ continue;
62
+ if (configuredSchemas.length > 0 &&
63
+ !configuredSchemas.includes(schemaName)) {
64
+ continue;
65
+ }
66
+ tablesMeta.push(buildTableMeta(resource, schemaName, context));
67
+ }
68
+ return tablesMeta;
69
+ }
@@ -0,0 +1,13 @@
1
+ import type { FieldMeta, MetaBuild, PgAttribute, PgCodec, PgTableResource } from './types';
2
+ export type AttributeInflector = (attrName: string, codec: PgCodec) => string;
3
+ export interface BuildContext {
4
+ build: MetaBuild;
5
+ inflectAttr: AttributeInflector;
6
+ }
7
+ export type TableResourceWithCodec = PgTableResource & {
8
+ codec: PgCodec & {
9
+ attributes: Record<string, PgAttribute>;
10
+ };
11
+ };
12
+ export declare function createBuildContext(build: MetaBuild): BuildContext;
13
+ export declare function buildFieldList(attrNames: string[], codec: PgCodec, attributes: Record<string, PgAttribute>, context: BuildContext): FieldMeta[];
@@ -0,0 +1,11 @@
1
+ import { createAttributeInflector } from './inflection-utils';
2
+ import { buildFieldMeta } from './type-mappings';
3
+ export function createBuildContext(build) {
4
+ return {
5
+ build,
6
+ inflectAttr: createAttributeInflector(build.inflection),
7
+ };
8
+ }
9
+ export function buildFieldList(attrNames, codec, attributes, context) {
10
+ return attrNames.map((attrName) => buildFieldMeta(context.inflectAttr(attrName, codec), attributes[attrName], context.build));
11
+ }
@@ -0,0 +1,12 @@
1
+ import type { MetaBuild, PgAttribute, PgCodec, PgRelation, PgTableResource, PgUnique } from './types';
2
+ import type { TableResourceWithCodec } from './table-meta-context';
3
+ export declare function isTableResource(resource: PgTableResource): resource is TableResourceWithCodec;
4
+ export declare function getSchemaName(resource: PgTableResource): string | null;
5
+ export declare function getUniques(resource: PgTableResource): PgUnique[];
6
+ export declare function getRelations(resource: PgTableResource): Record<string, PgRelation>;
7
+ export declare function getRelation(resource: PgTableResource, relationName: string): PgRelation | null;
8
+ export declare function sameAttributes(uniqueAttributes: string[] | undefined, relationAttributes: string[] | undefined): boolean;
9
+ export declare function getConfiguredSchemas(build: MetaBuild): string[];
10
+ export declare function getResourceCodec(resource: PgTableResource): (PgCodec & {
11
+ attributes: Record<string, PgAttribute>;
12
+ }) | null;
@@ -0,0 +1,50 @@
1
+ function isRecord(value) {
2
+ return typeof value === 'object' && value !== null;
3
+ }
4
+ export function isTableResource(resource) {
5
+ return (!!resource.codec &&
6
+ !resource.codec.isAnonymous &&
7
+ isRecord(resource.codec.attributes) &&
8
+ !resource.parameters &&
9
+ !resource.isVirtual &&
10
+ !resource.isUnique);
11
+ }
12
+ export function getSchemaName(resource) {
13
+ const schemaName = resource.codec?.extensions?.pg?.schemaName;
14
+ if (typeof schemaName !== 'string' || schemaName.length === 0)
15
+ return null;
16
+ return schemaName;
17
+ }
18
+ export function getUniques(resource) {
19
+ return Array.isArray(resource.uniques) ? resource.uniques : [];
20
+ }
21
+ export function getRelations(resource) {
22
+ return resource.relations || resource.getRelations?.() || {};
23
+ }
24
+ export function getRelation(resource, relationName) {
25
+ if (!relationName)
26
+ return null;
27
+ if (typeof resource.getRelation === 'function') {
28
+ return resource.getRelation(relationName) || null;
29
+ }
30
+ const relations = getRelations(resource);
31
+ return relations[relationName] || null;
32
+ }
33
+ export function sameAttributes(uniqueAttributes, relationAttributes) {
34
+ if (!uniqueAttributes || !relationAttributes)
35
+ return false;
36
+ return (uniqueAttributes.length === relationAttributes.length &&
37
+ uniqueAttributes.every((attrName) => relationAttributes.includes(attrName)));
38
+ }
39
+ export function getConfiguredSchemas(build) {
40
+ const pgSchemas = build.options?.pgSchemas;
41
+ if (!Array.isArray(pgSchemas))
42
+ return [];
43
+ return pgSchemas.filter((schemaName) => typeof schemaName === 'string');
44
+ }
45
+ export function getResourceCodec(resource) {
46
+ const codec = resource.codec;
47
+ if (!codec?.attributes)
48
+ return null;
49
+ return codec;
50
+ }
@@ -0,0 +1,3 @@
1
+ import type { FieldMeta, GqlTypeResolverBuild, PgAttribute } from './types';
2
+ export declare function pgTypeToGqlType(pgTypeName: string): string;
3
+ export declare function buildFieldMeta(name: string, attr: PgAttribute | null | undefined, build?: GqlTypeResolverBuild): FieldMeta;
@@ -0,0 +1,75 @@
1
+ const PG_TO_GQL_TYPE = {
2
+ text: 'String',
3
+ varchar: 'String',
4
+ char: 'String',
5
+ name: 'String',
6
+ bpchar: 'String',
7
+ uuid: 'UUID',
8
+ int2: 'Int',
9
+ int4: 'Int',
10
+ integer: 'Int',
11
+ int8: 'BigInt',
12
+ bigint: 'BigInt',
13
+ float4: 'Float',
14
+ float8: 'Float',
15
+ numeric: 'BigFloat',
16
+ bool: 'Boolean',
17
+ boolean: 'Boolean',
18
+ timestamptz: 'Datetime',
19
+ timestamp: 'Datetime',
20
+ date: 'Date',
21
+ time: 'Time',
22
+ timetz: 'Time',
23
+ json: 'JSON',
24
+ jsonb: 'JSON',
25
+ interval: 'Interval',
26
+ point: 'Point',
27
+ geometry: 'GeoJSON',
28
+ geography: 'GeoJSON',
29
+ inet: 'InternetAddress',
30
+ cidr: 'InternetAddress',
31
+ xml: 'String',
32
+ bytea: 'String',
33
+ macaddr: 'String',
34
+ };
35
+ export function pgTypeToGqlType(pgTypeName) {
36
+ return PG_TO_GQL_TYPE[pgTypeName] || pgTypeName;
37
+ }
38
+ function resolveGqlTypeName(build, codec) {
39
+ if (!codec)
40
+ return 'unknown';
41
+ try {
42
+ const codecForLookup = codec.arrayOfCodec || codec;
43
+ if (build?.hasGraphQLTypeForPgCodec?.(codecForLookup, 'output')) {
44
+ const resolved = build.getGraphQLTypeNameByPgCodec?.(codecForLookup, 'output');
45
+ if (resolved)
46
+ return resolved;
47
+ }
48
+ }
49
+ catch {
50
+ // Fall through to static fallback mapping.
51
+ }
52
+ const pgTypeName = codec.name || 'unknown';
53
+ const mapped = pgTypeToGqlType(pgTypeName);
54
+ if (mapped !== pgTypeName)
55
+ return mapped;
56
+ const nestedTypeName = codec.arrayOfCodec?.name;
57
+ return nestedTypeName ? pgTypeToGqlType(nestedTypeName) : pgTypeName;
58
+ }
59
+ export function buildFieldMeta(name, attr, build) {
60
+ const pgType = attr?.codec?.name || 'unknown';
61
+ const isNotNull = attr?.notNull || false;
62
+ const hasDefault = attr?.hasDefault || false;
63
+ return {
64
+ name,
65
+ type: {
66
+ pgType,
67
+ gqlType: build ? resolveGqlTypeName(build, attr?.codec) : pgTypeToGqlType(pgType),
68
+ isArray: !!attr?.codec?.arrayOfCodec,
69
+ isNotNull,
70
+ hasDefault,
71
+ },
72
+ isNotNull,
73
+ hasDefault,
74
+ };
75
+ }
@@ -0,0 +1,206 @@
1
+ export interface TableMeta {
2
+ name: string;
3
+ schemaName: string;
4
+ fields: FieldMeta[];
5
+ indexes: IndexMeta[];
6
+ constraints: ConstraintsMeta;
7
+ foreignKeyConstraints: ForeignKeyConstraintMeta[];
8
+ primaryKeyConstraints: PrimaryKeyConstraintMeta[];
9
+ uniqueConstraints: UniqueConstraintMeta[];
10
+ relations: RelationsMeta;
11
+ inflection: InflectionMeta;
12
+ query: QueryMeta;
13
+ }
14
+ export interface FieldMeta {
15
+ name: string;
16
+ type: TypeMeta;
17
+ isNotNull: boolean;
18
+ hasDefault: boolean;
19
+ }
20
+ export interface TypeMeta {
21
+ pgType: string;
22
+ gqlType: string;
23
+ isArray: boolean;
24
+ isNotNull?: boolean;
25
+ hasDefault?: boolean;
26
+ }
27
+ export interface IndexMeta {
28
+ name: string;
29
+ isUnique: boolean;
30
+ isPrimary: boolean;
31
+ columns: string[];
32
+ fields: FieldMeta[];
33
+ }
34
+ export interface ConstraintsMeta {
35
+ primaryKey: PrimaryKeyConstraintMeta | null;
36
+ unique: UniqueConstraintMeta[];
37
+ foreignKey: ForeignKeyConstraintMeta[];
38
+ }
39
+ export interface PrimaryKeyConstraintMeta {
40
+ name: string;
41
+ fields: FieldMeta[];
42
+ }
43
+ export interface UniqueConstraintMeta {
44
+ name: string;
45
+ fields: FieldMeta[];
46
+ }
47
+ export interface ForeignKeyConstraintMeta {
48
+ name: string;
49
+ fields: FieldMeta[];
50
+ referencedTable: string;
51
+ referencedFields: string[];
52
+ refFields: FieldMeta[];
53
+ refTable: {
54
+ name: string;
55
+ };
56
+ }
57
+ export interface RelationsMeta {
58
+ belongsTo: BelongsToRelation[];
59
+ has: HasRelation[];
60
+ hasOne: HasRelation[];
61
+ hasMany: HasRelation[];
62
+ manyToMany: ManyToManyRelation[];
63
+ }
64
+ export interface BelongsToRelation {
65
+ fieldName: string | null;
66
+ isUnique: boolean;
67
+ type: string | null;
68
+ keys: FieldMeta[];
69
+ references: {
70
+ name: string;
71
+ };
72
+ }
73
+ export interface HasRelation {
74
+ fieldName: string | null;
75
+ isUnique: boolean;
76
+ type: string | null;
77
+ keys: FieldMeta[];
78
+ referencedBy: {
79
+ name: string;
80
+ };
81
+ }
82
+ export interface ManyToManyRelation {
83
+ fieldName: string | null;
84
+ type: string | null;
85
+ junctionTable: {
86
+ name: string;
87
+ };
88
+ junctionLeftConstraint: ForeignKeyConstraintMeta;
89
+ junctionLeftKeyAttributes: FieldMeta[];
90
+ junctionRightConstraint: ForeignKeyConstraintMeta;
91
+ junctionRightKeyAttributes: FieldMeta[];
92
+ leftKeyAttributes: FieldMeta[];
93
+ rightKeyAttributes: FieldMeta[];
94
+ rightTable: {
95
+ name: string;
96
+ };
97
+ }
98
+ export interface InflectionMeta {
99
+ tableType: string;
100
+ allRows: string;
101
+ connection: string;
102
+ edge: string;
103
+ filterType: string | null;
104
+ orderByType: string;
105
+ conditionType: string;
106
+ patchType: string | null;
107
+ createInputType: string;
108
+ createPayloadType: string;
109
+ updatePayloadType: string | null;
110
+ deletePayloadType: string;
111
+ }
112
+ export interface QueryMeta {
113
+ all: string;
114
+ one: string | null;
115
+ create: string | null;
116
+ update: string | null;
117
+ delete: string | null;
118
+ }
119
+ export interface PgCodec {
120
+ name: string;
121
+ attributes?: Record<string, PgAttribute>;
122
+ arrayOfCodec?: PgCodec | null;
123
+ isAnonymous?: boolean;
124
+ extensions?: {
125
+ pg?: {
126
+ schemaName?: string;
127
+ };
128
+ };
129
+ }
130
+ export interface PgAttribute {
131
+ codec?: PgCodec | null;
132
+ notNull?: boolean;
133
+ hasDefault?: boolean;
134
+ }
135
+ export interface PgUnique {
136
+ attributes: string[];
137
+ isPrimary?: boolean;
138
+ tags?: {
139
+ name?: string;
140
+ };
141
+ }
142
+ export interface PgRelation {
143
+ isReferencee?: boolean;
144
+ localAttributes?: string[];
145
+ remoteAttributes?: string[];
146
+ remoteResource?: PgTableResource | null;
147
+ }
148
+ export interface PgTableResource {
149
+ codec?: PgCodec;
150
+ uniques?: PgUnique[];
151
+ relations?: Record<string, PgRelation>;
152
+ parameters?: unknown;
153
+ isVirtual?: boolean;
154
+ isUnique?: boolean;
155
+ getRelation?: (relationName: string) => PgRelation | undefined;
156
+ getRelations?: () => Record<string, PgRelation>;
157
+ }
158
+ export interface PgManyToManyRelationDetails {
159
+ leftTable: PgTableResource;
160
+ leftRelationName: string;
161
+ junctionTable: PgTableResource;
162
+ rightRelationName: string;
163
+ rightTable: PgTableResource;
164
+ allowsMultipleEdgesToNode?: boolean;
165
+ }
166
+ export interface MetaInflection {
167
+ tableType: (codec: PgCodec) => string;
168
+ _attributeName?: (input: {
169
+ attributeName: string;
170
+ codec: PgCodec;
171
+ }) => string;
172
+ camelCase?: (value: string) => string;
173
+ _manyToManyRelation?: (details: PgManyToManyRelationDetails) => string | null | undefined;
174
+ allRows?: (resource: PgTableResource) => string | null | undefined;
175
+ connectionType?: (tableType: string) => string | null | undefined;
176
+ edgeType?: (tableType: string) => string | null | undefined;
177
+ filterType?: (tableType: string) => string | null | undefined;
178
+ orderByType?: (tableType: string) => string | null | undefined;
179
+ conditionType?: (tableType: string) => string | null | undefined;
180
+ patchType?: (tableType: string) => string | null | undefined;
181
+ createInputType?: (resource: PgTableResource) => string | null | undefined;
182
+ createPayloadType?: (resource: PgTableResource) => string | null | undefined;
183
+ updatePayloadType?: (resource: PgTableResource) => string | null | undefined;
184
+ deletePayloadType?: (resource: PgTableResource) => string | null | undefined;
185
+ tableFieldName?: (resource: PgTableResource) => string | null | undefined;
186
+ createField?: (resource: PgTableResource) => string | null | undefined;
187
+ updateByKeys?: (resource: PgTableResource) => string | null | undefined;
188
+ deleteByKeys?: (resource: PgTableResource) => string | null | undefined;
189
+ }
190
+ export interface GqlTypeResolverBuild {
191
+ hasGraphQLTypeForPgCodec?: (codec: PgCodec, mode?: 'output' | 'input' | string) => boolean;
192
+ getGraphQLTypeNameByPgCodec?: (codec: PgCodec, mode?: 'output' | 'input' | string) => string | null | undefined;
193
+ }
194
+ export interface MetaBuild extends GqlTypeResolverBuild {
195
+ input: {
196
+ pgRegistry: {
197
+ pgResources: Record<string, PgTableResource>;
198
+ };
199
+ };
200
+ inflection: MetaInflection;
201
+ options?: {
202
+ pgSchemas?: string[];
203
+ [key: string]: unknown;
204
+ };
205
+ pgManyToManyRealtionshipsByResource?: Map<unknown, unknown>;
206
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * PostGraphile v5 Meta Schema Plugin
3
+ *
4
+ * Exposes a `_meta` GraphQL query that provides metadata about tables, fields,
5
+ * constraints, indexes, and relations for code generation tooling.
6
+ */
7
+ import type { GraphileConfig } from 'graphile-config';
8
+ import { cachedTablesMeta } from './meta-schema/cache';
9
+ import { MetaSchemaPlugin } from './meta-schema/plugin';
10
+ import { buildFieldMeta, pgTypeToGqlType } from './meta-schema/type-mappings';
11
+ export { MetaSchemaPlugin };
12
+ export declare const MetaSchemaPreset: GraphileConfig.Preset;
13
+ /** @internal Exported for testing only */
14
+ export { pgTypeToGqlType as _pgTypeToGqlType };
15
+ /** @internal Exported for testing only */
16
+ export { buildFieldMeta as _buildFieldMeta };
17
+ /** @internal Exported for testing only */
18
+ export { cachedTablesMeta as _cachedTablesMeta };
19
+ export default MetaSchemaPlugin;