@axinom/mosaic-graphql-common 0.1.0-rc.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.
- package/README.md +16 -0
- package/dist/common/checks.d.ts +9 -0
- package/dist/common/checks.d.ts.map +1 -0
- package/dist/common/checks.js +21 -0
- package/dist/common/checks.js.map +1 -0
- package/dist/common/index.d.ts +3 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +19 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/types.d.ts +13 -0
- package/dist/common/types.d.ts.map +1 -0
- package/dist/common/types.js +15 -0
- package/dist/common/types.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/add-error-codes-enum-plugin.d.ts +27 -0
- package/dist/plugins/add-error-codes-enum-plugin.d.ts.map +1 -0
- package/dist/plugins/add-error-codes-enum-plugin.js +78 -0
- package/dist/plugins/add-error-codes-enum-plugin.js.map +1 -0
- package/dist/plugins/annotate-types-with-permissions-plugin.d.ts +22 -0
- package/dist/plugins/annotate-types-with-permissions-plugin.d.ts.map +1 -0
- package/dist/plugins/annotate-types-with-permissions-plugin.js +145 -0
- package/dist/plugins/annotate-types-with-permissions-plugin.js.map +1 -0
- package/dist/plugins/deprecate-stray-node-id-fields-plugin.d.ts +14 -0
- package/dist/plugins/deprecate-stray-node-id-fields-plugin.d.ts.map +1 -0
- package/dist/plugins/deprecate-stray-node-id-fields-plugin.js +37 -0
- package/dist/plugins/deprecate-stray-node-id-fields-plugin.js.map +1 -0
- package/dist/plugins/generic-bulk-plugin-factory.d.ts +49 -0
- package/dist/plugins/generic-bulk-plugin-factory.d.ts.map +1 -0
- package/dist/plugins/generic-bulk-plugin-factory.js +181 -0
- package/dist/plugins/generic-bulk-plugin-factory.js.map +1 -0
- package/dist/plugins/graphiql-management-mode-plugin-hook.d.ts +13 -0
- package/dist/plugins/graphiql-management-mode-plugin-hook.d.ts.map +1 -0
- package/dist/plugins/graphiql-management-mode-plugin-hook.js +44 -0
- package/dist/plugins/graphiql-management-mode-plugin-hook.js.map +1 -0
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +26 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/omit-from-query-root-plugin.d.ts +17 -0
- package/dist/plugins/omit-from-query-root-plugin.d.ts.map +1 -0
- package/dist/plugins/omit-from-query-root-plugin.js +43 -0
- package/dist/plugins/omit-from-query-root-plugin.js.map +1 -0
- package/dist/plugins/operations-enum-generator-plugin-factory.d.ts +15 -0
- package/dist/plugins/operations-enum-generator-plugin-factory.d.ts.map +1 -0
- package/dist/plugins/operations-enum-generator-plugin-factory.js +108 -0
- package/dist/plugins/operations-enum-generator-plugin-factory.js.map +1 -0
- package/dist/plugins/subscriptions-plugin-factory.d.ts +9 -0
- package/dist/plugins/subscriptions-plugin-factory.d.ts.map +1 -0
- package/dist/plugins/subscriptions-plugin-factory.js +67 -0
- package/dist/plugins/subscriptions-plugin-factory.js.map +1 -0
- package/dist/plugins/validation-directives-plugin.d.ts +6 -0
- package/dist/plugins/validation-directives-plugin.d.ts.map +1 -0
- package/dist/plugins/validation-directives-plugin.js +117 -0
- package/dist/plugins/validation-directives-plugin.js.map +1 -0
- package/dist/postgraphile/enhance-graphql-errors.d.ts +48 -0
- package/dist/postgraphile/enhance-graphql-errors.d.ts.map +1 -0
- package/dist/postgraphile/enhance-graphql-errors.js +67 -0
- package/dist/postgraphile/enhance-graphql-errors.js.map +1 -0
- package/dist/postgraphile/index.d.ts +4 -0
- package/dist/postgraphile/index.d.ts.map +1 -0
- package/dist/postgraphile/index.js +20 -0
- package/dist/postgraphile/index.js.map +1 -0
- package/dist/postgraphile/postgraphile-options-builder.d.ts +273 -0
- package/dist/postgraphile/postgraphile-options-builder.d.ts.map +1 -0
- package/dist/postgraphile/postgraphile-options-builder.js +419 -0
- package/dist/postgraphile/postgraphile-options-builder.js.map +1 -0
- package/dist/postgraphile/websocket-utils.d.ts +11 -0
- package/dist/postgraphile/websocket-utils.d.ts.map +1 -0
- package/dist/postgraphile/websocket-utils.js +17 -0
- package/dist/postgraphile/websocket-utils.js.map +1 -0
- package/package.json +61 -0
- package/src/common/checks.ts +23 -0
- package/src/common/index.ts +2 -0
- package/src/common/types.ts +15 -0
- package/src/index.ts +3 -0
- package/src/plugins/add-error-codes-enum-plugin.ts +102 -0
- package/src/plugins/annotate-types-with-permissions-plugin.spec.ts +158 -0
- package/src/plugins/annotate-types-with-permissions-plugin.ts +205 -0
- package/src/plugins/deprecate-stray-node-id-fields-plugin.ts +41 -0
- package/src/plugins/generic-bulk-plugin-factory.ts +313 -0
- package/src/plugins/graphiql-management-mode-plugin-hook.ts +46 -0
- package/src/plugins/index.ts +9 -0
- package/src/plugins/omit-from-query-root-plugin.ts +69 -0
- package/src/plugins/operations-enum-generator-plugin-factory.ts +130 -0
- package/src/plugins/subscriptions-plugin-factory.ts +114 -0
- package/src/plugins/validation-directives-plugin.ts +141 -0
- package/src/postgraphile/enhance-graphql-errors.spec.ts +241 -0
- package/src/postgraphile/enhance-graphql-errors.ts +138 -0
- package/src/postgraphile/index.ts +3 -0
- package/src/postgraphile/postgraphile-options-builder.spec.ts +744 -0
- package/src/postgraphile/postgraphile-options-builder.ts +510 -0
- package/src/postgraphile/websocket-utils.ts +19 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GenericBulkPluginFactory = void 0;
|
|
4
|
+
const graphile_utils_1 = require("graphile-utils");
|
|
5
|
+
const common_1 = require("../common");
|
|
6
|
+
/**
|
|
7
|
+
* Get all the database IDs from the entities that were selected via the GraphQL filter
|
|
8
|
+
*/
|
|
9
|
+
const getEntityIds = async (filter, graphql, args, context, schema) => {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
if (filter.queryName === undefined) {
|
|
12
|
+
throw new Error(`No query found for the filter of type '${filter.filterName}'.`);
|
|
13
|
+
}
|
|
14
|
+
const queryResult = await graphql.execute(schema, (0, graphile_utils_1.gql) `
|
|
15
|
+
query getEntityIds($filter: ${filter.filterName}) {
|
|
16
|
+
entities: ${filter.queryName}(filter: $filter) {
|
|
17
|
+
nodes {
|
|
18
|
+
${filter.primaryKeyName}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
`, undefined, context, args);
|
|
23
|
+
return (_b = (_a = queryResult === null || queryResult === void 0 ? void 0 : queryResult.data) === null || _a === void 0 ? void 0 : _a.entities) === null || _b === void 0 ? void 0 : _b.nodes.map((entity) => {
|
|
24
|
+
(0, common_1.assertDictionary)(entity);
|
|
25
|
+
return entity[filter.primaryKeyName];
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
const getEntityTypeFromCollectionType = (type) => {
|
|
29
|
+
var _a;
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
const fields = type._fields();
|
|
32
|
+
let tempType = (_a = fields === null || fields === void 0 ? void 0 : fields.nodes) === null || _a === void 0 ? void 0 : _a.type;
|
|
33
|
+
if (tempType !== undefined) {
|
|
34
|
+
while (tempType === null || tempType === void 0 ? void 0 : tempType.ofType) {
|
|
35
|
+
tempType = tempType === null || tempType === void 0 ? void 0 : tempType.ofType;
|
|
36
|
+
}
|
|
37
|
+
return tempType === null || tempType === void 0 ? void 0 : tempType.name;
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
};
|
|
41
|
+
const setPayloadGqlType = (build, pkDbType) => {
|
|
42
|
+
let pkGqlType;
|
|
43
|
+
let bulkMutationPayloadName;
|
|
44
|
+
switch (pkDbType) {
|
|
45
|
+
case 'uuid': {
|
|
46
|
+
bulkMutationPayloadName = 'BulkMutationUuidPayload';
|
|
47
|
+
pkGqlType = build.getTypeByName('UUID');
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case 'int4':
|
|
51
|
+
default: {
|
|
52
|
+
bulkMutationPayloadName = 'BulkMutationIntPayload';
|
|
53
|
+
pkGqlType = build.graphql.GraphQLInt;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const existingPayloadType = build.getTypeByName(bulkMutationPayloadName);
|
|
58
|
+
if (existingPayloadType !== undefined) {
|
|
59
|
+
return existingPayloadType;
|
|
60
|
+
}
|
|
61
|
+
build.addType(new build.graphql.GraphQLObjectType({
|
|
62
|
+
name: bulkMutationPayloadName,
|
|
63
|
+
description: 'Bulk mutation payload type.',
|
|
64
|
+
fields: () => ({
|
|
65
|
+
affectedIds: {
|
|
66
|
+
type: build.graphql.GraphQLList(pkGqlType),
|
|
67
|
+
},
|
|
68
|
+
totalCount: { type: build.graphql.GraphQLInt },
|
|
69
|
+
}),
|
|
70
|
+
}));
|
|
71
|
+
return build.getTypeByName(bulkMutationPayloadName);
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Plugin factory to create bulk mutations based on query filters
|
|
75
|
+
* @param callback The callback that shall perform the actual bulk operation. It
|
|
76
|
+
* receives different parameters from the base plugin to assist with the
|
|
77
|
+
* operation, e.g. a list of ids for which the bulk operation shall be performed.
|
|
78
|
+
* @param definePlugin The callback that decides for which filters a bulk action is defined.
|
|
79
|
+
* @param inputType Defines additional input parameters for the bulk action. The values are forwarded as part of the message payload.
|
|
80
|
+
*/
|
|
81
|
+
const GenericBulkPluginFactory = (callback, definePlugin, inputType) => {
|
|
82
|
+
return async (builder) => {
|
|
83
|
+
// initialize the availableBulkFilters to collect all filters usable for bulk mutations
|
|
84
|
+
builder.hook('build', (build) => {
|
|
85
|
+
build.availableBulkFilters = {};
|
|
86
|
+
if (inputType !== undefined &&
|
|
87
|
+
build.getTypeByName(inputType.name) === undefined) {
|
|
88
|
+
build.addType(inputType);
|
|
89
|
+
}
|
|
90
|
+
return build;
|
|
91
|
+
});
|
|
92
|
+
builder.hook('GraphQLInputObjectType:fields', (fields, build, { scope: { isPgConnectionFilter, pgIntrospection }, Self }) => {
|
|
93
|
+
var _a;
|
|
94
|
+
if (isPgConnectionFilter &&
|
|
95
|
+
(pgIntrospection === null || pgIntrospection === void 0 ? void 0 : pgIntrospection.kind) === 'class' &&
|
|
96
|
+
(pgIntrospection === null || pgIntrospection === void 0 ? void 0 : pgIntrospection.classKind) !== 'c' && // c represents composite types which doesn't have primary keys.
|
|
97
|
+
((_a = pgIntrospection === null || pgIntrospection === void 0 ? void 0 : pgIntrospection.primaryKeyConstraint) === null || _a === void 0 ? void 0 : _a.type) === 'p' &&
|
|
98
|
+
(pgIntrospection === null || pgIntrospection === void 0 ? void 0 : pgIntrospection.primaryKeyConstraint.keyAttributes.length) === 1) {
|
|
99
|
+
const { name, type } = pgIntrospection.primaryKeyConstraint.keyAttributes[0];
|
|
100
|
+
const availableBulkFilters = build
|
|
101
|
+
.availableBulkFilters;
|
|
102
|
+
const table = pgIntrospection;
|
|
103
|
+
availableBulkFilters[Self.name] = {
|
|
104
|
+
tableName: table.name,
|
|
105
|
+
primaryKeyName: name,
|
|
106
|
+
primaryKeyType: type.name,
|
|
107
|
+
filterName: Self.name,
|
|
108
|
+
filterType: Self,
|
|
109
|
+
queryName: 'set-later',
|
|
110
|
+
typeName: 'set-later',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return fields;
|
|
114
|
+
});
|
|
115
|
+
// Add the query endpoints to the corresponding filters
|
|
116
|
+
// Add the bulk mutations based on what the plugin needs
|
|
117
|
+
builder.hook('GraphQLObjectType:fields', (fields, build, { scope: { isRootQuery, isRootMutation } }) => {
|
|
118
|
+
var _a, _b, _c, _d;
|
|
119
|
+
const bulkFilters = build.availableBulkFilters;
|
|
120
|
+
if (isRootQuery) {
|
|
121
|
+
// Root query is called first - gather the query operation names
|
|
122
|
+
for (const queryName in fields) {
|
|
123
|
+
const element = fields[queryName];
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
125
|
+
const filterName = (_c = (_b = (_a = element === null || element === void 0 ? void 0 : element.args) === null || _a === void 0 ? void 0 : _a.filter) === null || _b === void 0 ? void 0 : _b.type) === null || _c === void 0 ? void 0 : _c.name;
|
|
126
|
+
if (Object.prototype.hasOwnProperty.call(fields, queryName) &&
|
|
127
|
+
element !== undefined &&
|
|
128
|
+
filterName !== undefined &&
|
|
129
|
+
bulkFilters[filterName] !== undefined) {
|
|
130
|
+
// we found a query which is using a connection filter property that is usable for bulk mutations
|
|
131
|
+
const filter = bulkFilters[filterName];
|
|
132
|
+
filter.queryName = queryName;
|
|
133
|
+
filter.typeName =
|
|
134
|
+
(_d = getEntityTypeFromCollectionType(element.type)) !== null && _d !== void 0 ? _d : filterName.slice(0, -1 * 'Filter'.length);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (isRootMutation) {
|
|
139
|
+
// Root mutation is called after root query - actually add mutations
|
|
140
|
+
for (const filterName in bulkFilters) {
|
|
141
|
+
const filter = bulkFilters[filterName];
|
|
142
|
+
const settings = definePlugin(filter);
|
|
143
|
+
if (settings !== undefined) {
|
|
144
|
+
const args = Object.assign({ filter: {
|
|
145
|
+
type: filter.filterType,
|
|
146
|
+
} }, (inputType !== undefined && {
|
|
147
|
+
input: { type: inputType },
|
|
148
|
+
}));
|
|
149
|
+
const payloadType = setPayloadGqlType(build, filter.primaryKeyType);
|
|
150
|
+
const operation = {
|
|
151
|
+
type: payloadType,
|
|
152
|
+
args,
|
|
153
|
+
async resolve(_parent, input, context, resolveInfo) {
|
|
154
|
+
const ids = await getEntityIds(filter, build.graphql, input, context, resolveInfo.schema);
|
|
155
|
+
const { input: additionalInput } = input;
|
|
156
|
+
await callback({
|
|
157
|
+
entityIds: ids,
|
|
158
|
+
entityType: filter.typeName,
|
|
159
|
+
primaryKeyName: filter.primaryKeyName,
|
|
160
|
+
tableName: filter.tableName,
|
|
161
|
+
graphQLAdditionalInput: additionalInput,
|
|
162
|
+
graphQLContext: context,
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
affectedIds: ids,
|
|
166
|
+
totalCount: ids.length,
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
build.extend(fields, {
|
|
171
|
+
[settings.graphQLEndpointName]: operation,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return fields;
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
exports.GenericBulkPluginFactory = GenericBulkPluginFactory;
|
|
181
|
+
//# sourceMappingURL=generic-bulk-plugin-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generic-bulk-plugin-factory.js","sourceRoot":"","sources":["../../src/plugins/generic-bulk-plugin-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on:
|
|
3
|
+
*
|
|
4
|
+
* https://gist.github.com/bkeating/cfe0d5e72bd3f9f1f77e1a2ff2309972
|
|
5
|
+
*
|
|
6
|
+
* with some additions for the PostGraphiQL extension.
|
|
7
|
+
*/
|
|
8
|
+
import { PostGraphilePlugin } from 'postgraphile';
|
|
9
|
+
/**
|
|
10
|
+
* This plugin override changes the branding piece of graphiql.
|
|
11
|
+
*/
|
|
12
|
+
export declare const GraphiqlManagementModePluginHook: PostGraphilePlugin;
|
|
13
|
+
//# sourceMappingURL=graphiql-management-mode-plugin-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphiql-management-mode-plugin-hook.d.ts","sourceRoot":"","sources":["../../src/plugins/graphiql-management-mode-plugin-hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,gCAAgC,EAAE,kBAgC9C,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Based on:
|
|
4
|
+
*
|
|
5
|
+
* https://gist.github.com/bkeating/cfe0d5e72bd3f9f1f77e1a2ff2309972
|
|
6
|
+
*
|
|
7
|
+
* with some additions for the PostGraphiQL extension.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.GraphiqlManagementModePluginHook = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* This plugin override changes the branding piece of graphiql.
|
|
13
|
+
*/
|
|
14
|
+
exports.GraphiqlManagementModePluginHook = {
|
|
15
|
+
['postgraphile:graphiql:html'](html) {
|
|
16
|
+
return html.replace('</head>', `
|
|
17
|
+
<style>
|
|
18
|
+
/* GraphiQL Management Styles */
|
|
19
|
+
#root .graphiql-container .doc-explorer-title-bar,
|
|
20
|
+
#root .graphiql-container .historyPaneWrap > section,
|
|
21
|
+
#secondary-editor-title {
|
|
22
|
+
background: #aaa;
|
|
23
|
+
}
|
|
24
|
+
#root .graphiql-container .topBar,
|
|
25
|
+
#root .graphiql-container .docExplorerShow {
|
|
26
|
+
background: #888;
|
|
27
|
+
}
|
|
28
|
+
#root .graphiql-container .topBar .toolbar-button,
|
|
29
|
+
#root .graphiql-container .topBar .toolbar-button > svg,
|
|
30
|
+
#root .graphiql-container .topBar .execute-button {
|
|
31
|
+
box-shadow: none;
|
|
32
|
+
background: #555;
|
|
33
|
+
color: #ddd;
|
|
34
|
+
fill: #ddd;
|
|
35
|
+
}
|
|
36
|
+
#root .graphiql-container .topBar .toolbar-button {
|
|
37
|
+
border-radius: 0;
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
40
|
+
</head>
|
|
41
|
+
`);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=graphiql-management-mode-plugin-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphiql-management-mode-plugin-hook.js","sourceRoot":"","sources":["../../src/plugins/graphiql-management-mode-plugin-hook.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAIH;;GAEG;AACU,QAAA,gCAAgC,GAAuB;IAClE,CAAC,4BAA4B,CAAC,CAAC,IAAY;QACzC,OAAO,IAAI,CAAC,OAAO,CACjB,SAAS,EACT;;;;;;;;;;;;;;;;;;;;;;;;;QAyBE,CACH,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './add-error-codes-enum-plugin';
|
|
2
|
+
export * from './annotate-types-with-permissions-plugin';
|
|
3
|
+
export * from './deprecate-stray-node-id-fields-plugin';
|
|
4
|
+
export * from './generic-bulk-plugin-factory';
|
|
5
|
+
export * from './graphiql-management-mode-plugin-hook';
|
|
6
|
+
export * from './omit-from-query-root-plugin';
|
|
7
|
+
export * from './operations-enum-generator-plugin-factory';
|
|
8
|
+
export * from './subscriptions-plugin-factory';
|
|
9
|
+
export * from './validation-directives-plugin';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0CAA0C,CAAC;AACzD,cAAc,yCAAyC,CAAC;AACxD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
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("./add-error-codes-enum-plugin"), exports);
|
|
18
|
+
__exportStar(require("./annotate-types-with-permissions-plugin"), exports);
|
|
19
|
+
__exportStar(require("./deprecate-stray-node-id-fields-plugin"), exports);
|
|
20
|
+
__exportStar(require("./generic-bulk-plugin-factory"), exports);
|
|
21
|
+
__exportStar(require("./graphiql-management-mode-plugin-hook"), exports);
|
|
22
|
+
__exportStar(require("./omit-from-query-root-plugin"), exports);
|
|
23
|
+
__exportStar(require("./operations-enum-generator-plugin-factory"), exports);
|
|
24
|
+
__exportStar(require("./subscriptions-plugin-factory"), exports);
|
|
25
|
+
__exportStar(require("./validation-directives-plugin"), exports);
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gEAA8C;AAC9C,2EAAyD;AACzD,0EAAwD;AACxD,gEAA8C;AAC9C,yEAAuD;AACvD,gEAA8C;AAC9C,6EAA2D;AAC3D,iEAA+C;AAC/C,iEAA+C"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Plugin } from 'postgraphile';
|
|
2
|
+
/**
|
|
3
|
+
* Plugin for omitting tables from query root but keeping them still accessible
|
|
4
|
+
* from entities through relations.
|
|
5
|
+
*
|
|
6
|
+
* Add `omitFromQueryRoot: true,` to `tags` object of postgraphile smart tags
|
|
7
|
+
* for table you want to omit.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* This is different from `@omit all many` as the tables are still accessible
|
|
11
|
+
* through relations.
|
|
12
|
+
*
|
|
13
|
+
* References:
|
|
14
|
+
* - https://discord.com/channels/489127045289476126/498852330754801666/578654093963427860
|
|
15
|
+
*/
|
|
16
|
+
export declare const OmitFromQueryRootPlugin: Plugin;
|
|
17
|
+
//# sourceMappingURL=omit-from-query-root-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"omit-from-query-root-plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/omit-from-query-root-plugin.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,MAAM,EAAE,MAAM,cAAc,CAAC;AAclD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,uBAAuB,EAAE,MA2BrC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OmitFromQueryRootPlugin = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Plugin for omitting tables from query root but keeping them still accessible
|
|
6
|
+
* from entities through relations.
|
|
7
|
+
*
|
|
8
|
+
* Add `omitFromQueryRoot: true,` to `tags` object of postgraphile smart tags
|
|
9
|
+
* for table you want to omit.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* This is different from `@omit all many` as the tables are still accessible
|
|
13
|
+
* through relations.
|
|
14
|
+
*
|
|
15
|
+
* References:
|
|
16
|
+
* - https://discord.com/channels/489127045289476126/498852330754801666/578654093963427860
|
|
17
|
+
*/
|
|
18
|
+
const OmitFromQueryRootPlugin = (builder) => {
|
|
19
|
+
builder.hook('GraphQLObjectType:fields', (fields, build, context) => {
|
|
20
|
+
const hookContext = context;
|
|
21
|
+
const introspection = build.pgIntrospectionResultsByKind;
|
|
22
|
+
const inflection = build.inflection;
|
|
23
|
+
if (hookContext.Self.name !== 'Query' || !hookContext.scope.isRootQuery) {
|
|
24
|
+
return fields;
|
|
25
|
+
}
|
|
26
|
+
const tablesToExclude = introspection.class.filter((cls) => cls.tags.omitFromQueryRoot === true);
|
|
27
|
+
// Remove both single item query and paginated query.
|
|
28
|
+
const fieldNamesToExclude = [].concat(...tablesToExclude.map((cls) => [
|
|
29
|
+
inflection.camelCase(`${inflection._singularizedTableName(cls)}`),
|
|
30
|
+
inflection.camelCase(inflection.distinctPluralize(inflection._singularizedTableName(cls))),
|
|
31
|
+
]));
|
|
32
|
+
return removeProperties(fields, fieldNamesToExclude);
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
exports.OmitFromQueryRootPlugin = OmitFromQueryRootPlugin;
|
|
36
|
+
function removeProperties(obj, keysToRemove) {
|
|
37
|
+
const result = Object.assign({}, obj);
|
|
38
|
+
for (const key of keysToRemove) {
|
|
39
|
+
delete result[key];
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=omit-from-query-root-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"omit-from-query-root-plugin.js","sourceRoot":"","sources":["../../src/plugins/omit-from-query-root-plugin.ts"],"names":[],"mappings":";;;AAgBA;;;;;;;;;;;;;GAaG;AACI,MAAM,uBAAuB,GAAW,CAAC,OAAO,EAAE,EAAE;IACzD,OAAO,CAAC,IAAI,CAAC,0BAA0B,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAClE,MAAM,WAAW,GAAgB,OAAsB,CAAC;QACxD,MAAM,aAAa,GACjB,KAAK,CAAC,4BAA4B,CAAC;QACrC,MAAM,UAAU,GAAe,KAAK,CAAC,UAAU,CAAC;QAEhD,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE;YACvE,OAAO,MAAM,CAAC;SACf;QAED,MAAM,eAAe,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAChD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,KAAK,IAAI,CAC7C,CAAC;QAEF,qDAAqD;QACrD,MAAM,mBAAmB,GAAI,EAAe,CAAC,MAAM,CACjD,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;YAC9B,UAAU,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC;YACjE,UAAU,CAAC,SAAS,CAClB,UAAU,CAAC,iBAAiB,CAAC,UAAU,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CACrE;SACF,CAAC,CACH,CAAC;QAEF,OAAO,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AA3BW,QAAA,uBAAuB,2BA2BlC;AAEF,SAAS,gBAAgB,CACvB,GAA4C,EAC5C,YAAsB;IAEtB,MAAM,MAAM,qBAAQ,GAAG,CAAE,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE;QAC9B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;KACpB;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Plugin } from 'postgraphile';
|
|
2
|
+
interface OperationsEnumGeneratorOptions {
|
|
3
|
+
/** Target root directory where the source files will be written. */
|
|
4
|
+
outRoot: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* PostGraphile plugin factory that will create a plugin for generating operation (queries and mutations) enums for the EnforceStrictPermissionsPlugin.
|
|
8
|
+
* - Make sure to register this after all schema modifying plugins and before EnforceStrictPermissionsPlugin.
|
|
9
|
+
* - This plugin does not modify the schema.
|
|
10
|
+
* - Enums will be generated under `src/generated/security/operations`.
|
|
11
|
+
* @param options - Plugin configuration options.
|
|
12
|
+
*/
|
|
13
|
+
export declare function OperationsEnumGeneratorPluginFactory(options?: OperationsEnumGeneratorOptions): Plugin;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=operations-enum-generator-plugin-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations-enum-generator-plugin-factory.d.ts","sourceRoot":"","sources":["../../src/plugins/operations-enum-generator-plugin-factory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,UAAU,8BAA8B;IACtC,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;CACjB;AAID;;;;;;GAMG;AACH,wBAAgB,oCAAoC,CAClD,OAAO,GAAE,8BAER,GACA,MAAM,CAuER"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.OperationsEnumGeneratorPluginFactory = void 0;
|
|
7
|
+
const endent_1 = __importDefault(require("endent"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
// TODO: Generate *all* operations, even those that are omitted with smart tags. We need them to allow subqueries.
|
|
11
|
+
// TODO: Consider adding functionality to group operations also by tables, not only queries/mutations.
|
|
12
|
+
/**
|
|
13
|
+
* PostGraphile plugin factory that will create a plugin for generating operation (queries and mutations) enums for the EnforceStrictPermissionsPlugin.
|
|
14
|
+
* - Make sure to register this after all schema modifying plugins and before EnforceStrictPermissionsPlugin.
|
|
15
|
+
* - This plugin does not modify the schema.
|
|
16
|
+
* - Enums will be generated under `src/generated/security/operations`.
|
|
17
|
+
* @param options - Plugin configuration options.
|
|
18
|
+
*/
|
|
19
|
+
function OperationsEnumGeneratorPluginFactory(options = {
|
|
20
|
+
outRoot: './src/generated/security/operations',
|
|
21
|
+
}) {
|
|
22
|
+
return (builder, _options) => {
|
|
23
|
+
const operations = {
|
|
24
|
+
Queries: new Set(),
|
|
25
|
+
Mutations: new Set(),
|
|
26
|
+
Relations: new Set(),
|
|
27
|
+
Subscriptions: new Set(),
|
|
28
|
+
};
|
|
29
|
+
//Enumerates all relations/subqueries
|
|
30
|
+
builder.hook('GraphQLObjectType:fields:field', (field, _build, { scope }) => {
|
|
31
|
+
if (scope.fieldName !== 'query' &&
|
|
32
|
+
(scope.isPgForwardRelationField || scope.isPgBackwardRelationField)) {
|
|
33
|
+
operations.Relations.add(scope.fieldName);
|
|
34
|
+
}
|
|
35
|
+
return field;
|
|
36
|
+
});
|
|
37
|
+
// Enumerate all queries, mutations and subscriptions
|
|
38
|
+
builder.hook('GraphQLObjectType:fields', (fields, _build, context) => {
|
|
39
|
+
if (context.Self.name === 'Query') {
|
|
40
|
+
Object.keys(fields).forEach((q) => {
|
|
41
|
+
if (q !== 'query') {
|
|
42
|
+
operations.Queries.add(q);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (context.Self.name === 'Mutation') {
|
|
47
|
+
Object.keys(fields).forEach((m) => operations.Mutations.add(m));
|
|
48
|
+
}
|
|
49
|
+
if (context.Self.name === 'Subscription') {
|
|
50
|
+
Object.keys(fields).forEach((s) => operations.Subscriptions.add(s));
|
|
51
|
+
}
|
|
52
|
+
return fields;
|
|
53
|
+
});
|
|
54
|
+
// Write enums to file when the schema is built.
|
|
55
|
+
builder.hook('finalize', (schema, _build, _context) => {
|
|
56
|
+
const operationsToEnum = [];
|
|
57
|
+
for (const [key, value] of Object.entries(operations)) {
|
|
58
|
+
const outputEnumPath = path_1.default.join(options.outRoot, `${key.toLowerCase()}.ts`);
|
|
59
|
+
// Exit early if expected operations are not there and assume there was an error during GQL schema generation.
|
|
60
|
+
// Do not write any files, keep whatever was already on the disk.
|
|
61
|
+
if (value.size === 0) {
|
|
62
|
+
if (fs_1.default.existsSync(outputEnumPath)) {
|
|
63
|
+
operationsToEnum.push(key);
|
|
64
|
+
}
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
writeSourceFile(outputEnumPath, generateEnum(key, [...value]));
|
|
68
|
+
operationsToEnum.push(key);
|
|
69
|
+
}
|
|
70
|
+
writeSourceFile(path_1.default.join(options.outRoot, 'index.ts'), generateIndex(operationsToEnum.map((o) => o.toLowerCase())));
|
|
71
|
+
return schema;
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
exports.OperationsEnumGeneratorPluginFactory = OperationsEnumGeneratorPluginFactory;
|
|
76
|
+
/**
|
|
77
|
+
* Writes generated source code to file but compares with the content of the existing file first to avoid triggering compilation in watch mode.
|
|
78
|
+
* @param outPath - Path where to write the source file.
|
|
79
|
+
* @param contents - Contents of the source file.
|
|
80
|
+
*/
|
|
81
|
+
function writeSourceFile(outPath, contents) {
|
|
82
|
+
if (!fs_1.default.existsSync(path_1.default.dirname(outPath))) {
|
|
83
|
+
fs_1.default.mkdirSync(path_1.default.dirname(outPath), { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
// Don't write file if the contents are the same, avoid triggering a build in watch mode.
|
|
86
|
+
if (fs_1.default.existsSync(outPath)) {
|
|
87
|
+
const currentContents = fs_1.default.readFileSync(outPath, { encoding: 'utf-8' });
|
|
88
|
+
if (currentContents.toString() === contents) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
fs_1.default.writeFileSync(outPath, contents, 'utf-8');
|
|
93
|
+
}
|
|
94
|
+
function generateEnum(name, members) {
|
|
95
|
+
return (0, endent_1.default) `export enum ${name} {
|
|
96
|
+
${members
|
|
97
|
+
.sort()
|
|
98
|
+
.map((m) => `${m} = '${m}'`)
|
|
99
|
+
.join(',\n')}
|
|
100
|
+
}`;
|
|
101
|
+
}
|
|
102
|
+
function generateIndex(modules) {
|
|
103
|
+
return modules
|
|
104
|
+
.sort()
|
|
105
|
+
.map((m) => `export * from './${m}';`)
|
|
106
|
+
.join('\n');
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=operations-enum-generator-plugin-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations-enum-generator-plugin-factory.js","sourceRoot":"","sources":["../../src/plugins/operations-enum-generator-plugin-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Plugin } from 'postgraphile';
|
|
2
|
+
/**
|
|
3
|
+
* Factory function to create a makeExtendSchemaPlugin that adds a subscription endpoint for specific entity.
|
|
4
|
+
* @param mainTableName name of the table in the database without schema
|
|
5
|
+
* @param typeName name of the GraphQL type that is generated by postgraphile for `mainTableName` table
|
|
6
|
+
* @param gqlIdDataType optional parameter to set an ID type for the endpoint. Supported types are `Int` and `UUID`. Default is `Int`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SubscriptionsPluginFactory: (mainTableName: string, typeName: string, gqlIdDataType?: 'Int' | 'UUID') => Plugin;
|
|
9
|
+
//# sourceMappingURL=subscriptions-plugin-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscriptions-plugin-factory.d.ts","sourceRoot":"","sources":["../../src/plugins/subscriptions-plugin-factory.ts"],"names":[],"mappings":"AAUA,OAAO,EAAS,MAAM,EAAE,MAAM,cAAc,CAAC;AAyD7C;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,kBACtB,MAAM,YACX,MAAM,kBACD,KAAK,GAAG,MAAM,KAC5B,MAoCC,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SubscriptionsPluginFactory = void 0;
|
|
7
|
+
const graphile_utils_1 = require("graphile-utils");
|
|
8
|
+
const inflection_1 = __importDefault(require("inflection"));
|
|
9
|
+
/*
|
|
10
|
+
* This function handles the boilerplate of fetching a record from the database
|
|
11
|
+
* which has the 'id' equal to the 'subject' from the PG NOTIFY event payload
|
|
12
|
+
* (see `tg__graphql_subscription()` trigger function in the database).
|
|
13
|
+
*/
|
|
14
|
+
function recordByIdFromTable(build, sqlTable) {
|
|
15
|
+
const { pgSql: sql } = build;
|
|
16
|
+
return async (event, _args, _context,
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/typedef
|
|
18
|
+
{ graphile: { selectGraphQLResultFromTable } }) => {
|
|
19
|
+
const rows = await selectGraphQLResultFromTable(sqlTable, (tableAlias, sqlBuilder) => {
|
|
20
|
+
sqlBuilder.where(sql.fragment `${tableAlias}.id = ${sql.value(event.subject)}`);
|
|
21
|
+
});
|
|
22
|
+
return rows[0];
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function getId() {
|
|
26
|
+
return async (event) => event.subject;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Factory function to create a makeExtendSchemaPlugin that adds a subscription endpoint for specific entity.
|
|
30
|
+
* @param mainTableName name of the table in the database without schema
|
|
31
|
+
* @param typeName name of the GraphQL type that is generated by postgraphile for `mainTableName` table
|
|
32
|
+
* @param gqlIdDataType optional parameter to set an ID type for the endpoint. Supported types are `Int` and `UUID`. Default is `Int`.
|
|
33
|
+
*/
|
|
34
|
+
const SubscriptionsPluginFactory = (mainTableName, typeName, gqlIdDataType = 'Int') => (0, graphile_utils_1.makeExtendSchemaPlugin)((build) => {
|
|
35
|
+
const { pgSql: sql } = build;
|
|
36
|
+
const variableName = inflection_1.default.camelize(typeName, true);
|
|
37
|
+
const payloadName = inflection_1.default.camelize(typeName, false) + 'SubscriptionPayload';
|
|
38
|
+
const topicName = 'graphql:' + mainTableName;
|
|
39
|
+
return {
|
|
40
|
+
typeDefs: (0, graphile_utils_1.gql) `
|
|
41
|
+
type ${payloadName} {
|
|
42
|
+
id: ${gqlIdDataType}! # Populated by our resolver below
|
|
43
|
+
${variableName}: ${typeName} # Populated by our resolver below
|
|
44
|
+
event: String # Part of the NOTIFY payload
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
extend type Subscription {
|
|
48
|
+
"""
|
|
49
|
+
Triggered when a ${typeName} is mutated (insert, update or delete).
|
|
50
|
+
"""
|
|
51
|
+
${variableName}Mutated: ${payloadName}
|
|
52
|
+
@pgSubscription(topic: "${topicName}")
|
|
53
|
+
}
|
|
54
|
+
`,
|
|
55
|
+
resolvers: {
|
|
56
|
+
[payloadName]: {
|
|
57
|
+
id: getId(),
|
|
58
|
+
[variableName]: recordByIdFromTable(build, sql.fragment([`app_public.${mainTableName}`])),
|
|
59
|
+
},
|
|
60
|
+
Subscription: {
|
|
61
|
+
[`${variableName}Mutated`]: (event) => event,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
exports.SubscriptionsPluginFactory = SubscriptionsPluginFactory;
|
|
67
|
+
//# sourceMappingURL=subscriptions-plugin-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscriptions-plugin-factory.js","sourceRoot":"","sources":["../../src/plugins/subscriptions-plugin-factory.ts"],"names":[],"mappings":";;;;;;AAEA,mDAIwB;AAGxB,4DAAoC;AAsBpC;;;;GAIG;AACH,SAAS,mBAAmB,CAC1B,KAAY,EACZ,QAAa;IAEb,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAC7B,OAAO,KAAK,EACV,KAAoC,EACpC,KAA8B,EAC9B,QAAa;IACb,sDAAsD;IACtD,EAAE,QAAQ,EAAE,EAAE,4BAA4B,EAAE,EAAE,EAC9C,EAAE;QACF,MAAM,IAAI,GAAG,MAAM,4BAA4B,CAC7C,QAAQ,EACR,CAAC,UAAe,EAAE,UAAwB,EAAE,EAAE;YAC5C,UAAU,CAAC,KAAK,CACd,GAAG,CAAC,QAAQ,CAAA,GAAG,UAAU,SAAS,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAC7D,CAAC;QACJ,CAAC,CACF,CAAC;QACF,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,KAAK;IAIZ,OAAO,KAAK,EAAE,KAAoC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;AACvE,CAAC;AAED;;;;;GAKG;AACI,MAAM,0BAA0B,GAAG,CACxC,aAAqB,EACrB,QAAgB,EAChB,gBAAgC,KAAK,EAC7B,EAAE,CACV,IAAA,uCAAsB,EAAC,CAAC,KAAY,EAAE,EAAE;IACtC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAC7B,MAAM,YAAY,GAAG,oBAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACzD,MAAM,WAAW,GACf,oBAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,qBAAqB,CAAC;IAC/D,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,CAAC;IAC7C,OAAO;QACL,QAAQ,EAAE,IAAA,oBAAG,EAAA;aACN,WAAW;cACV,aAAa;UACjB,YAAY,KAAK,QAAQ;;;;;;2BAMR,QAAQ;;UAEzB,YAAY,YAAY,WAAW;oCACT,SAAS;;KAExC;QACC,SAAS,EAAE;YACT,CAAC,WAAW,CAAC,EAAE;gBACb,EAAE,EAAE,KAAK,EAAE;gBACX,CAAC,YAAY,CAAC,EAAE,mBAAmB,CACjC,KAAK,EACL,GAAG,CAAC,QAAQ,CAAC,CAAC,cAAc,aAAa,EAAE,CAAC,CAAC,CAC9C;aACF;YACD,YAAY,EAAE;gBACZ,CAAC,GAAG,YAAY,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;aAC7C;SACF;KACqB,CAAC;AAC3B,CAAC,CAAC,CAAC;AAxCQ,QAAA,0BAA0B,8BAwClC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-directives-plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/validation-directives-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAiB,MAAM,gBAAgB,CAAC;AA2ElE;;GAEG;AACH,eAAO,MAAM,0BAA0B,EAAE,MA8DxC,CAAC"}
|