@eleven-am/golem-core 0.1.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.
@@ -0,0 +1,16 @@
1
+ export type GolemAction = 'read' | 'create' | 'update' | 'delete';
2
+ export interface AuthorizationProvider {
3
+ authorize(action: GolemAction, model: string, context: unknown): Promise<void>;
4
+ constrain(action: GolemAction, model: string, context: unknown): Promise<unknown>;
5
+ check?(action: GolemAction, model: string, entity: unknown, context: unknown): Promise<boolean>;
6
+ checkField?(action: GolemAction, model: string, entity: unknown, field: string, context: unknown): Promise<boolean>;
7
+ classifyFields?(action: GolemAction, model: string, fields: readonly string[], context: unknown): Promise<Record<string, FieldClassification>>;
8
+ freshContext?(context: unknown): unknown;
9
+ }
10
+ export interface FieldClassification {
11
+ access: 'always' | 'conditional' | 'never';
12
+ requires?: readonly string[];
13
+ }
14
+ export declare function isConditionalConstraint(constraint: unknown): boolean;
15
+ export declare const NESTED_WRITE_ACTIONS: Record<string, GolemAction>;
16
+ export declare function mergeConstraint(where: unknown, constraint: unknown): unknown;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NESTED_WRITE_ACTIONS = void 0;
4
+ exports.isConditionalConstraint = isConditionalConstraint;
5
+ exports.mergeConstraint = mergeConstraint;
6
+ function isConditionalConstraint(constraint) {
7
+ return (constraint !== undefined &&
8
+ constraint !== null &&
9
+ typeof constraint === 'object' &&
10
+ Object.keys(constraint).length > 0);
11
+ }
12
+ exports.NESTED_WRITE_ACTIONS = {
13
+ create: 'create',
14
+ createMany: 'create',
15
+ connectOrCreate: 'create',
16
+ connect: 'update',
17
+ disconnect: 'update',
18
+ set: 'update',
19
+ update: 'update',
20
+ updateMany: 'update',
21
+ upsert: 'update',
22
+ delete: 'delete',
23
+ deleteMany: 'delete',
24
+ };
25
+ function mergeConstraint(where, constraint) {
26
+ if (constraint === undefined) {
27
+ return where;
28
+ }
29
+ if (where === undefined || where === null) {
30
+ return constraint;
31
+ }
32
+ return { AND: [where, constraint] };
33
+ }
@@ -0,0 +1,2 @@
1
+ /** Runs independent policy checks concurrently while reporting the earliest input-order failure. */
2
+ export declare function runPolicyChecks(checks: readonly (() => Promise<void>)[], concurrency?: number): Promise<void>;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runPolicyChecks = runPolicyChecks;
4
+ const DEFAULT_POLICY_CONCURRENCY = 8;
5
+ /** Runs independent policy checks concurrently while reporting the earliest input-order failure. */
6
+ async function runPolicyChecks(checks, concurrency = DEFAULT_POLICY_CONCURRENCY) {
7
+ const width = Math.max(1, Math.floor(concurrency));
8
+ for (let offset = 0; offset < checks.length; offset += width) {
9
+ const settled = await Promise.allSettled(checks.slice(offset, offset + width).map((check) => check()));
10
+ for (const result of settled) {
11
+ if (result.status === 'rejected') {
12
+ throw result.reason;
13
+ }
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,48 @@
1
+ import { GolemOperation } from './hooks';
2
+ export type DatamodelFieldKind = 'scalar' | 'object' | 'enum';
3
+ export interface DatamodelField {
4
+ name: string;
5
+ kind: DatamodelFieldKind;
6
+ type: string;
7
+ isList: boolean;
8
+ isRequired: boolean;
9
+ isUnique: boolean;
10
+ isId: boolean;
11
+ hasDefaultValue: boolean;
12
+ isReadOnly: boolean;
13
+ isUpdatedAt: boolean;
14
+ relationName?: string;
15
+ relationFromFields?: readonly string[];
16
+ relationToFields?: readonly string[];
17
+ }
18
+ export interface DatamodelModel {
19
+ name: string;
20
+ fields: readonly DatamodelField[];
21
+ }
22
+ export interface DatamodelEnum {
23
+ name: string;
24
+ values: readonly string[];
25
+ }
26
+ export interface DatamodelDocument<TModels = Record<string, string>> {
27
+ models: readonly DatamodelModel[];
28
+ enums: readonly DatamodelEnum[];
29
+ __models?: TModels;
30
+ }
31
+ export interface ModelConfig<TField extends string = string> {
32
+ subscriptions?: boolean;
33
+ operations?: readonly GolemOperation[];
34
+ hidden?: readonly TField[];
35
+ immutable?: readonly TField[];
36
+ maxTake?: number;
37
+ }
38
+ export type ModelsConfig<TModels> = {
39
+ [K in keyof TModels]?: false | ModelConfig<Extract<TModels[K], string>>;
40
+ };
41
+ export interface GolemDefaults {
42
+ subscriptions?: boolean;
43
+ operations?: readonly GolemOperation[];
44
+ maxTake?: number;
45
+ maxDepth?: number;
46
+ checkWriteResults?: boolean;
47
+ checkReadFields?: boolean;
48
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,20 @@
1
+ export type GolemErrorCode = 'NOT_FOUND' | 'CONFLICT' | 'BAD_USER_INPUT' | 'UNAUTHENTICATED' | 'FORBIDDEN';
2
+ export declare class GolemError extends Error {
3
+ readonly code: GolemErrorCode;
4
+ constructor(message: string, code: GolemErrorCode);
5
+ }
6
+ export declare class GolemNotFoundError extends GolemError {
7
+ constructor(message: string);
8
+ }
9
+ export declare class GolemConflictError extends GolemError {
10
+ constructor(message: string);
11
+ }
12
+ export declare class GolemValidationError extends GolemError {
13
+ constructor(message: string);
14
+ }
15
+ export declare class GolemUnauthorizedError extends GolemError {
16
+ constructor(message: string);
17
+ }
18
+ export declare class GolemForbiddenError extends GolemError {
19
+ constructor(message: string);
20
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GolemForbiddenError = exports.GolemUnauthorizedError = exports.GolemValidationError = exports.GolemConflictError = exports.GolemNotFoundError = exports.GolemError = void 0;
4
+ class GolemError extends Error {
5
+ code;
6
+ constructor(message, code) {
7
+ super(message);
8
+ this.code = code;
9
+ this.name = new.target.name;
10
+ }
11
+ }
12
+ exports.GolemError = GolemError;
13
+ class GolemNotFoundError extends GolemError {
14
+ constructor(message) {
15
+ super(message, 'NOT_FOUND');
16
+ }
17
+ }
18
+ exports.GolemNotFoundError = GolemNotFoundError;
19
+ class GolemConflictError extends GolemError {
20
+ constructor(message) {
21
+ super(message, 'CONFLICT');
22
+ }
23
+ }
24
+ exports.GolemConflictError = GolemConflictError;
25
+ class GolemValidationError extends GolemError {
26
+ constructor(message) {
27
+ super(message, 'BAD_USER_INPUT');
28
+ }
29
+ }
30
+ exports.GolemValidationError = GolemValidationError;
31
+ class GolemUnauthorizedError extends GolemError {
32
+ constructor(message) {
33
+ super(message, 'UNAUTHENTICATED');
34
+ }
35
+ }
36
+ exports.GolemUnauthorizedError = GolemUnauthorizedError;
37
+ class GolemForbiddenError extends GolemError {
38
+ constructor(message) {
39
+ super(message, 'FORBIDDEN');
40
+ }
41
+ }
42
+ exports.GolemForbiddenError = GolemForbiddenError;
@@ -0,0 +1,5 @@
1
+ export interface BufferedEvent {
2
+ publish(): Promise<void>;
3
+ }
4
+ export declare function bufferEvent(event: BufferedEvent): boolean;
5
+ export declare function withBufferedEvents<T>(fn: () => Promise<T>): Promise<T>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bufferEvent = bufferEvent;
4
+ exports.withBufferedEvents = withBufferedEvents;
5
+ const node_async_hooks_1 = require("node:async_hooks");
6
+ const storage = new node_async_hooks_1.AsyncLocalStorage();
7
+ function bufferEvent(event) {
8
+ const store = storage.getStore();
9
+ if (!store) {
10
+ return false;
11
+ }
12
+ store.buffer.push(event);
13
+ return true;
14
+ }
15
+ async function withBufferedEvents(fn) {
16
+ const store = { buffer: [] };
17
+ const result = await storage.run(store, fn);
18
+ for (const event of store.buffer) {
19
+ await event.publish();
20
+ }
21
+ return result;
22
+ }
@@ -0,0 +1,13 @@
1
+ export type GolemEventType = 'CREATED' | 'UPDATED' | 'DELETED';
2
+ export interface GolemEventPayload {
3
+ type: GolemEventType;
4
+ model: string;
5
+ id: string | number;
6
+ /** Pre-delete snapshot used only to authorize deletion delivery; never exposed as event.entity. */
7
+ entity?: Record<string, unknown>;
8
+ }
9
+ export interface GolemEventBus {
10
+ publish(topic: string, payload: GolemEventPayload): Promise<void>;
11
+ iterate(topic: string): AsyncIterableIterator<GolemEventPayload>;
12
+ }
13
+ export declare function eventTopic(model: string): string;
package/dist/events.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.eventTopic = eventTopic;
4
+ function eventTopic(model) {
5
+ return `golem.${model}`;
6
+ }
@@ -0,0 +1,17 @@
1
+ import { GraphQLResolveInfo } from 'graphql';
2
+ export interface ComputedFieldSpec {
3
+ model: string;
4
+ name: string;
5
+ type: string;
6
+ requires: readonly string[];
7
+ resolve: (parent: any, ctx: unknown, info: GraphQLResolveInfo) => unknown;
8
+ }
9
+ export interface CustomOperationSpec {
10
+ kind: 'query' | 'mutation';
11
+ name: string;
12
+ type: string;
13
+ args?: Record<string, string>;
14
+ resolve: (args: any, ctx: unknown, info: GraphQLResolveInfo) => unknown;
15
+ }
16
+ export type ComputedRequiresMap = ReadonlyMap<string, ReadonlyMap<string, readonly string[]>>;
17
+ export declare function buildComputedRequiresMap(specs: readonly ComputedFieldSpec[]): ComputedRequiresMap;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildComputedRequiresMap = buildComputedRequiresMap;
4
+ function buildComputedRequiresMap(specs) {
5
+ const map = new Map();
6
+ for (const spec of specs) {
7
+ const perModel = map.get(spec.model) ?? new Map();
8
+ perModel.set(spec.name, spec.requires);
9
+ map.set(spec.model, perModel);
10
+ }
11
+ return map;
12
+ }
@@ -0,0 +1,18 @@
1
+ export type GolemOperation = 'findOne' | 'findMany' | 'create' | 'update' | 'delete' | 'updateMany' | 'deleteMany';
2
+ export declare const ALL_OPERATIONS: readonly GolemOperation[];
3
+ export interface GolemHookContext {
4
+ model: string;
5
+ operation: GolemOperation;
6
+ context?: unknown;
7
+ }
8
+ export type BeforeHook<TRequest = any> = (request: TRequest, ctx: GolemHookContext) => TRequest | void | Promise<TRequest | void>;
9
+ export type AfterHook = (result: unknown, ctx: GolemHookContext) => void | Promise<void>;
10
+ export declare class HookRegistry {
11
+ private readonly beforeHooks;
12
+ private readonly afterHooks;
13
+ private static key;
14
+ registerBefore(model: string, operation: GolemOperation, hook: BeforeHook): void;
15
+ registerAfter(model: string, operation: GolemOperation, hook: AfterHook): void;
16
+ beforeFor(model: string, operation: GolemOperation): readonly BeforeHook[];
17
+ afterFor(model: string, operation: GolemOperation): readonly AfterHook[];
18
+ }
package/dist/hooks.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HookRegistry = exports.ALL_OPERATIONS = void 0;
4
+ exports.ALL_OPERATIONS = [
5
+ 'findOne',
6
+ 'findMany',
7
+ 'create',
8
+ 'update',
9
+ 'delete',
10
+ 'updateMany',
11
+ 'deleteMany',
12
+ ];
13
+ class HookRegistry {
14
+ beforeHooks = new Map();
15
+ afterHooks = new Map();
16
+ static key(model, operation) {
17
+ return `${model}.${operation}`;
18
+ }
19
+ registerBefore(model, operation, hook) {
20
+ const key = HookRegistry.key(model, operation);
21
+ const hooks = this.beforeHooks.get(key) ?? [];
22
+ hooks.push(hook);
23
+ this.beforeHooks.set(key, hooks);
24
+ }
25
+ registerAfter(model, operation, hook) {
26
+ const key = HookRegistry.key(model, operation);
27
+ const hooks = this.afterHooks.get(key) ?? [];
28
+ hooks.push(hook);
29
+ this.afterHooks.set(key, hooks);
30
+ }
31
+ beforeFor(model, operation) {
32
+ return this.beforeHooks.get(HookRegistry.key(model, operation)) ?? [];
33
+ }
34
+ afterFor(model, operation) {
35
+ return this.afterHooks.get(HookRegistry.key(model, operation)) ?? [];
36
+ }
37
+ }
38
+ exports.HookRegistry = HookRegistry;
@@ -0,0 +1,16 @@
1
+ export * from './authorization';
2
+ export * from './datamodel';
3
+ export * from './event-buffer';
4
+ export * from './errors';
5
+ export * from './events';
6
+ export * from './extensions';
7
+ export * from './hooks';
8
+ export * from './model-meta';
9
+ export * from './nested-writes';
10
+ export * from './publisher';
11
+ export * from './naming';
12
+ export * from './operations';
13
+ export * from './schema';
14
+ export * from './select';
15
+ export * from './typemap';
16
+ export * from './verify';
package/dist/index.js ADDED
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./authorization"), exports);
18
+ __exportStar(require("./datamodel"), exports);
19
+ __exportStar(require("./event-buffer"), exports);
20
+ __exportStar(require("./errors"), exports);
21
+ __exportStar(require("./events"), exports);
22
+ __exportStar(require("./extensions"), exports);
23
+ __exportStar(require("./hooks"), exports);
24
+ __exportStar(require("./model-meta"), exports);
25
+ __exportStar(require("./nested-writes"), exports);
26
+ __exportStar(require("./publisher"), exports);
27
+ __exportStar(require("./naming"), exports);
28
+ __exportStar(require("./operations"), exports);
29
+ __exportStar(require("./schema"), exports);
30
+ __exportStar(require("./select"), exports);
31
+ __exportStar(require("./typemap"), exports);
32
+ __exportStar(require("./verify"), exports);
@@ -0,0 +1,29 @@
1
+ import { GraphQLEnumType, GraphQLInputObjectType, GraphQLScalarType } from 'graphql';
2
+ import { DatamodelField, DatamodelModel } from './datamodel';
3
+ export interface InputBuilderContext {
4
+ modelsByName: Map<string, DatamodelModel>;
5
+ enumTypes: Map<string, GraphQLEnumType>;
6
+ whereUniqueInputs: Map<string, GraphQLInputObjectType>;
7
+ scalarType: (model: DatamodelModel, field: DatamodelField) => GraphQLScalarType;
8
+ hiddenFor: (model: string) => ReadonlySet<string>;
9
+ immutableFor: (model: string) => ReadonlySet<string>;
10
+ }
11
+ export declare class InputTypeRegistry {
12
+ private readonly ctx;
13
+ private readonly types;
14
+ constructor(ctx: InputBuilderContext);
15
+ private memo;
16
+ find(name: string): GraphQLInputObjectType | undefined;
17
+ private backRelationField;
18
+ private writableFields;
19
+ private updatableFields;
20
+ private scalarInputField;
21
+ private createRequired;
22
+ createInput(model: DatamodelModel): GraphQLInputObjectType;
23
+ private createWithoutInput;
24
+ private buildCreateInput;
25
+ private nestedCreateInput;
26
+ updateInput(model: DatamodelModel): GraphQLInputObjectType;
27
+ private nestedUpdateInput;
28
+ updateManyInput(model: DatamodelModel): GraphQLInputObjectType;
29
+ }
package/dist/inputs.js ADDED
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InputTypeRegistry = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const naming_1 = require("./naming");
6
+ class InputTypeRegistry {
7
+ ctx;
8
+ types = new Map();
9
+ constructor(ctx) {
10
+ this.ctx = ctx;
11
+ }
12
+ memo(name, factory) {
13
+ const existing = this.types.get(name);
14
+ if (existing) {
15
+ return existing;
16
+ }
17
+ const created = factory();
18
+ this.types.set(name, created);
19
+ return created;
20
+ }
21
+ find(name) {
22
+ return this.types.get(name);
23
+ }
24
+ backRelationField(model, field) {
25
+ const target = this.ctx.modelsByName.get(field.type);
26
+ if (!target) {
27
+ throw new Error(`Relation ${model.name}.${field.name} targets unknown model ${field.type}`);
28
+ }
29
+ const back = target.fields.find((f) => f.kind === 'object' && f.relationName === field.relationName && f.type === model.name);
30
+ if (!back) {
31
+ throw new Error(`Relation ${model.name}.${field.name} has no back relation on ${field.type}`);
32
+ }
33
+ return back;
34
+ }
35
+ writableFields(model, excludeRelation) {
36
+ const hidden = this.ctx.hiddenFor(model.name);
37
+ return model.fields.filter((field) => {
38
+ if (field.isReadOnly || hidden.has(field.name)) {
39
+ return false;
40
+ }
41
+ if (excludeRelation && field.name === excludeRelation.name) {
42
+ return false;
43
+ }
44
+ return true;
45
+ });
46
+ }
47
+ updatableFields(model) {
48
+ const immutable = this.ctx.immutableFor(model.name);
49
+ return this.writableFields(model).filter((field) => !immutable.has(field.name));
50
+ }
51
+ scalarInputField(model, field, required) {
52
+ const base = field.kind === 'enum' ? this.ctx.enumTypes.get(field.type) : this.ctx.scalarType(model, field);
53
+ return { type: required ? new graphql_1.GraphQLNonNull(base) : base };
54
+ }
55
+ createRequired(field) {
56
+ return field.isRequired && !field.hasDefaultValue && !field.isUpdatedAt;
57
+ }
58
+ createInput(model) {
59
+ return this.memo(`${model.name}CreateInput`, () => this.buildCreateInput(`${model.name}CreateInput`, model, undefined));
60
+ }
61
+ createWithoutInput(model, excludeRelation) {
62
+ const name = `${model.name}CreateWithout${(0, naming_1.ucFirst)(excludeRelation.name)}Input`;
63
+ return this.memo(name, () => this.buildCreateInput(name, model, excludeRelation));
64
+ }
65
+ buildCreateInput(name, model, excludeRelation) {
66
+ return new graphql_1.GraphQLInputObjectType({
67
+ name,
68
+ fields: () => {
69
+ const fields = {};
70
+ for (const field of this.writableFields(model, excludeRelation)) {
71
+ if (field.kind === 'object') {
72
+ if (!this.ctx.modelsByName.has(field.type)) {
73
+ continue;
74
+ }
75
+ fields[field.name] = { type: this.nestedCreateInput(model, field) };
76
+ }
77
+ else {
78
+ fields[field.name] = this.scalarInputField(model, field, this.createRequired(field));
79
+ }
80
+ }
81
+ return fields;
82
+ },
83
+ });
84
+ }
85
+ nestedCreateInput(model, field) {
86
+ const target = this.ctx.modelsByName.get(field.type);
87
+ const back = this.backRelationField(model, field);
88
+ const whereUnique = this.ctx.whereUniqueInputs.get(target.name);
89
+ if (field.isList) {
90
+ const envelope = this.memo(`${target.name}CreateNestedManyWithout${(0, naming_1.ucFirst)(back.name)}Input`, () => new graphql_1.GraphQLInputObjectType({
91
+ name: `${target.name}CreateNestedManyWithout${(0, naming_1.ucFirst)(back.name)}Input`,
92
+ fields: () => ({
93
+ create: { type: new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(this.createWithoutInput(target, back))) },
94
+ connect: { type: new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(whereUnique)) },
95
+ }),
96
+ }));
97
+ return envelope;
98
+ }
99
+ const envelope = this.memo(`${target.name}CreateNestedOneWithout${(0, naming_1.ucFirst)(back.name)}Input`, () => new graphql_1.GraphQLInputObjectType({
100
+ name: `${target.name}CreateNestedOneWithout${(0, naming_1.ucFirst)(back.name)}Input`,
101
+ fields: () => ({
102
+ create: { type: this.createWithoutInput(target, back) },
103
+ connect: { type: whereUnique },
104
+ }),
105
+ }));
106
+ return field.isRequired ? new graphql_1.GraphQLNonNull(envelope) : envelope;
107
+ }
108
+ updateInput(model) {
109
+ return this.memo(`${model.name}UpdateInput`, () => new graphql_1.GraphQLInputObjectType({
110
+ name: `${model.name}UpdateInput`,
111
+ fields: () => {
112
+ const fields = {};
113
+ for (const field of this.updatableFields(model)) {
114
+ if (field.kind === 'object') {
115
+ if (!this.ctx.modelsByName.has(field.type)) {
116
+ continue;
117
+ }
118
+ fields[field.name] = { type: this.nestedUpdateInput(field) };
119
+ }
120
+ else {
121
+ fields[field.name] = this.scalarInputField(model, field, false);
122
+ }
123
+ }
124
+ return fields;
125
+ },
126
+ }));
127
+ }
128
+ nestedUpdateInput(field) {
129
+ const target = this.ctx.modelsByName.get(field.type);
130
+ const whereUnique = this.ctx.whereUniqueInputs.get(target.name);
131
+ if (field.isList) {
132
+ return this.memo(`${target.name}UpdateManyRelationInput`, () => new graphql_1.GraphQLInputObjectType({
133
+ name: `${target.name}UpdateManyRelationInput`,
134
+ fields: () => ({
135
+ connect: { type: new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(whereUnique)) },
136
+ disconnect: { type: new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(whereUnique)) },
137
+ }),
138
+ }));
139
+ }
140
+ if (field.isRequired) {
141
+ return this.memo(`${target.name}UpdateOneRequiredRelationInput`, () => new graphql_1.GraphQLInputObjectType({
142
+ name: `${target.name}UpdateOneRequiredRelationInput`,
143
+ fields: () => ({
144
+ connect: { type: whereUnique },
145
+ }),
146
+ }));
147
+ }
148
+ return this.memo(`${target.name}UpdateOneRelationInput`, () => new graphql_1.GraphQLInputObjectType({
149
+ name: `${target.name}UpdateOneRelationInput`,
150
+ fields: () => ({
151
+ connect: { type: whereUnique },
152
+ disconnect: { type: graphql_1.GraphQLBoolean },
153
+ }),
154
+ }));
155
+ }
156
+ updateManyInput(model) {
157
+ return this.memo(`${model.name}UpdateManyInput`, () => new graphql_1.GraphQLInputObjectType({
158
+ name: `${model.name}UpdateManyInput`,
159
+ fields: () => {
160
+ const fields = {};
161
+ for (const field of this.updatableFields(model)) {
162
+ if (field.kind === 'object') {
163
+ continue;
164
+ }
165
+ fields[field.name] = this.scalarInputField(model, field, false);
166
+ }
167
+ return fields;
168
+ },
169
+ }));
170
+ }
171
+ }
172
+ exports.InputTypeRegistry = InputTypeRegistry;
@@ -0,0 +1,10 @@
1
+ import { DatamodelField, DatamodelModel } from './datamodel';
2
+ export interface ModelMetadata {
3
+ readonly model: DatamodelModel;
4
+ readonly fieldsByName: ReadonlyMap<string, DatamodelField>;
5
+ readonly scalarFields: readonly DatamodelField[];
6
+ readonly relations: readonly DatamodelField[];
7
+ readonly primaryKey?: DatamodelField;
8
+ }
9
+ export type ModelMetadataIndex = ReadonlyMap<string, ModelMetadata>;
10
+ export declare function buildModelMetadata(models: readonly DatamodelModel[]): ModelMetadataIndex;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildModelMetadata = buildModelMetadata;
4
+ class ImmutableMap {
5
+ #data;
6
+ constructor(entries) {
7
+ this.#data = new Map(entries);
8
+ Object.freeze(this);
9
+ }
10
+ get size() { return this.#data.size; }
11
+ get(key) { return this.#data.get(key); }
12
+ has(key) { return this.#data.has(key); }
13
+ entries() { return this.#data.entries(); }
14
+ keys() { return this.#data.keys(); }
15
+ values() { return this.#data.values(); }
16
+ [Symbol.iterator]() { return this.#data[Symbol.iterator](); }
17
+ forEach(callbackfn, thisArg) {
18
+ this.#data.forEach((value, key) => callbackfn.call(thisArg, value, key, this));
19
+ }
20
+ }
21
+ function buildModelMetadata(models) {
22
+ const entries = models.map((model) => {
23
+ const scalarFields = Object.freeze(model.fields.filter((field) => field.kind !== 'object'));
24
+ const relations = Object.freeze(model.fields.filter((field) => field.kind === 'object'));
25
+ return [
26
+ model.name,
27
+ Object.freeze({
28
+ model,
29
+ fieldsByName: new ImmutableMap(model.fields.map((field) => [field.name, field])),
30
+ scalarFields,
31
+ relations,
32
+ primaryKey: scalarFields.find((field) => field.isId),
33
+ }),
34
+ ];
35
+ });
36
+ return new ImmutableMap(entries);
37
+ }
@@ -0,0 +1,10 @@
1
+ export declare function lcFirst(name: string): string;
2
+ export declare function ucFirst(name: string): string;
3
+ export declare function findOneFieldName(model: string): string;
4
+ export declare function findManyFieldName(model: string): string;
5
+ export declare function createFieldName(model: string): string;
6
+ export declare function updateFieldName(model: string): string;
7
+ export declare function deleteFieldName(model: string): string;
8
+ export declare function updateManyFieldName(model: string): string;
9
+ export declare function deleteManyFieldName(model: string): string;
10
+ export declare function eventsFieldName(model: string): string;