@grantjs/schema 1.5.1 → 1.5.3

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 (29) hide show
  1. package/README.md +32 -15
  2. package/package.json +10 -4
  3. package/src/events/event-catalog.ts +12 -15
  4. package/src/generated/graphql.ts +0 -380
  5. package/src/generated/resolvers.ts +1197 -4996
  6. package/src/generated/schema-types.ts +0 -34
  7. package/src/index.ts +1 -24
  8. package/src/notifications/notification.types.ts +0 -4
  9. package/src/operations/role-permissions/role-permissions.graphql +0 -21
  10. package/src/operations/user-permissions/user-permissions.graphql +0 -21
  11. package/src/schema/base.graphql +0 -5
  12. package/src/sdl-contract.test.ts +90 -0
  13. package/src/test-support/sdl-fixture.ts +79 -0
  14. package/src/webhooks/webhook.types.ts +0 -8
  15. package/src/operations/organization-invitations/getOrganizationInvitations.graphql +0 -17
  16. package/src/schema/account-project-api-keys/inputs/remove-account-project-api-key.graphql +0 -5
  17. package/src/schema/accounts/types/account-searchable-field.graphql +0 -3
  18. package/src/schema/me/input/update-my-user-authentication-method.graphql +0 -7
  19. package/src/schema/organization-members/types/organization-member-searchable-field.graphql +0 -4
  20. package/src/schema/organization-project-api-keys/inputs/remove-organization-project-api-key.graphql +0 -5
  21. /package/src/schema/me/{input → inputs}/change-my-password.graphql +0 -0
  22. /package/src/schema/me/{input → inputs}/create-my-user-authentication-method.graphql +0 -0
  23. /package/src/schema/me/{input → inputs}/delete-my-accounts.graphql +0 -0
  24. /package/src/schema/me/{input → inputs}/my-user-sessions.graphql +0 -0
  25. /package/src/schema/me/{input → inputs}/notification.graphql +0 -0
  26. /package/src/schema/me/{input → inputs}/update-my-project-membership.graphql +0 -0
  27. /package/src/schema/me/{input → inputs}/update-my-user.graphql +0 -0
  28. /package/src/schema/me/{input → inputs}/upload-my-project-membership-picture.graphql +0 -0
  29. /package/src/schema/me/{input → inputs}/upload-my-user-picture.graphql +0 -0
package/README.md CHANGED
@@ -74,9 +74,23 @@ const resolvers: Resolvers = {
74
74
  pnpm generate
75
75
 
76
76
  # Watch for changes and regenerate
77
- pnpm generate:watch
77
+ pnpm dev
78
78
  ```
79
79
 
80
+ Generated output under `src/generated/` is committed and must stay in sync with its
81
+ sources. CI runs `pnpm codegen:check` (regenerate, fail on any diff), so edit the
82
+ `.graphql` files or `codegen.ts` — never `src/generated/` directly.
83
+
84
+ ### Test
85
+
86
+ ```bash
87
+ pnpm test
88
+ ```
89
+
90
+ Structural assertions on the merged SDL: it builds, every operation document
91
+ validates against it, and the count of types unreachable from `Query`/`Mutation`
92
+ is pinned. See `src/sdl-contract.test.ts`.
93
+
80
94
  ### Build Package
81
95
 
82
96
  ```bash
@@ -87,22 +101,25 @@ pnpm build
87
101
 
88
102
  ```
89
103
  src/
90
- ├── schema/ # GraphQL schema definitions
91
- │ ├── permissions/ # Permission-related types and operations
92
- │ ├── users/ # User-related types and operations
93
- │ ├── roles/ # Role-related types and operations
94
- │ ├── groups/ # Group-related types and operations
95
- │ ├── organizations/ # Organization-related types and operations
96
- │ ├── projects/ # Project-related types and operations
97
- │ └── tags/ # Tag-related types and operations
98
- ├── generated/ # Generated TypeScript files
99
- │ ├── types.ts # Generated types
100
- │ ├── operations.ts # Generated operations
101
- │ └── resolvers.ts # Generated resolvers
102
- └── types/ # Additional TypeScript types
103
- └── index.ts # Context and additional types
104
+ ├── schema/ # GraphQL SDL — one directory per domain, each with
105
+ │ │ # inputs/, types/ and (where the domain is on the graph)
106
+ │ │ # queries/ and mutations/
107
+ │ ├── base.graphql # Scalars, shared interfaces, Tenant/SortOrder, Scope
108
+ │ └── root.graphql # Query/Mutation roots the domains extend
109
+ ├── operations/ # Client operation documents, one directory per domain
110
+ ├── generated/ # Codegen output — committed, never hand-edited
111
+ │ ├── schema-types.ts # Schema types (owns every type name)
112
+ │ ├── graphql.ts # Operation types + typed document nodes
113
+ │ └── resolvers.ts # Resolver types; imports from schema-types
114
+ ├── events/ # Event catalog and envelope types
115
+ ├── cdm/, notifications/, # Hand-written contract types that are not codegen'd
116
+ │ webhooks/
117
+ └── index.ts # Public barrel
104
118
  ```
105
119
 
120
+ `apps/api` loads every file under `src/schema/` into `makeExecutableSchema`, so
121
+ anything declared there ships in the served schema whether or not a query reaches it.
122
+
106
123
  ## Contributing
107
124
 
108
125
  When modifying the GraphQL schema:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grantjs/schema",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
4
4
  "description": "GraphQL schema and generated types for Grant",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -13,14 +13,18 @@
13
13
  "@graphql-typed-document-node/core": "^3.2.0"
14
14
  },
15
15
  "devDependencies": {
16
+ "@graphql-codegen/add": "^7.1.0",
16
17
  "@graphql-codegen/cli": "^7.2.0",
17
- "@graphql-codegen/client-preset": "^6.1.0",
18
+ "@graphql-codegen/typed-document-node": "^7.1.0",
18
19
  "@graphql-codegen/typescript": "^6.1.0",
20
+ "@graphql-codegen/typescript-operations": "^6.1.2",
19
21
  "@graphql-codegen/typescript-resolvers": "^6.1.0",
20
22
  "@parcel/watcher": "^2.6.0",
21
23
  "@types/node": "^26.1.1",
22
24
  "eslint": "^10.7.0",
23
- "typescript": "^6.0.3"
25
+ "graphql": "^16.14.2",
26
+ "typescript": "^6.0.3",
27
+ "vitest": "^4.1.10"
24
28
  },
25
29
  "scripts": {
26
30
  "build": "tsc",
@@ -30,6 +34,8 @@
30
34
  "lint": "eslint src --ext .ts,.tsx",
31
35
  "lint:fix": "eslint src --ext .ts,.tsx --fix",
32
36
  "type-check": "tsc --noEmit",
33
- "clean": "rm -rf dist"
37
+ "clean": "rm -rf dist",
38
+ "test": "vitest",
39
+ "test:coverage": "vitest run --coverage"
34
40
  }
35
41
  }
@@ -11,28 +11,25 @@
11
11
  export const EVENT_CATEGORIES = ['security', 'iam', 'membership', 'integrations'] as const;
12
12
  export type EventCategory = (typeof EVENT_CATEGORIES)[number];
13
13
 
14
- export const EVENT_DELIVERY_CLASSES = ['transactional', 'notification'] as const;
15
- export type EventDeliveryClass = (typeof EVENT_DELIVERY_CLASSES)[number];
16
-
17
- /** Declarative audience primitives resolved by the notification audience resolver. */
18
- export const AUDIENCE_PRIMITIVES = [
19
- 'actor',
20
- 'subject',
21
- 'scopeMembers',
22
- 'roleHolders',
23
- 'owners',
24
- 'watchers',
25
- ] as const;
26
- export type AudiencePrimitive = (typeof AUDIENCE_PRIMITIVES)[number];
14
+ export type EventDeliveryClass = 'transactional' | 'notification';
15
+
16
+ /**
17
+ * Declarative audience primitives resolved by the notification audience resolver.
18
+ * A union rather than an `as const` array: nothing enumerates these at runtime, so
19
+ * the array was shipped dead weight. Re-introduce the array if a caller ever needs
20
+ * to iterate them.
21
+ */
22
+ export type AudiencePrimitive =
23
+ 'actor' | 'subject' | 'scopeMembers' | 'roleHolders' | 'owners' | 'watchers';
27
24
 
28
- export interface AudienceRule {
25
+ interface AudienceRule {
29
26
  /** Primitives whose resolved users are unioned to form the candidate set. */
30
27
  primitives: readonly AudiencePrimitive[];
31
28
  /** Exclude the acting user from the resolved audience (default true). */
32
29
  excludeActor?: boolean;
33
30
  }
34
31
 
35
- export interface EventCatalogEntry {
32
+ interface EventCatalogEntry {
36
33
  category: EventCategory;
37
34
  deliveryClass: EventDeliveryClass;
38
35
  audienceRule: AudienceRule;
@@ -786,29 +786,6 @@ export type GetInvitationQuery = {
786
786
  } | null;
787
787
  };
788
788
 
789
- export type GetOrganizationInvitationsQueryVariables = Exact<{
790
- scope: Types.Scope;
791
- status?: Types.OrganizationInvitationStatus | null | undefined;
792
- }>;
793
-
794
- export type GetOrganizationInvitationsQuery = {
795
- organizationInvitations: {
796
- totalCount: number;
797
- hasNextPage: boolean;
798
- invitations: Array<{
799
- id: string;
800
- organizationId: string;
801
- email: string;
802
- roleId: string;
803
- status: Types.OrganizationInvitationStatus;
804
- expiresAt: Date;
805
- invitedBy: string;
806
- invitedAt: Date;
807
- createdAt: Date;
808
- }>;
809
- };
810
- };
811
-
812
789
  export type InviteMemberMutationVariables = Exact<{
813
790
  input: Types.InviteMemberInput;
814
791
  }>;
@@ -1595,30 +1572,6 @@ export type RevokeRolePermissionMutation = {
1595
1572
  };
1596
1573
  };
1597
1574
 
1598
- export type GetRoleDirectPermissionsQueryVariables = Exact<{
1599
- scope: Types.Scope;
1600
- roleId: string | number;
1601
- }>;
1602
-
1603
- export type GetRoleDirectPermissionsQuery = {
1604
- roles: {
1605
- roles: Array<{
1606
- id: string;
1607
- permissionCount: number;
1608
- rolePermissions: Array<{
1609
- id: string;
1610
- permissionId: string;
1611
- permission: {
1612
- id: string;
1613
- name: string;
1614
- action: string;
1615
- resource: { slug: string } | null;
1616
- } | null;
1617
- }> | null;
1618
- }>;
1619
- };
1620
- };
1621
-
1622
1575
  export type CreateRoleMutationVariables = Exact<{
1623
1576
  input: Types.CreateRoleInput;
1624
1577
  }>;
@@ -1823,30 +1776,6 @@ export type RevokeUserPermissionMutation = {
1823
1776
  };
1824
1777
  };
1825
1778
 
1826
- export type GetUserDirectPermissionsQueryVariables = Exact<{
1827
- scope: Types.Scope;
1828
- userId: string | number;
1829
- }>;
1830
-
1831
- export type GetUserDirectPermissionsQuery = {
1832
- users: {
1833
- users: Array<{
1834
- id: string;
1835
- permissionCount: number;
1836
- userPermissions: Array<{
1837
- id: string;
1838
- permissionId: string;
1839
- permission: {
1840
- id: string;
1841
- name: string;
1842
- action: string;
1843
- resource: { slug: string } | null;
1844
- } | null;
1845
- }> | null;
1846
- }>;
1847
- };
1848
- };
1849
-
1850
1779
  export type CreateUserMutationVariables = Exact<{
1851
1780
  input: Types.CreateUserInput;
1852
1781
  }>;
@@ -5108,83 +5037,6 @@ export const GetInvitationDocument = {
5108
5037
  },
5109
5038
  ],
5110
5039
  } as unknown as DocumentNode<GetInvitationQuery, GetInvitationQueryVariables>;
5111
- export const GetOrganizationInvitationsDocument = {
5112
- kind: 'Document',
5113
- definitions: [
5114
- {
5115
- kind: 'OperationDefinition',
5116
- operation: 'query',
5117
- name: { kind: 'Name', value: 'GetOrganizationInvitations' },
5118
- variableDefinitions: [
5119
- {
5120
- kind: 'VariableDefinition',
5121
- variable: { kind: 'Variable', name: { kind: 'Name', value: 'scope' } },
5122
- type: {
5123
- kind: 'NonNullType',
5124
- type: { kind: 'NamedType', name: { kind: 'Name', value: 'Scope' } },
5125
- },
5126
- },
5127
- {
5128
- kind: 'VariableDefinition',
5129
- variable: { kind: 'Variable', name: { kind: 'Name', value: 'status' } },
5130
- type: {
5131
- kind: 'NamedType',
5132
- name: { kind: 'Name', value: 'OrganizationInvitationStatus' },
5133
- },
5134
- },
5135
- ],
5136
- selectionSet: {
5137
- kind: 'SelectionSet',
5138
- selections: [
5139
- {
5140
- kind: 'Field',
5141
- name: { kind: 'Name', value: 'organizationInvitations' },
5142
- arguments: [
5143
- {
5144
- kind: 'Argument',
5145
- name: { kind: 'Name', value: 'scope' },
5146
- value: { kind: 'Variable', name: { kind: 'Name', value: 'scope' } },
5147
- },
5148
- {
5149
- kind: 'Argument',
5150
- name: { kind: 'Name', value: 'status' },
5151
- value: { kind: 'Variable', name: { kind: 'Name', value: 'status' } },
5152
- },
5153
- ],
5154
- selectionSet: {
5155
- kind: 'SelectionSet',
5156
- selections: [
5157
- {
5158
- kind: 'Field',
5159
- name: { kind: 'Name', value: 'invitations' },
5160
- selectionSet: {
5161
- kind: 'SelectionSet',
5162
- selections: [
5163
- { kind: 'Field', name: { kind: 'Name', value: 'id' } },
5164
- { kind: 'Field', name: { kind: 'Name', value: 'organizationId' } },
5165
- { kind: 'Field', name: { kind: 'Name', value: 'email' } },
5166
- { kind: 'Field', name: { kind: 'Name', value: 'roleId' } },
5167
- { kind: 'Field', name: { kind: 'Name', value: 'status' } },
5168
- { kind: 'Field', name: { kind: 'Name', value: 'expiresAt' } },
5169
- { kind: 'Field', name: { kind: 'Name', value: 'invitedBy' } },
5170
- { kind: 'Field', name: { kind: 'Name', value: 'invitedAt' } },
5171
- { kind: 'Field', name: { kind: 'Name', value: 'createdAt' } },
5172
- ],
5173
- },
5174
- },
5175
- { kind: 'Field', name: { kind: 'Name', value: 'totalCount' } },
5176
- { kind: 'Field', name: { kind: 'Name', value: 'hasNextPage' } },
5177
- ],
5178
- },
5179
- },
5180
- ],
5181
- },
5182
- },
5183
- ],
5184
- } as unknown as DocumentNode<
5185
- GetOrganizationInvitationsQuery,
5186
- GetOrganizationInvitationsQueryVariables
5187
- >;
5188
5040
  export const InviteMemberDocument = {
5189
5041
  kind: 'Document',
5190
5042
  definitions: [
@@ -8331,122 +8183,6 @@ export const RevokeRolePermissionDocument = {
8331
8183
  },
8332
8184
  ],
8333
8185
  } as unknown as DocumentNode<RevokeRolePermissionMutation, RevokeRolePermissionMutationVariables>;
8334
- export const GetRoleDirectPermissionsDocument = {
8335
- kind: 'Document',
8336
- definitions: [
8337
- {
8338
- kind: 'OperationDefinition',
8339
- operation: 'query',
8340
- name: { kind: 'Name', value: 'GetRoleDirectPermissions' },
8341
- variableDefinitions: [
8342
- {
8343
- kind: 'VariableDefinition',
8344
- variable: { kind: 'Variable', name: { kind: 'Name', value: 'scope' } },
8345
- type: {
8346
- kind: 'NonNullType',
8347
- type: { kind: 'NamedType', name: { kind: 'Name', value: 'Scope' } },
8348
- },
8349
- },
8350
- {
8351
- kind: 'VariableDefinition',
8352
- variable: { kind: 'Variable', name: { kind: 'Name', value: 'roleId' } },
8353
- type: {
8354
- kind: 'NonNullType',
8355
- type: { kind: 'NamedType', name: { kind: 'Name', value: 'ID' } },
8356
- },
8357
- },
8358
- ],
8359
- selectionSet: {
8360
- kind: 'SelectionSet',
8361
- selections: [
8362
- {
8363
- kind: 'Field',
8364
- name: { kind: 'Name', value: 'roles' },
8365
- arguments: [
8366
- {
8367
- kind: 'Argument',
8368
- name: { kind: 'Name', value: 'scope' },
8369
- value: { kind: 'Variable', name: { kind: 'Name', value: 'scope' } },
8370
- },
8371
- {
8372
- kind: 'Argument',
8373
- name: { kind: 'Name', value: 'ids' },
8374
- value: {
8375
- kind: 'ListValue',
8376
- values: [{ kind: 'Variable', name: { kind: 'Name', value: 'roleId' } }],
8377
- },
8378
- },
8379
- {
8380
- kind: 'Argument',
8381
- name: { kind: 'Name', value: 'limit' },
8382
- value: { kind: 'IntValue', value: '1' },
8383
- },
8384
- ],
8385
- selectionSet: {
8386
- kind: 'SelectionSet',
8387
- selections: [
8388
- {
8389
- kind: 'Field',
8390
- name: { kind: 'Name', value: 'roles' },
8391
- selectionSet: {
8392
- kind: 'SelectionSet',
8393
- selections: [
8394
- { kind: 'Field', name: { kind: 'Name', value: 'id' } },
8395
- { kind: 'Field', name: { kind: 'Name', value: 'permissionCount' } },
8396
- {
8397
- kind: 'Field',
8398
- name: { kind: 'Name', value: 'rolePermissions' },
8399
- selectionSet: {
8400
- kind: 'SelectionSet',
8401
- selections: [
8402
- { kind: 'Field', name: { kind: 'Name', value: 'id' } },
8403
- { kind: 'Field', name: { kind: 'Name', value: 'permissionId' } },
8404
- {
8405
- kind: 'Field',
8406
- name: { kind: 'Name', value: 'permission' },
8407
- arguments: [
8408
- {
8409
- kind: 'Argument',
8410
- name: { kind: 'Name', value: 'scope' },
8411
- value: {
8412
- kind: 'Variable',
8413
- name: { kind: 'Name', value: 'scope' },
8414
- },
8415
- },
8416
- ],
8417
- selectionSet: {
8418
- kind: 'SelectionSet',
8419
- selections: [
8420
- { kind: 'Field', name: { kind: 'Name', value: 'id' } },
8421
- { kind: 'Field', name: { kind: 'Name', value: 'name' } },
8422
- { kind: 'Field', name: { kind: 'Name', value: 'action' } },
8423
- {
8424
- kind: 'Field',
8425
- name: { kind: 'Name', value: 'resource' },
8426
- selectionSet: {
8427
- kind: 'SelectionSet',
8428
- selections: [
8429
- { kind: 'Field', name: { kind: 'Name', value: 'slug' } },
8430
- ],
8431
- },
8432
- },
8433
- ],
8434
- },
8435
- },
8436
- ],
8437
- },
8438
- },
8439
- ],
8440
- },
8441
- },
8442
- ],
8443
- },
8444
- },
8445
- ],
8446
- },
8447
- },
8448
- ],
8449
- } as unknown as DocumentNode<GetRoleDirectPermissionsQuery, GetRoleDirectPermissionsQueryVariables>;
8450
8186
  export const CreateRoleDocument = {
8451
8187
  kind: 'Document',
8452
8188
  definitions: [
@@ -9399,122 +9135,6 @@ export const RevokeUserPermissionDocument = {
9399
9135
  },
9400
9136
  ],
9401
9137
  } as unknown as DocumentNode<RevokeUserPermissionMutation, RevokeUserPermissionMutationVariables>;
9402
- export const GetUserDirectPermissionsDocument = {
9403
- kind: 'Document',
9404
- definitions: [
9405
- {
9406
- kind: 'OperationDefinition',
9407
- operation: 'query',
9408
- name: { kind: 'Name', value: 'GetUserDirectPermissions' },
9409
- variableDefinitions: [
9410
- {
9411
- kind: 'VariableDefinition',
9412
- variable: { kind: 'Variable', name: { kind: 'Name', value: 'scope' } },
9413
- type: {
9414
- kind: 'NonNullType',
9415
- type: { kind: 'NamedType', name: { kind: 'Name', value: 'Scope' } },
9416
- },
9417
- },
9418
- {
9419
- kind: 'VariableDefinition',
9420
- variable: { kind: 'Variable', name: { kind: 'Name', value: 'userId' } },
9421
- type: {
9422
- kind: 'NonNullType',
9423
- type: { kind: 'NamedType', name: { kind: 'Name', value: 'ID' } },
9424
- },
9425
- },
9426
- ],
9427
- selectionSet: {
9428
- kind: 'SelectionSet',
9429
- selections: [
9430
- {
9431
- kind: 'Field',
9432
- name: { kind: 'Name', value: 'users' },
9433
- arguments: [
9434
- {
9435
- kind: 'Argument',
9436
- name: { kind: 'Name', value: 'scope' },
9437
- value: { kind: 'Variable', name: { kind: 'Name', value: 'scope' } },
9438
- },
9439
- {
9440
- kind: 'Argument',
9441
- name: { kind: 'Name', value: 'ids' },
9442
- value: {
9443
- kind: 'ListValue',
9444
- values: [{ kind: 'Variable', name: { kind: 'Name', value: 'userId' } }],
9445
- },
9446
- },
9447
- {
9448
- kind: 'Argument',
9449
- name: { kind: 'Name', value: 'limit' },
9450
- value: { kind: 'IntValue', value: '1' },
9451
- },
9452
- ],
9453
- selectionSet: {
9454
- kind: 'SelectionSet',
9455
- selections: [
9456
- {
9457
- kind: 'Field',
9458
- name: { kind: 'Name', value: 'users' },
9459
- selectionSet: {
9460
- kind: 'SelectionSet',
9461
- selections: [
9462
- { kind: 'Field', name: { kind: 'Name', value: 'id' } },
9463
- { kind: 'Field', name: { kind: 'Name', value: 'permissionCount' } },
9464
- {
9465
- kind: 'Field',
9466
- name: { kind: 'Name', value: 'userPermissions' },
9467
- selectionSet: {
9468
- kind: 'SelectionSet',
9469
- selections: [
9470
- { kind: 'Field', name: { kind: 'Name', value: 'id' } },
9471
- { kind: 'Field', name: { kind: 'Name', value: 'permissionId' } },
9472
- {
9473
- kind: 'Field',
9474
- name: { kind: 'Name', value: 'permission' },
9475
- arguments: [
9476
- {
9477
- kind: 'Argument',
9478
- name: { kind: 'Name', value: 'scope' },
9479
- value: {
9480
- kind: 'Variable',
9481
- name: { kind: 'Name', value: 'scope' },
9482
- },
9483
- },
9484
- ],
9485
- selectionSet: {
9486
- kind: 'SelectionSet',
9487
- selections: [
9488
- { kind: 'Field', name: { kind: 'Name', value: 'id' } },
9489
- { kind: 'Field', name: { kind: 'Name', value: 'name' } },
9490
- { kind: 'Field', name: { kind: 'Name', value: 'action' } },
9491
- {
9492
- kind: 'Field',
9493
- name: { kind: 'Name', value: 'resource' },
9494
- selectionSet: {
9495
- kind: 'SelectionSet',
9496
- selections: [
9497
- { kind: 'Field', name: { kind: 'Name', value: 'slug' } },
9498
- ],
9499
- },
9500
- },
9501
- ],
9502
- },
9503
- },
9504
- ],
9505
- },
9506
- },
9507
- ],
9508
- },
9509
- },
9510
- ],
9511
- },
9512
- },
9513
- ],
9514
- },
9515
- },
9516
- ],
9517
- } as unknown as DocumentNode<GetUserDirectPermissionsQuery, GetUserDirectPermissionsQueryVariables>;
9518
9138
  export const CreateUserDocument = {
9519
9139
  kind: 'Document',
9520
9140
  definitions: [