@smartive/graphql-magic 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/.eslintrc +21 -0
  2. package/.github/workflows/release.yml +24 -0
  3. package/.github/workflows/testing.yml +37 -0
  4. package/.nvmrc +1 -0
  5. package/.prettierignore +34 -0
  6. package/.prettierrc.json +1 -0
  7. package/.releaserc +27 -0
  8. package/CHANGELOG.md +6 -0
  9. package/README.md +15 -0
  10. package/dist/cjs/index.cjs +2646 -0
  11. package/dist/esm/client/gql.d.ts +1 -0
  12. package/dist/esm/client/gql.js +5 -0
  13. package/dist/esm/client/gql.js.map +1 -0
  14. package/dist/esm/client/index.d.ts +2 -0
  15. package/dist/esm/client/index.js +4 -0
  16. package/dist/esm/client/index.js.map +1 -0
  17. package/dist/esm/client/queries.d.ts +24 -0
  18. package/dist/esm/client/queries.js +152 -0
  19. package/dist/esm/client/queries.js.map +1 -0
  20. package/dist/esm/context.d.ts +30 -0
  21. package/dist/esm/context.js +2 -0
  22. package/dist/esm/context.js.map +1 -0
  23. package/dist/esm/errors.d.ts +17 -0
  24. package/dist/esm/errors.js +27 -0
  25. package/dist/esm/errors.js.map +1 -0
  26. package/dist/esm/generate/generate.d.ts +7 -0
  27. package/dist/esm/generate/generate.js +211 -0
  28. package/dist/esm/generate/generate.js.map +1 -0
  29. package/dist/esm/generate/index.d.ts +3 -0
  30. package/dist/esm/generate/index.js +5 -0
  31. package/dist/esm/generate/index.js.map +1 -0
  32. package/dist/esm/generate/mutations.d.ts +2 -0
  33. package/dist/esm/generate/mutations.js +18 -0
  34. package/dist/esm/generate/mutations.js.map +1 -0
  35. package/dist/esm/generate/utils.d.ts +22 -0
  36. package/dist/esm/generate/utils.js +150 -0
  37. package/dist/esm/generate/utils.js.map +1 -0
  38. package/dist/esm/index.d.ts +10 -0
  39. package/dist/esm/index.js +12 -0
  40. package/dist/esm/index.js.map +1 -0
  41. package/dist/esm/migrations/generate.d.ts +28 -0
  42. package/dist/esm/migrations/generate.js +516 -0
  43. package/dist/esm/migrations/generate.js.map +1 -0
  44. package/dist/esm/migrations/index.d.ts +1 -0
  45. package/dist/esm/migrations/index.js +3 -0
  46. package/dist/esm/migrations/index.js.map +1 -0
  47. package/dist/esm/models.d.ts +170 -0
  48. package/dist/esm/models.js +27 -0
  49. package/dist/esm/models.js.map +1 -0
  50. package/dist/esm/permissions/check.d.ts +15 -0
  51. package/dist/esm/permissions/check.js +162 -0
  52. package/dist/esm/permissions/check.js.map +1 -0
  53. package/dist/esm/permissions/generate.d.ts +45 -0
  54. package/dist/esm/permissions/generate.js +77 -0
  55. package/dist/esm/permissions/generate.js.map +1 -0
  56. package/dist/esm/permissions/index.d.ts +2 -0
  57. package/dist/esm/permissions/index.js +4 -0
  58. package/dist/esm/permissions/index.js.map +1 -0
  59. package/dist/esm/resolvers/arguments.d.ts +26 -0
  60. package/dist/esm/resolvers/arguments.js +88 -0
  61. package/dist/esm/resolvers/arguments.js.map +1 -0
  62. package/dist/esm/resolvers/filters.d.ts +5 -0
  63. package/dist/esm/resolvers/filters.js +126 -0
  64. package/dist/esm/resolvers/filters.js.map +1 -0
  65. package/dist/esm/resolvers/index.d.ts +7 -0
  66. package/dist/esm/resolvers/index.js +9 -0
  67. package/dist/esm/resolvers/index.js.map +1 -0
  68. package/dist/esm/resolvers/mutations.d.ts +3 -0
  69. package/dist/esm/resolvers/mutations.js +255 -0
  70. package/dist/esm/resolvers/mutations.js.map +1 -0
  71. package/dist/esm/resolvers/node.d.ts +44 -0
  72. package/dist/esm/resolvers/node.js +102 -0
  73. package/dist/esm/resolvers/node.js.map +1 -0
  74. package/dist/esm/resolvers/resolver.d.ts +5 -0
  75. package/dist/esm/resolvers/resolver.js +143 -0
  76. package/dist/esm/resolvers/resolver.js.map +1 -0
  77. package/dist/esm/resolvers/resolvers.d.ts +9 -0
  78. package/dist/esm/resolvers/resolvers.js +39 -0
  79. package/dist/esm/resolvers/resolvers.js.map +1 -0
  80. package/dist/esm/resolvers/utils.d.ts +43 -0
  81. package/dist/esm/resolvers/utils.js +125 -0
  82. package/dist/esm/resolvers/utils.js.map +1 -0
  83. package/dist/esm/utils.d.ts +25 -0
  84. package/dist/esm/utils.js +159 -0
  85. package/dist/esm/utils.js.map +1 -0
  86. package/dist/esm/values.d.ts +15 -0
  87. package/dist/esm/values.js +7 -0
  88. package/dist/esm/values.js.map +1 -0
  89. package/jest.config.ts +12 -0
  90. package/package.json +66 -0
  91. package/renovate.json +32 -0
  92. package/src/client/gql.ts +7 -0
  93. package/src/client/index.ts +4 -0
  94. package/src/client/queries.ts +251 -0
  95. package/src/context.ts +27 -0
  96. package/src/errors.ts +32 -0
  97. package/src/generate/generate.ts +273 -0
  98. package/src/generate/index.ts +5 -0
  99. package/src/generate/mutations.ts +35 -0
  100. package/src/generate/utils.ts +223 -0
  101. package/src/index.ts +12 -0
  102. package/src/migrations/generate.ts +633 -0
  103. package/src/migrations/index.ts +3 -0
  104. package/src/models.ts +228 -0
  105. package/src/permissions/check.ts +239 -0
  106. package/src/permissions/generate.ts +143 -0
  107. package/src/permissions/index.ts +4 -0
  108. package/src/resolvers/arguments.ts +129 -0
  109. package/src/resolvers/filters.ts +163 -0
  110. package/src/resolvers/index.ts +9 -0
  111. package/src/resolvers/mutations.ts +313 -0
  112. package/src/resolvers/node.ts +193 -0
  113. package/src/resolvers/resolver.ts +223 -0
  114. package/src/resolvers/resolvers.ts +40 -0
  115. package/src/resolvers/utils.ts +188 -0
  116. package/src/utils.ts +186 -0
  117. package/src/values.ts +19 -0
  118. package/tests/unit/__snapshots__/generate.spec.ts.snap +105 -0
  119. package/tests/unit/__snapshots__/resolve.spec.ts.snap +60 -0
  120. package/tests/unit/generate.spec.ts +8 -0
  121. package/tests/unit/resolve.spec.ts +128 -0
  122. package/tests/unit/utils.ts +82 -0
  123. package/tsconfig.jest.json +13 -0
  124. package/tsconfig.json +13 -0
package/src/utils.ts ADDED
@@ -0,0 +1,186 @@
1
+ import assert from 'assert';
2
+ import { pluralize } from 'inflection';
3
+ import camelCase from 'lodash/camelCase';
4
+ import lodashGet from 'lodash/get';
5
+ import kebabCase from 'lodash/kebabCase';
6
+ import startCase from 'lodash/startCase';
7
+ import { Model, Models, ObjectModel, RawModels, Relation, ReverseRelation, isObjectModel } from './models';
8
+
9
+ const isNotFalsy = <T>(v: T | null | undefined | false): v is T => typeof v !== 'undefined' && v !== null && v !== false;
10
+
11
+ export const merge = <T>(objects: ({ [name: string]: T } | undefined | false)[] | undefined): { [name: string]: T } =>
12
+ (objects || []).filter(isNotFalsy).reduce((i, acc) => ({ ...acc, ...i }), {});
13
+
14
+ // Target -> target
15
+ export const typeToField = (type: string) => type.substr(0, 1).toLowerCase() + type.substr(1);
16
+
17
+ export const getModelPlural = (model: ObjectModel | Model) => model.plural || pluralize(model.name);
18
+
19
+ export const getModelPluralField = (model: Model) => typeToField(getModelPlural(model));
20
+
21
+ export const getModelSlug = (model: Model) => kebabCase(getModelPlural(model));
22
+
23
+ export const getModelLabelPlural = (model: Model) => getLabel(getModelPlural(model));
24
+
25
+ export const getModelLabel = (model: Model) => getLabel(model.name);
26
+
27
+ export const getLabel = (s: string) => startCase(camelCase(s));
28
+
29
+ export const getModels = (rawModels: RawModels): Models => {
30
+ const models: Models = rawModels.filter(isObjectModel).map((model) => {
31
+ const objectModel: Model = {
32
+ ...model,
33
+ fieldsByName: {},
34
+ relations: [],
35
+ relationsByName: {},
36
+ reverseRelations: [],
37
+ reverseRelationsByName: {},
38
+ fields: [
39
+ { name: 'id', type: 'ID', nonNull: true, unique: true, primary: true, generated: true },
40
+ ...model.fields,
41
+ ...(model.creatable
42
+ ? [
43
+ { name: 'createdAt', type: 'DateTime', nonNull: !model.nonStrict, orderable: true, generated: true },
44
+ {
45
+ name: 'createdBy',
46
+ type: 'User',
47
+ relation: true,
48
+ nonNull: !model.nonStrict,
49
+ reverse: `created${getModelPlural(model)}`,
50
+ generated: true,
51
+ },
52
+ ]
53
+ : []),
54
+ ...(model.updatable
55
+ ? [
56
+ { name: 'updatedAt', type: 'DateTime', nonNull: !model.nonStrict, orderable: true, generated: true },
57
+ {
58
+ name: 'updatedBy',
59
+ type: 'User',
60
+ relation: true,
61
+ nonNull: !model.nonStrict,
62
+ reverse: `updated${getModelPlural(model)}`,
63
+ generated: true,
64
+ },
65
+ ]
66
+ : []),
67
+ ...(model.deletable
68
+ ? [
69
+ {
70
+ name: 'deleted',
71
+ type: 'Boolean',
72
+ nonNull: true,
73
+ default: false,
74
+ filterable: true,
75
+ defaultFilter: false,
76
+ generated: true,
77
+ },
78
+ { name: 'deletedAt', type: 'DateTime', orderable: true, generated: true },
79
+ {
80
+ name: 'deletedBy',
81
+ type: 'User',
82
+ relation: true,
83
+ reverse: `deleted${getModelPlural(model)}`,
84
+ generated: true,
85
+ },
86
+ ]
87
+ : []),
88
+ ].map(({ foreignKey, ...field }) => ({
89
+ ...field,
90
+ ...(field.relation && {
91
+ foreignKey: foreignKey || `${field.name}Id`,
92
+ }),
93
+ })),
94
+ };
95
+
96
+ for (const field of objectModel.fields) {
97
+ objectModel.fieldsByName[field.name] = field;
98
+ }
99
+
100
+ return objectModel;
101
+ });
102
+
103
+ for (const model of models) {
104
+ for (const field of model.fields.filter(({ relation }) => relation)) {
105
+ const fieldModel = summonByName(models, field.type);
106
+
107
+ const reverseRelation: ReverseRelation = {
108
+ name: field.reverse || (field.toOne ? typeToField(model.name) : getModelPluralField(model)),
109
+ foreignKey: get(field, 'foreignKey'),
110
+ type: model.name,
111
+ toOne: !!field.toOne,
112
+ fieldModel,
113
+ field,
114
+ model,
115
+ };
116
+
117
+ const relation: Relation = {
118
+ field,
119
+ model: fieldModel,
120
+ reverseRelation,
121
+ };
122
+ model.relations.push(relation);
123
+ model.relationsByName[relation.field.name] = relation;
124
+
125
+ fieldModel.reverseRelations.push(reverseRelation);
126
+
127
+ fieldModel.reverseRelationsByName[reverseRelation.name] = reverseRelation;
128
+ }
129
+ }
130
+
131
+ return models;
132
+ };
133
+
134
+ export const summonByName = <T extends { name: string }>(array: T[], value: string) => summonByKey(array, 'name', value);
135
+
136
+ export const summonByKey = <T>(array: readonly T[] | undefined, key: string, value: unknown) =>
137
+ summon(array, (element: T) => lodashGet(element, key) === value, `No element found with ${key} ${value}`);
138
+
139
+ export const summon = <T>(array: readonly T[] | undefined, cb: Parameters<T[]['find']>[1], errorMessage?: string) => {
140
+ if (array === undefined) {
141
+ throw new Error('Base array is not defined.');
142
+ }
143
+ const result = array.find(cb);
144
+ if (result === undefined) {
145
+ console.trace();
146
+ throw new Error(errorMessage || 'Element not found.');
147
+ }
148
+ return result;
149
+ };
150
+
151
+ type ForSure<T> = T extends undefined | null ? never : T;
152
+
153
+ export const it = <T>(object: T | null | undefined): ForSure<T> => {
154
+ if (object === undefined || object === null) {
155
+ console.trace();
156
+ throw new Error('Base object is not defined.');
157
+ }
158
+
159
+ return object as ForSure<T>;
160
+ };
161
+
162
+ export const get = <T, U extends keyof ForSure<T>>(object: T | null | undefined, key: U): ForSure<ForSure<T>[U]> => {
163
+ const value = it(object)[key];
164
+ if (value === undefined || value === null) {
165
+ console.trace();
166
+ throw new Error(`Object doesn't have ${String(key)}`);
167
+ }
168
+ return value as ForSure<ForSure<T>[U]>;
169
+ };
170
+
171
+ export const getString = (v: unknown) => {
172
+ assert(typeof v === 'string');
173
+ return v;
174
+ };
175
+
176
+ export const retry = async <T>(cb: () => Promise<T>, condition: (e: any) => boolean) => {
177
+ try {
178
+ return await cb();
179
+ } catch (e) {
180
+ if (condition(e)) {
181
+ return await cb();
182
+ } else {
183
+ throw e;
184
+ }
185
+ }
186
+ };
package/src/values.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { DateTime } from 'luxon';
2
+
3
+ export class Enum {
4
+ constructor(public value: string) {}
5
+ }
6
+
7
+ export type BasicValue = undefined | null | boolean | string | number | DateTime;
8
+
9
+ export type Value = any; // BasicValue | Enum | Enum[] | Record<string, Value> | Value[];
10
+
11
+ export type Values = {
12
+ name: string;
13
+ values: Value;
14
+ }[];
15
+
16
+ export type Directive = {
17
+ name: string;
18
+ values?: Values | undefined;
19
+ };
@@ -0,0 +1,105 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`generate generates a schema 1`] = `
4
+ "type AnotherObject {
5
+ id: ID!
6
+ manyObjects(where: SomeObjectWhere, search: String, orderBy: [SomeObjectOrderBy!], limit: Int, offset: Int): [SomeObject!]!
7
+ }
8
+
9
+ input AnotherObjectWhere {
10
+ id: [ID!]
11
+ }
12
+
13
+ input AnotherObjectWhereUnique {
14
+ id: ID
15
+ }
16
+
17
+ input CreateSomeObject {
18
+ xyz: Int!
19
+ }
20
+
21
+ scalar DateTime
22
+
23
+ type Mutation {
24
+ createSomeObject(data: CreateSomeObject!): SomeObject!
25
+ updateSomeObject(where: SomeObjectWhereUnique!, data: UpdateSomeObject!): SomeObject!
26
+ deleteSomeObject(where: SomeObjectWhereUnique!, dryRun: Boolean): ID!
27
+ restoreSomeObject(where: SomeObjectWhereUnique!): ID!
28
+ }
29
+
30
+ enum Order {
31
+ ASC
32
+ DESC
33
+ }
34
+
35
+ type Query {
36
+ me: User
37
+ someObject(where: SomeObjectWhereUnique!): SomeObject!
38
+ manyObjects(where: SomeObjectWhere, search: String, orderBy: [SomeObjectOrderBy!], limit: Int, offset: Int): [SomeObject!]!
39
+ }
40
+
41
+ enum SomeEnum {
42
+ A
43
+ B
44
+ C
45
+ }
46
+
47
+ type SomeObject {
48
+ id: ID!
49
+ field: String
50
+ another: AnotherObject!
51
+ list(magic: Boolean): [Float!]!
52
+ xyz: Int!
53
+ createdAt: DateTime!
54
+ createdBy: User!
55
+ updatedAt: DateTime!
56
+ updatedBy: User!
57
+ deleted: Boolean!
58
+ deletedAt: DateTime
59
+ deletedBy: User
60
+ }
61
+
62
+ input SomeObjectOrderBy {
63
+ xyz: Order
64
+ createdAt: Order
65
+ updatedAt: Order
66
+ deletedAt: Order
67
+ }
68
+
69
+ input SomeObjectWhere {
70
+ id: [ID!]
71
+ deleted: [Boolean!] = false
72
+ another: AnotherObjectWhere
73
+ }
74
+
75
+ input SomeObjectWhereUnique {
76
+ id: ID
77
+ }
78
+
79
+ type SomeRawObject {
80
+ field: String
81
+ }
82
+
83
+ input UpdateSomeObject {
84
+ xyz: Int
85
+ }
86
+
87
+ scalar Upload
88
+
89
+ type User {
90
+ id: ID!
91
+ username: String
92
+ createdManyObjects(where: SomeObjectWhere, search: String, orderBy: [SomeObjectOrderBy!], limit: Int, offset: Int): [SomeObject!]!
93
+ updatedManyObjects(where: SomeObjectWhere, search: String, orderBy: [SomeObjectOrderBy!], limit: Int, offset: Int): [SomeObject!]!
94
+ deletedManyObjects(where: SomeObjectWhere, search: String, orderBy: [SomeObjectOrderBy!], limit: Int, offset: Int): [SomeObject!]!
95
+ }
96
+
97
+ input UserWhere {
98
+ id: [ID!]
99
+ }
100
+
101
+ input UserWhereUnique {
102
+ id: ID
103
+ }
104
+ "
105
+ `;
@@ -0,0 +1,60 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`resolvers are generated correctly 1`] = `
4
+ {
5
+ "Mutation": {
6
+ "createSomeObject": [Function],
7
+ "deleteSomeObject": [Function],
8
+ "restoreSomeObject": [Function],
9
+ "updateSomeObject": [Function],
10
+ },
11
+ "Query": {
12
+ "manyObjects": [Function],
13
+ "me": [Function],
14
+ "someObject": [Function],
15
+ },
16
+ }
17
+ `;
18
+
19
+ exports[`resolvers resolve lists, many-to-one and one-to-many queries 1`] = `
20
+ {
21
+ "data": {
22
+ "manyObjects": [
23
+ {
24
+ "another": {
25
+ "id": "bar",
26
+ "manyObjects": [
27
+ {
28
+ "field": "foo",
29
+ "id": "foo",
30
+ },
31
+ ],
32
+ },
33
+ "field": "foo",
34
+ "id": "foo",
35
+ },
36
+ ],
37
+ },
38
+ }
39
+ `;
40
+
41
+ exports[`resolvers resolve lists, many-to-one and one-to-many queries: query 1`] = `"select * from "User" where "id" = $1 limit $2"`;
42
+
43
+ exports[`resolvers resolve lists, many-to-one and one-to-many queries: query 2`] = `"select "SO"."id" as "SO__ID", "SO"."id" as "SO__id", "SO"."field" as "SO__field", "SO__a"."id" as "SO__a__ID", "SO__a"."id" as "SO__a__id" from "SomeObject" as "SO" left join "AnotherObject" as "SO__W__a" on "SO"."anotherId" = "SO__W__a"."id" left join "AnotherObject" as "SO__a" on "SO"."anotherId" = "SO__a"."id" where "SO__W__a"."id" in ($1) and "SO"."deleted" = $2 order by "SO"."xyz" DESC"`;
44
+
45
+ exports[`resolvers resolve lists, many-to-one and one-to-many queries: query 3`] = `"select "SO__a__mO"."id" as "SO__a__mO__ID", "SO__a__mO"."id" as "SO__a__mO__id", "SO__a__mO"."field" as "SO__a__mO__field", "SO__a__mO"."anotherId" as "SO__a__mO__anotherId" from "SomeObject" as "SO__a__mO" where "SO__a__mO"."id" in ($1) and "SO__a__mO"."deleted" = $2 and "SO__a__mO"."anotherId" = $3 order by "SO__a__mO"."createdAt" DESC"`;
46
+
47
+ exports[`resolvers resolve single query 1`] = `
48
+ {
49
+ "data": {
50
+ "someObject": {
51
+ "field": "foo",
52
+ "id": "foo",
53
+ },
54
+ },
55
+ }
56
+ `;
57
+
58
+ exports[`resolvers resolve single query: query 1`] = `"select * from "User" where "id" = $1 limit $2"`;
59
+
60
+ exports[`resolvers resolve single query: query 2`] = `"select "SO"."id" as "SO__ID", "SO"."id" as "SO__id", "SO"."field" as "SO__field" from "SomeObject" as "SO" where "SO"."id" = $1 and "SO"."deleted" = $2 order by "SO"."createdAt" DESC limit $3"`;
@@ -0,0 +1,8 @@
1
+ import { printSchemaFromModels } from '../../src/generate';
2
+ import { rawModels } from './utils';
3
+
4
+ describe('generate', () => {
5
+ it('generates a schema', () => {
6
+ expect(printSchemaFromModels(rawModels)).toMatchSnapshot();
7
+ });
8
+ });
@@ -0,0 +1,128 @@
1
+ import { makeExecutableSchema } from '@graphql-tools/schema';
2
+ import { execute, parse, Source } from 'graphql';
3
+ import knex from 'knex';
4
+ import { gql } from '../../src/client/gql';
5
+ import { Context } from '../../src/context';
6
+ import { generate } from '../../src/generate';
7
+ import { getResolvers } from '../../src/resolvers';
8
+ import { models, permissions, rawModels } from './utils';
9
+ import { DateTime } from 'luxon';
10
+
11
+ const test = async (operationName: string, query: string, variableValues: object, responses: unknown[]) => {
12
+ const knexInstance = knex({
13
+ client: 'postgresql',
14
+ });
15
+
16
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
17
+ const mockKnex = require('mock-knex');
18
+ mockKnex.mock(knexInstance);
19
+ const tracker = mockKnex.getTracker();
20
+
21
+ tracker.install();
22
+ tracker.on('query', function someFunction(query, step) {
23
+ expect(query.sql).toMatchSnapshot('query');
24
+ query.response(responses[step - 1]);
25
+ });
26
+
27
+ const user = await knexInstance('User').where({ id: 1 }).first();
28
+ const typeDefs = generate(rawModels);
29
+ const contextValue: Context = {
30
+ req: null as any,
31
+ knex: knexInstance,
32
+ document: typeDefs,
33
+ locale: 'en',
34
+ locales: ['en'],
35
+ user,
36
+ rawModels,
37
+ models,
38
+ permissions,
39
+ now: DateTime.fromISO('2020-01-01T00:00:00.000Z'),
40
+ };
41
+ const result = await execute({
42
+ schema: makeExecutableSchema({
43
+ typeDefs,
44
+ resolvers: getResolvers(models),
45
+ }),
46
+ document: parse(new Source(query, 'GraphQL request')),
47
+ contextValue,
48
+ variableValues,
49
+ operationName,
50
+ });
51
+
52
+ expect(result).toMatchSnapshot();
53
+
54
+ tracker.uninstall();
55
+ };
56
+
57
+ describe('resolvers', () => {
58
+ it('are generated correctly', () => {
59
+ expect(getResolvers(models)).toMatchSnapshot();
60
+ });
61
+
62
+ it('resolve lists, many-to-one and one-to-many queries', async () => {
63
+ await test(
64
+ 'SomeQuery',
65
+ gql`
66
+ query SomeQuery {
67
+ manyObjects(where: { another: { id: "bar" } }, orderBy: [{ xyz: DESC }]) {
68
+ id
69
+ field
70
+ another {
71
+ id
72
+ manyObjects(where: { id: "foo" }) {
73
+ id
74
+ field
75
+ }
76
+ }
77
+ }
78
+ }
79
+ `,
80
+ {},
81
+ [
82
+ { id: 1, role: 'ADMIN' },
83
+ [
84
+ {
85
+ SO__ID: 'foo',
86
+ SO__id: 'foo',
87
+ SO__field: 'foo',
88
+ SO__a__ID: 'bar',
89
+ SO__a__id: 'bar',
90
+ },
91
+ ],
92
+ [
93
+ {
94
+ SO__a__mO__ID: 'foo',
95
+ SO__a__mO__id: 'foo',
96
+ SO__a__mO__field: 'foo',
97
+ SO__a__mO__anotherId: 'bar',
98
+ },
99
+ ],
100
+ ]
101
+ );
102
+ });
103
+
104
+ it('resolve single query', async () => {
105
+ await test(
106
+ 'SomeQuery',
107
+ gql`
108
+ query SomeQuery {
109
+ someObject(where: { id: "foo" }) {
110
+ id
111
+ field
112
+ }
113
+ }
114
+ `,
115
+ {},
116
+ [
117
+ { id: 1, role: 'ADMIN' },
118
+ [
119
+ {
120
+ SO__ID: 'foo',
121
+ SO__id: 'foo',
122
+ SO__field: 'foo',
123
+ },
124
+ ],
125
+ ]
126
+ );
127
+ });
128
+ });
@@ -0,0 +1,82 @@
1
+ import { RawModels } from '../../src/models';
2
+ import { generatePermissions, PermissionsConfig } from '../../src/permissions/generate';
3
+ import { getModels } from '../../src/utils';
4
+
5
+ export const rawModels: RawModels = [
6
+ {
7
+ name: 'SomeEnum',
8
+ type: 'enum',
9
+ values: ['A', 'B', 'C'],
10
+ },
11
+
12
+ {
13
+ name: 'SomeRawObject',
14
+ type: 'raw-object',
15
+ fields: [{ name: 'field', type: 'String' }],
16
+ },
17
+
18
+ {
19
+ type: 'object',
20
+ name: 'User',
21
+ fields: [
22
+ {
23
+ name: 'username',
24
+ type: 'String',
25
+ },
26
+ ],
27
+ },
28
+ {
29
+ type: 'object',
30
+ name: 'SomeObject',
31
+ plural: 'ManyObjects',
32
+ description: 'An object',
33
+ queriable: true,
34
+ listQueriable: true,
35
+ creatable: true,
36
+ updatable: true,
37
+ deletable: true,
38
+ fields: [
39
+ {
40
+ name: 'field',
41
+ searchable: true,
42
+ type: 'String',
43
+ },
44
+ {
45
+ name: 'another',
46
+ type: 'AnotherObject',
47
+ relation: true,
48
+ filterable: true,
49
+ nonNull: true,
50
+ },
51
+ {
52
+ name: 'list',
53
+ type: 'Float',
54
+ nonNull: true,
55
+ list: true,
56
+ args: [{ name: 'magic', type: 'Boolean' }],
57
+ },
58
+ {
59
+ name: 'xyz',
60
+ type: 'Int',
61
+ description: 'yay',
62
+ nonNull: true,
63
+ creatable: true,
64
+ updatable: true,
65
+ orderable: true,
66
+ },
67
+ ],
68
+ },
69
+ {
70
+ type: 'object',
71
+ name: 'AnotherObject',
72
+ fields: [],
73
+ },
74
+ ];
75
+
76
+ export const models = getModels(rawModels);
77
+
78
+ const permissionsConfig: PermissionsConfig = {
79
+ ADMIN: true,
80
+ };
81
+
82
+ export const permissions = generatePermissions(models, permissionsConfig);
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["**/*.ts", "**/*.tsx", "**/unit/**/*.spec.ts"],
4
+ "exclude": ["node_modules", "dist"],
5
+ "compilerOptions": {
6
+ "rootDir": "./",
7
+ "types": ["jest"],
8
+ "esModuleInterop": true,
9
+ "moduleResolution": "node",
10
+ "isolatedModules": true,
11
+ "allowJs": true
12
+ }
13
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "include": ["./src/**/*.ts", "./src/**/*.tsx"],
3
+ "exclude": ["node_modules", "dist"],
4
+ "compilerOptions": {
5
+ "outDir": "./dist/esm",
6
+ "rootDir": "./src",
7
+ "sourceMap": true,
8
+ "declaration": true,
9
+ "target": "esnext",
10
+ "moduleResolution": "bundler",
11
+ "allowSyntheticDefaultImports": true
12
+ }
13
+ }