graphile-build-pg
Advanced tools
Comparing version 5.0.0-beta.6 to 5.0.0-beta.7
@@ -12,3 +12,3 @@ "use strict"; | ||
function processAttribute(fields, build, context, attributeName, overrideName) { | ||
const { extend, inflection, input: { pgRegistry: registry }, } = build; | ||
const { extend, inflection } = build; | ||
const { scope: { pgCodec: rawPgCodec }, Self, } = context; | ||
@@ -41,7 +41,4 @@ if (!rawPgCodec || !rawPgCodec.attributes) { | ||
}; | ||
const executor = pgCodec.executor; | ||
const resource = baseCodec.attributes | ||
? Object.values(registry.pgResources).find((potentialSource) => potentialSource.codec === baseCodec && | ||
!potentialSource.parameters && | ||
potentialSource.executor === executor) | ||
? build.pgTableResource(baseCodec, false) | ||
: null; | ||
@@ -48,0 +45,0 @@ if (baseCodec.attributes && !resource) { |
@@ -57,2 +57,6 @@ import "graphile-build"; | ||
pgGetBehavior: typeof getBehavior; | ||
/** | ||
* Get a table-like resource for the given codec, assuming exactly one exists. | ||
*/ | ||
pgTableResource<TCodec extends PgCodecWithAttributes>(codec: TCodec, strict?: boolean): PgResource<string, TCodec, ReadonlyArray<PgResourceUnique>, undefined> | null; | ||
} | ||
@@ -59,0 +63,0 @@ interface BehaviorEntities { |
@@ -158,2 +158,29 @@ "use strict"; | ||
}; | ||
const resourceByCodecCacheUnstrict = new Map(); | ||
const resourceByCodecCacheStrict = new Map(); | ||
const pgTableResource = (codec, strict = true) => { | ||
const resourceByCodecCache = strict | ||
? resourceByCodecCacheStrict | ||
: resourceByCodecCacheUnstrict; | ||
if (resourceByCodecCache.has(codec)) { | ||
return resourceByCodecCache.get(codec); | ||
} | ||
const resources = Object.values(build.input.pgRegistry.pgResources).filter((r) => r.codec === codec && | ||
!r.parameters && | ||
r.executor === codec.executor && | ||
(!strict || (!r.isVirtual && !r.isUnique))); | ||
if (resources.length < 1) { | ||
resourceByCodecCache.set(codec, null); | ||
return null; | ||
} | ||
else if (resources.length > 1) { | ||
console.warn(`[WARNING]: detected more than one table-like resource for codec '${codec.name}'; returning nothing to avoid ambiguity.`); | ||
resourceByCodecCache.set(codec, null); | ||
return null; | ||
} | ||
else { | ||
resourceByCodecCache.set(codec, resources[0]); | ||
return resources[0]; | ||
} | ||
}; | ||
return build.extend(build, { | ||
@@ -174,2 +201,3 @@ versions: build.extend(build.versions, { | ||
pgSql: pg_sql2_1.default, | ||
pgTableResource, | ||
}, "Adding helpers from PgBasicsPlugin"); | ||
@@ -176,0 +204,0 @@ }, |
@@ -852,4 +852,5 @@ "use strict"; | ||
const copy = (underlyingTypeName) => () => { | ||
const baseType = build.getTypeByName(underlyingTypeName); | ||
const config = { ...baseType?.toConfig() }; | ||
const details = build.getTypeMetaByName(underlyingTypeName); | ||
const baseConfig = details?.specGenerator(); | ||
const config = { ...baseConfig }; | ||
delete config.name; | ||
@@ -856,0 +857,0 @@ delete config.description; |
@@ -178,12 +178,23 @@ "use strict"; | ||
: finalBuild.getGraphQLTypeByPgCodec(paramBaseCodec, variant); | ||
const typeNameForFetcher = variant === "nodeId" | ||
? finalBuild.getGraphQLTypeNameByPgCodec(paramBaseCodec, "output") | ||
: null; | ||
if (variant === "nodeId" && !finalBuild.nodeFetcherByTypeName) { | ||
if (variant === "nodeId" && !finalBuild.nodeIdSpecForCodec) { | ||
// ERRORS: tell them how to turn the nodeId variant off | ||
throw new Error(`Argument is configured to use nodeId variant, but build is not configured with Node support - there is no 'build.nodeFetcherByTypeName'. Did you skip NodePlugin?`); | ||
} | ||
const fetcher = typeNameForFetcher | ||
? finalBuild.nodeFetcherByTypeName(typeNameForFetcher) | ||
const getSpec = variant === "nodeId" | ||
? finalBuild.nodeIdSpecForCodec(paramBaseCodec) | ||
: null; | ||
if (variant === "nodeId" && !getSpec) { | ||
// ERRORS: tell them how to turn the nodeId variant off | ||
throw new Error(`Argument is configured to use nodeId variant, but we don't know how to get the spec for codec '${paramBaseCodec.name}'`); | ||
} | ||
const codecResource = variant === "nodeId" | ||
? finalBuild.pgTableResource(paramBaseCodec) | ||
: null; | ||
if (variant === "nodeId" && !codecResource) { | ||
// ERRORS: tell them how to turn the nodeId variant off | ||
throw new Error(`Argument is configured to use nodeId variant, but we couldn't find a suitable resource to pull a '${paramBaseCodec.name}' record from`); | ||
} | ||
const fetcher = getSpec && codecResource | ||
? (0, graphile_build_1.EXPORTABLE)((codecResource, getSpec) => ($nodeId) => codecResource.get(getSpec($nodeId)), [codecResource, getSpec]) | ||
: null; | ||
if (!baseInputType) { | ||
@@ -389,21 +400,22 @@ const hint = variant === "input" | ||
build.registerInputObjectType(inputTypeName, { isMutationInput: true }, () => { | ||
const { argDetails } = pgGetArgDetailsFromParameters(resource, resource.parameters); | ||
// Not used for isMutation; that's handled elsewhere | ||
const fields = argDetails.reduce((memo, { inputType, graphqlArgName }) => { | ||
memo[graphqlArgName] = { | ||
type: inputType, | ||
}; | ||
return memo; | ||
}, Object.assign(Object.create(null), { | ||
clientMutationId: { | ||
type: GraphQLString, | ||
autoApplyAfterParentApplyPlan: true, | ||
applyPlan: (0, graphile_build_1.EXPORTABLE)(() => function plan($input, val) { | ||
$input.set("clientMutationId", val.get()); | ||
}, []), | ||
}, | ||
})); | ||
return { | ||
description: `All input for the \`${fieldName}\` mutation.`, | ||
fields, | ||
fields: () => { | ||
const { argDetails } = pgGetArgDetailsFromParameters(resource, resource.parameters); | ||
// Not used for isMutation; that's handled elsewhere | ||
return argDetails.reduce((memo, { inputType, graphqlArgName }) => { | ||
memo[graphqlArgName] = { | ||
type: inputType, | ||
}; | ||
return memo; | ||
}, Object.assign(Object.create(null), { | ||
clientMutationId: { | ||
type: GraphQLString, | ||
autoApplyAfterParentApplyPlan: true, | ||
applyPlan: (0, graphile_build_1.EXPORTABLE)(() => function plan($input, val) { | ||
$input.set("clientMutationId", val.get()); | ||
}, []), | ||
}, | ||
})); | ||
}, | ||
}; | ||
@@ -410,0 +422,0 @@ }, "PgCustomTypeFieldPlugin mutation function input type"); |
@@ -42,13 +42,6 @@ "use strict"; | ||
} | ||
const resources = Object.values(build.input.pgRegistry.pgResources).filter((resource) => { | ||
if (resource.codec !== pgCodec) | ||
return false; | ||
if (resource.parameters) | ||
return false; | ||
return true; | ||
}); | ||
if (resources.length !== 1) { | ||
const resource = build.pgTableResource(pgCodec); | ||
if (!resource) { | ||
return fields; | ||
} | ||
const resource = resources[0]; | ||
const pk = resource.uniques?.find((u) => u.isPrimary); | ||
@@ -55,0 +48,0 @@ if (!pk) { |
@@ -213,45 +213,47 @@ "use strict"; | ||
}, () => { | ||
const TablePatch = mode === "resource:update" | ||
? build.getInputTypeByName(tablePatchName) | ||
: null; | ||
return { | ||
description: build.wrapDescription(`All input for the \`${fieldName}\` mutation.`, "type"), | ||
fields: Object.assign({ | ||
clientMutationId: { | ||
description: build.wrapDescription("An arbitrary string value with no semantic meaning. Will be included in the payload verbatim. May be used to track mutations by the client.", "field"), | ||
type: GraphQLString, | ||
applyPlan: (0, graphile_build_1.EXPORTABLE)(() => function plan($input, val) { | ||
$input.set("clientMutationId", val.get()); | ||
}, []), | ||
}, | ||
...(uniqueMode === "node" | ||
fields() { | ||
const TablePatch = mode === "resource:update" | ||
? build.getInputTypeByName(tablePatchName) | ||
: null; | ||
return Object.assign({ | ||
clientMutationId: { | ||
description: build.wrapDescription("An arbitrary string value with no semantic meaning. Will be included in the payload verbatim. May be used to track mutations by the client.", "field"), | ||
type: GraphQLString, | ||
applyPlan: (0, graphile_build_1.EXPORTABLE)(() => function plan($input, val) { | ||
$input.set("clientMutationId", val.get()); | ||
}, []), | ||
}, | ||
...(uniqueMode === "node" | ||
? { | ||
[nodeIdFieldName]: { | ||
description: build.wrapDescription(`The globally unique \`ID\` which will identify a single \`${tableTypeName}\` to be ${modeText}d.`, "field"), | ||
type: new GraphQLNonNull(GraphQLID), | ||
}, | ||
} | ||
: unique.attributes.reduce((memo, attributeName) => { | ||
const attribute = resource.codec.attributes[attributeName]; | ||
memo[inflection.attribute({ | ||
attributeName, | ||
codec: resource.codec, | ||
})] = { | ||
description: attribute.description, | ||
type: new GraphQLNonNull(build.getGraphQLTypeByPgCodec(attribute.codec, "input")), | ||
}; | ||
return memo; | ||
}, Object.create(null))), | ||
}, mode === "resource:update" && TablePatch | ||
? { | ||
[nodeIdFieldName]: { | ||
description: build.wrapDescription(`The globally unique \`ID\` which will identify a single \`${tableTypeName}\` to be ${modeText}d.`, "field"), | ||
type: new GraphQLNonNull(GraphQLID), | ||
[inflection.patchField(inflection.tableFieldName(resource))]: { | ||
description: build.wrapDescription(`An object where the defined keys will be set on the \`${tableTypeName}\` being ${modeText}d.`, "field"), | ||
type: new GraphQLNonNull(TablePatch), | ||
applyPlan: (0, graphile_build_1.EXPORTABLE)(() => function plan($object) { | ||
const $record = $object.getStepForKey("result"); | ||
return $record.setPlan(); | ||
}, []), | ||
}, | ||
} | ||
: unique.attributes.reduce((memo, attributeName) => { | ||
const attribute = resource.codec.attributes[attributeName]; | ||
memo[inflection.attribute({ | ||
attributeName, | ||
codec: resource.codec, | ||
})] = { | ||
description: attribute.description, | ||
type: new GraphQLNonNull(build.getGraphQLTypeByPgCodec(attribute.codec, "input")), | ||
}; | ||
return memo; | ||
}, Object.create(null))), | ||
}, mode === "resource:update" | ||
? { | ||
[inflection.patchField(inflection.tableFieldName(resource))]: { | ||
description: build.wrapDescription(`An object where the defined keys will be set on the \`${tableTypeName}\` being ${modeText}d.`, "field"), | ||
type: new GraphQLNonNull(TablePatch), | ||
applyPlan: (0, graphile_build_1.EXPORTABLE)(() => function plan($object) { | ||
const $record = $object.getStepForKey("result"); | ||
return $record.setPlan(); | ||
}, []), | ||
}, | ||
} | ||
: null), | ||
: null); | ||
}, | ||
}; | ||
@@ -258,0 +260,0 @@ }, `Creating ${mode} input by ${uniqueMode} for ${unique.attributes.join(",")} of ${resource} from PgMutationUpdateDeletePlugin`); |
@@ -45,4 +45,4 @@ "use strict"; | ||
} | ||
const fetcher = build.nodeFetcherByTypeName?.(typeName); | ||
if (!fetcher) { | ||
const getSpec = build.nodeIdSpecForCodec?.(relation.remoteResource.codec); | ||
if (!getSpec) { | ||
return memo; | ||
@@ -80,3 +80,2 @@ } | ||
!anAttributeIsNotNull, GraphQLID), | ||
deprecationReason: fetcher.deprecationReason, | ||
autoApplyAfterParentInputPlan: true, | ||
@@ -88,3 +87,3 @@ autoApplyAfterParentApplyPlan: true, | ||
applyPlan: isPgCondition | ||
? (0, graphile_build_1.EXPORTABLE)((fetcher, localAttributeCodecs, localAttributes, remoteAttributes, sql) => function plan($condition, val) { | ||
? (0, graphile_build_1.EXPORTABLE)((getSpec, localAttributeCodecs, localAttributes, remoteAttributes, sql) => function plan($condition, val) { | ||
if (val.getRaw().evalIs(null)) { | ||
@@ -101,3 +100,3 @@ for (let i = 0, l = localAttributes.length; i < l; i++) { | ||
else { | ||
const $record = fetcher(val.get()); | ||
const spec = getSpec(val.get()); | ||
for (let i = 0, l = localAttributes.length; i < l; i++) { | ||
@@ -110,3 +109,3 @@ const localName = localAttributes[i]; | ||
attribute: localName, | ||
callback: (expression) => sql `${expression} = ${$condition.placeholder($record.get(remoteName), codec)}`, | ||
callback: (expression) => sql `${expression} = ${$condition.placeholder(spec[remoteName], codec)}`, | ||
}); | ||
@@ -116,3 +115,3 @@ } | ||
}, [ | ||
fetcher, | ||
getSpec, | ||
localAttributeCodecs, | ||
@@ -123,11 +122,11 @@ localAttributes, | ||
]) | ||
: (0, graphile_build_1.EXPORTABLE)((fetcher, localAttributes, remoteAttributes) => function plan($insert, val) { | ||
const $record = fetcher(val.get()); | ||
: (0, graphile_build_1.EXPORTABLE)((getSpec, localAttributes, remoteAttributes) => function plan($insert, val) { | ||
const spec = getSpec(val.get()); | ||
for (let i = 0, l = localAttributes.length; i < l; i++) { | ||
const localName = localAttributes[i]; | ||
const remoteName = remoteAttributes[i]; | ||
const $val = $record.get(remoteName); | ||
const $val = spec[remoteName]; | ||
$insert.set(localName, $val); | ||
} | ||
}, [fetcher, localAttributes, remoteAttributes]), | ||
}, [getSpec, localAttributes, remoteAttributes]), | ||
}), | ||
@@ -134,0 +133,0 @@ }, `Adding input object 'ID' field to ${pgCodec.name} (action = ${action}) representing relation ${relationName}.`); |
@@ -48,4 +48,4 @@ "use strict"; | ||
: allAttributes; | ||
const sources = Object.values(build.input.pgRegistry.pgResources).filter((s) => s.codec === pgCodec && !s.parameters); | ||
const uniques = sources.flatMap((s) => s.uniques); | ||
const resource = build.pgTableResource(pgCodec); | ||
const uniques = resource?.uniques ?? []; | ||
return extend(values, Object.entries(attributes).reduce((memo, [attributeName, attribute]) => { | ||
@@ -52,0 +52,0 @@ const fieldBehaviorScope = `attribute:orderBy`; |
@@ -25,7 +25,7 @@ "use strict"; | ||
const pgCodec = rawPgCodec; | ||
const resources = Object.values(build.input.pgRegistry.pgResources).filter((s) => s.codec === pgCodec && !s.parameters); | ||
if (resources.length < 1) { | ||
const resource = build.pgTableResource(pgCodec); | ||
if (!resource) { | ||
return values; | ||
} | ||
const primaryKey = resources[0].uniques.find((resource) => resource.isPrimary); | ||
const primaryKey = resource.uniques.find((unique) => unique.isPrimary); | ||
if (!primaryKey) { | ||
@@ -32,0 +32,0 @@ return values; |
@@ -7,2 +7,3 @@ import "graphile-config"; | ||
import type { PgCodec, PgCodecPolymorphism, PgCodecPolymorphismSingleTypeAttributeSpec } from "@dataplan/pg"; | ||
import type { ExecutableStep } from "grafast"; | ||
declare global { | ||
@@ -15,2 +16,7 @@ namespace GraphileConfig { | ||
namespace GraphileBuild { | ||
interface Build { | ||
nodeIdSpecForCodec(codec: PgCodec<any, any, any, any, any, any, any>): (($nodeId: ExecutableStep<string>) => { | ||
[key: string]: ExecutableStep<any>; | ||
}) | null; | ||
} | ||
interface ScopeInterface { | ||
@@ -45,4 +51,9 @@ pgCodec?: PgCodec<any, any, any, any, any, any, any>; | ||
} | ||
namespace DataplanPg { | ||
interface PgCodecExtensions { | ||
relationalInterfaceCodecName?: string; | ||
} | ||
} | ||
} | ||
export declare const PgPolymorphismPlugin: GraphileConfig.Plugin; | ||
//# sourceMappingURL=PgPolymorphismPlugin.d.ts.map |
@@ -39,3 +39,3 @@ "use strict"; | ||
version: version_js_1.version, | ||
after: ["smart-tags", "PgTablesPlugin", "PgCodecsPlugin"], | ||
after: ["smart-tags", "PgTablesPlugin", "PgCodecsPlugin", "PgBasicsPlugin"], | ||
gather: (0, graphile_build_1.gatherConfig)({ | ||
@@ -139,5 +139,9 @@ namespace: "pgPolymorphism", | ||
if (!pgConstraint) { | ||
throw new Error("Could not build polymorphic reference due to missing foreign key constraint"); | ||
throw new Error(`Could not build polymorphic reference from '${pgClass.getNamespace()?.nspname}.${pgClass.relname}' to '${referencedClass.getNamespace()?.nspname}.${referencedClass.relname}' due to missing foreign key constraint. Please create a foreign key constraint on the latter table's primary key, pointing to the former table.`); | ||
} | ||
const codec = await info.helpers.pgCodecs.getCodecFromClass(serviceName, referencedClass._id); | ||
const codec = (await info.helpers.pgCodecs.getCodecFromClass(serviceName, referencedClass._id)); | ||
if (!codec.extensions) { | ||
codec.extensions = Object.create(null); | ||
} | ||
codec.extensions.relationalInterfaceCodecName = spec.name; | ||
types[typeValue] = { | ||
@@ -419,2 +423,31 @@ name: info.inflection.tableType(codec), | ||
}, | ||
pgCodecAttribute: { | ||
provides: ["inferred"], | ||
after: ["default"], | ||
before: ["override"], | ||
callback(behavior, [codec, attributeName], build) { | ||
// If this is the primary key of a related table of a | ||
// `@interface mode:relational` table, then omit it from the schema | ||
const tbl = build.pgTableResource(codec); | ||
if (tbl) { | ||
const pk = tbl.uniques.find((u) => u.isPrimary); | ||
if (pk && pk.attributes.includes(attributeName)) { | ||
const fkeys = Object.values(tbl.getRelations()).filter((r) => (0, grafast_1.arraysMatch)(r.localAttributes, pk.attributes)); | ||
const myName = build.inflection.tableType(codec); | ||
for (const fkey of fkeys) { | ||
if (fkey.remoteResource.codec.polymorphism?.mode === | ||
"relational" && | ||
Object.values(fkey.remoteResource.codec.polymorphism.types).find((t) => t.name === myName) && | ||
!fkey.remoteResource.codec.attributes[attributeName]) { | ||
return [ | ||
behavior, | ||
"-attribute:select -attribute:update -attribute:filterBy -attribute:orderBy", | ||
]; | ||
} | ||
} | ||
} | ||
} | ||
return behavior; | ||
}, | ||
}, | ||
pgResource: { | ||
@@ -455,2 +488,130 @@ provides: ["inferred"], | ||
hooks: { | ||
build(build) { | ||
return build.extend(build, { | ||
nodeIdSpecForCodec(codec) { | ||
const table = build.pgTableResource(codec); | ||
if (!table) { | ||
return null; | ||
} | ||
const tablePk = table.uniques.find((u) => u.isPrimary); | ||
if (!tablePk) { | ||
return null; | ||
} | ||
const tablePkAttributes = tablePk.attributes; | ||
if (codec.polymorphism?.mode === "relational") { | ||
const details = []; | ||
for (const spec of Object.values(codec.polymorphism.types)) { | ||
const relation = table.getRelation(spec.relationName); | ||
const typeName = build.inflection.tableType(relation.remoteResource.codec); | ||
const handler = build.getNodeIdHandler?.(typeName); | ||
if (!handler) { | ||
return null; | ||
} | ||
const pk = relation.remoteResource.uniques.find((u) => u.isPrimary); | ||
if (!pk) { | ||
return null; | ||
} | ||
details.push({ | ||
pkAttributes: pk.attributes, | ||
handler, | ||
}); | ||
} | ||
const handlers = details.map((d) => d.handler); | ||
const decodeNodeId = (0, graphile_build_1.EXPORTABLE)((handlers, makeDecodeNodeId) => makeDecodeNodeId(handlers), [handlers, grafast_1.makeDecodeNodeId]); | ||
return (0, graphile_build_1.EXPORTABLE)((access, decodeNodeId, details, lambda, list, object, tablePkAttributes) => ($nodeId) => { | ||
const $specifier = decodeNodeId($nodeId); | ||
const $handlerMatches = list(details.map(({ handler, pkAttributes }) => { | ||
const spec = handler.getSpec(access($specifier, handler.codec.name)); | ||
return object({ | ||
match: lambda($specifier, (specifier) => { | ||
const value = specifier[handler.codec.name]; | ||
return value != null | ||
? handler.match(value) | ||
: false; | ||
}), | ||
pks: list(pkAttributes.map((n) => spec[n])), | ||
}); | ||
})); | ||
const $pkValues = lambda($handlerMatches, (handlerMatches) => { | ||
const match = handlerMatches.find((pk) => pk.match); | ||
return match?.pks; | ||
}, true); | ||
return tablePkAttributes.reduce((memo, pkAttribute, i) => { | ||
memo[pkAttribute] = access($pkValues, i); | ||
return memo; | ||
}, Object.create(null)); | ||
}, [ | ||
grafast_1.access, | ||
decodeNodeId, | ||
details, | ||
grafast_1.lambda, | ||
grafast_1.list, | ||
grafast_1.object, | ||
tablePkAttributes, | ||
]); | ||
} | ||
else if (codec.polymorphism?.mode === "single") { | ||
// Lots of type names, but they all relate to the same table | ||
const handlers = []; | ||
for (const spec of Object.values(codec.polymorphism.types)) { | ||
const typeName = spec.name; | ||
const handler = build.getNodeIdHandler?.(typeName); | ||
if (!handler) { | ||
return null; | ||
} | ||
handlers.push(handler); | ||
} | ||
const decodeNodeId = (0, graphile_build_1.EXPORTABLE)((handlers, makeDecodeNodeId) => makeDecodeNodeId(handlers), [handlers, grafast_1.makeDecodeNodeId]); | ||
return (0, graphile_build_1.EXPORTABLE)((access, decodeNodeId, handlers, lambda, list, object, tablePkAttributes) => ($nodeId) => { | ||
const $specifier = decodeNodeId($nodeId); | ||
const $handlerMatches = list(handlers.map((handler) => { | ||
const spec = handler.getSpec(access($specifier, handler.codec.name)); | ||
return object({ | ||
match: lambda($specifier, (specifier) => { | ||
const value = specifier[handler.codec.name]; | ||
return value != null | ||
? handler.match(value) | ||
: false; | ||
}), | ||
pks: list(tablePkAttributes.map((n) => spec[n])), | ||
}); | ||
})); | ||
const $pkValues = lambda($handlerMatches, (handlerMatches) => { | ||
const match = handlerMatches.find((pk) => pk.match); | ||
return match?.pks; | ||
}, true); | ||
return tablePkAttributes.reduce((memo, pkAttribute, i) => { | ||
memo[pkAttribute] = access($pkValues, i); | ||
return memo; | ||
}, Object.create(null)); | ||
}, [ | ||
grafast_1.access, | ||
decodeNodeId, | ||
handlers, | ||
grafast_1.lambda, | ||
grafast_1.list, | ||
grafast_1.object, | ||
tablePkAttributes, | ||
]); | ||
} | ||
else if (codec.polymorphism) { | ||
throw new Error(`Don't know how to get the spec for nodeId for codec with polymorphism mode '${codec.polymorphism.mode}'`); | ||
} | ||
else { | ||
const typeName = build.inflection.tableType(codec); | ||
const handler = build.getNodeIdHandler?.(typeName); | ||
const { specForHandler } = build; | ||
if (!handler || !specForHandler) { | ||
return null; | ||
} | ||
return (0, graphile_build_1.EXPORTABLE)((handler, lambda, specForHandler) => ($nodeId) => { | ||
// TODO: should change this to a common method like | ||
// `const $decoded = getDecodedNodeIdForHandler(handler, $nodeId)` | ||
const $decoded = lambda($nodeId, specForHandler(handler)); | ||
return handler.getSpec($decoded); | ||
}, [handler, grafast_1.lambda, specForHandler]); | ||
} | ||
}, | ||
}, "Adding PgPolmorphismPlugin helpers to Build"); | ||
}, | ||
init(_, build, _context) { | ||
@@ -504,17 +665,3 @@ const { inflection, options: { pgForbidSetofFunctionsToReturnNull }, setGraphQLTypeForPgCodec, grafast: { list, constant, access }, } = build; | ||
}); | ||
const resources = Object.values(build.input.pgRegistry.pgResources).filter((r) => { | ||
if (r.codec !== codec) | ||
return false; | ||
if (r.parameters) | ||
return false; | ||
if (r.isUnique) | ||
return false; | ||
if (r.isVirtual) | ||
return false; | ||
return true; | ||
}); | ||
const resource = resources.length === 1 ? resources[0] : null; | ||
if (resources.length !== 1) { | ||
console.warn(`Found multiple table resources for codec '${codec.name}'; we don't currently support that but we _could_ - get in touch if you need this.`); | ||
} | ||
const resource = build.pgTableResource(codec); | ||
const primaryKey = resource | ||
@@ -540,3 +687,3 @@ ? resource.uniques.find((u) => u.isPrimary === true) | ||
description: codec.description, | ||
interfaces: [ | ||
interfaces: () => [ | ||
build.getTypeByName(interfaceTypeName), | ||
@@ -543,0 +690,0 @@ ], |
@@ -14,3 +14,2 @@ "use strict"; | ||
const version_js_1 = require("../version.js"); | ||
const ref_first = tamedevil_1.default.ref(grafast_1.first, "first"); | ||
const ref_connection = tamedevil_1.default.ref(grafast_1.connection, "connection"); | ||
@@ -411,5 +410,3 @@ const ref_sql = tamedevil_1.default.ref(pg_sql2_1.default, "sql"); | ||
} | ||
const allPgResources = Object.values(build.input.pgRegistry.pgResources); | ||
const resource = (pgTypeResource ?? | ||
allPgResources.find((s) => s.codec === codec && !s.parameters)); | ||
const resource = pgTypeResource ?? build.pgTableResource(codec); | ||
const relations = (build.input.pgRegistry | ||
@@ -596,11 +593,11 @@ .pgRelations[codec.name] ?? Object.create(null)); | ||
if (isMutationPayload) { | ||
functionLines.push((0, tamedevil_1.default) `return ($in) => {`); | ||
functionLines.push((0, tamedevil_1.default) `return function PgRelationsPlugin_mutation_payload_relation($in) {`); | ||
functionLines.push((0, tamedevil_1.default) ` const $record = $in.get("result");`); | ||
} | ||
else { | ||
functionLines.push((0, tamedevil_1.default) `return ($record) => {`); | ||
functionLines.push((0, tamedevil_1.default) `return function PgRelationsPlugin_relation($record) {`); | ||
} | ||
const finalLayer = path.layers[path.layers.length - 1]; | ||
const ref_finalLayerResource = tamedevil_1.default.ref(finalLayer.resource, finalLayer.resource.name); | ||
const collectionIdentifier = tamedevil_1.default.identifier(build.inflection.pluralize(finalLayer.resource.name)); | ||
const collectionIdentifier = tamedevil_1.default.identifier(`$` + build.inflection.pluralize(finalLayer.resource.name)); | ||
functionLines.push((0, tamedevil_1.default) ` const ${collectionIdentifier} = ${ref_finalLayerResource}.find();`); | ||
@@ -638,3 +635,3 @@ // NOTE: do we ever need to make the above `DISTINCT ON (primary key)`? | ||
if (single) { | ||
functionLines.push((0, tamedevil_1.default) ` return ${ref_first}(${collectionIdentifier});`); | ||
functionLines.push((0, tamedevil_1.default) ` return ${collectionIdentifier}.single();`); | ||
} | ||
@@ -641,0 +638,0 @@ else if (isConnection) { |
@@ -28,16 +28,4 @@ "use strict"; | ||
codec.polymorphism.mode === "relational")) { | ||
const resources = Object.values(build.input.pgRegistry.pgResources).filter((r) => { | ||
if (r.codec !== codec) | ||
return false; | ||
if (r.parameters) | ||
return false; | ||
if (r.isUnique) | ||
return false; | ||
if (r.isVirtual) | ||
return false; | ||
if (!r.uniques || r.uniques.length < 1) | ||
return false; | ||
return true; | ||
}); | ||
if (resources.length === 1) { | ||
const resource = build.pgTableResource(codec); | ||
if (resource && resource.uniques?.length >= 1) { | ||
if (codec.polymorphism) { | ||
@@ -50,5 +38,2 @@ newBehavior.push("interface:node"); | ||
} | ||
else if (resources.length > 1) { | ||
console.warn(`Found multiple table resources for codec '${codec.name}'; we don't currently support that but we _could_ - get in touch if you need this.`); | ||
} | ||
else { | ||
@@ -55,0 +40,0 @@ // Meh |
@@ -145,3 +145,3 @@ "use strict"; | ||
description: build.wrapDescription("An interval of time that has passed where the smallest distinct unit is a second.", "type"), | ||
fields: makeIntervalFields(), | ||
fields: () => makeIntervalFields(), | ||
}), "graphile-build-pg built-in (Interval)"); | ||
@@ -151,3 +151,3 @@ doConnection("Interval"); | ||
description: build.wrapDescription("An interval of time that has passed where the smallest distinct unit is a second.", "type"), | ||
fields: makeIntervalFields(), | ||
fields: () => makeIntervalFields(), | ||
}), "graphile-build-pg built-in (IntervalInput)"); | ||
@@ -158,3 +158,3 @@ function registerGeometry(typeName, description, fieldGen, inputFieldGen) { | ||
description: build.wrapDescription(description, "type"), | ||
fields: fieldGen(), | ||
fields: () => fieldGen(), | ||
}), `graphile-build-pg built-in (${typeName})`); | ||
@@ -164,3 +164,3 @@ doConnection(typeName); | ||
description: build.wrapDescription(description, "type"), | ||
fields: inputFieldGen(), | ||
fields: () => inputFieldGen(), | ||
}), `graphile-build-pg built-in (${typeName}Input)`); | ||
@@ -167,0 +167,0 @@ } |
@@ -1,2 +0,2 @@ | ||
export declare const version = "5.0.0-beta.6"; | ||
export declare const version = "5.0.0-beta.7"; | ||
//# sourceMappingURL=version.d.ts.map |
@@ -5,3 +5,3 @@ "use strict"; | ||
// This file is autogenerated by /scripts/postversion.mjs | ||
exports.version = "5.0.0-beta.6"; | ||
exports.version = "5.0.0-beta.7"; | ||
//# sourceMappingURL=version.js.map |
{ | ||
"name": "graphile-build-pg", | ||
"version": "5.0.0-beta.6", | ||
"version": "5.0.0-beta.7", | ||
"description": "PostgreSQL plugins for Graphile Build - build a supercharged GraphQL schema by reflection over a PostgreSQL database and executed by Grafast.", | ||
@@ -55,5 +55,5 @@ "type": "commonjs", | ||
"peerDependencies": { | ||
"@dataplan/pg": "^0.0.1-beta.4", | ||
"grafast": "^0.0.1-beta.4", | ||
"graphile-build": "5.0.0-beta.5", | ||
"@dataplan/pg": "^0.0.1-beta.5", | ||
"grafast": "^0.0.1-beta.5", | ||
"graphile-build": "5.0.0-beta.6", | ||
"graphile-config": "^0.0.1-beta.1", | ||
@@ -97,3 +97,3 @@ "graphql": "^16.1.0-experimental-stream-defer.6", | ||
"pg": "^8.7.1", | ||
"ruru": "^2.0.0-beta.1", | ||
"ruru": "^2.0.0-beta.2", | ||
"ts-node": "^10.9.1", | ||
@@ -100,0 +100,0 @@ "typescript": "^5.0.4", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1086830
11565