@tinacms/graphql 3.0.0 → 4.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.
@@ -0,0 +1,25 @@
1
+ import type { Collectable, TinaSchema } from '@tinacms/schema-tools';
2
+ /** Marks where a rich-text field was parsed: later segments address tree nodes, not stored keys. */
3
+ export declare const MDX_SEGMENT: {
4
+ readonly mdx: true;
5
+ };
6
+ export type LocatorSegment = string | number | typeof MDX_SEGMENT;
7
+ export type ReferenceVisit = {
8
+ /** The stored value: the path of the document being referenced. */
9
+ value: string;
10
+ /** The collections the field may point at. The index records it under each. */
11
+ collections: string[];
12
+ /** The path to it, as keys and list indices from the document root. */
13
+ locator: LocatorSegment[];
14
+ /** Replaces the value in the document being walked. */
15
+ replace: (next: string | null) => void;
16
+ };
17
+ export declare const encodeLocator: (locator: LocatorSegment[]) => string;
18
+ /**
19
+ * Walks a stored document alongside its schema, visiting every reference it holds, and returns
20
+ * whether any `replace` was called.
21
+ *
22
+ * The index build and the rename and delete rewrites all use this traversal, so they resolve the
23
+ * same references.
24
+ */
25
+ export declare const visitReferences: (data: Record<string, unknown>, collectable: Collectable, tinaSchema: TinaSchema, visit: (reference: ReferenceVisit) => void) => boolean;
package/dist/resolve.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { GraphQLConfig } from './types';
2
2
  import type { Database } from './database';
3
- export declare const resolve: ({ config, query, variables, database, silenceErrors, verbose, isAudit, ctxUser, }: {
3
+ import { type CtxUser } from './resolver';
4
+ export declare const resolve: ({ config, query, variables, database, silenceErrors, verbose, isAudit, ctxUser, isSignIn, }: {
4
5
  config?: GraphQLConfig;
5
6
  query: string;
6
7
  variables: object;
@@ -8,9 +9,9 @@ export declare const resolve: ({ config, query, variables, database, silenceErro
8
9
  silenceErrors?: boolean;
9
10
  verbose?: boolean;
10
11
  isAudit?: boolean;
11
- ctxUser?: {
12
- sub: string;
13
- };
12
+ ctxUser?: CtxUser;
13
+ /** Set only by the generated database client's `authenticate()`. */
14
+ isSignIn?: boolean;
14
15
  }) => Promise<import("graphql").ExecutionResult<{
15
16
  [key: string]: any;
16
17
  }, {
@@ -1,15 +1,56 @@
1
- import type { TinaSchema } from '@tinacms/schema-tools';
1
+ import type { Collection, TinaSchema } from '@tinacms/schema-tools';
2
2
  import type { GraphQLResolveInfo } from 'graphql';
3
3
  import type { Resolver } from './index';
4
- export declare function handleAuthenticate({ tinaSchema, resolver, sub, password, ctxUser, }: {
4
+ export declare function getUserDocumentContext(tinaSchema: TinaSchema, resolver: Resolver): Promise<{
5
+ collection: Collection<true>;
6
+ userField: {
7
+ path: string[];
8
+ collectable: import("@tinacms/schema-tools").Collectable;
9
+ idFieldName?: string;
10
+ passwordFieldName?: string;
11
+ };
12
+ users: any;
13
+ userDoc: {
14
+ _sys: {
15
+ title: any;
16
+ basename: string;
17
+ filename: string;
18
+ extension: string;
19
+ hasReferences: boolean;
20
+ path: string;
21
+ relativePath: string;
22
+ breadcrumbs: string[];
23
+ collection: Collection<true>;
24
+ template: string | number;
25
+ };
26
+ _values: {
27
+ _collection: any;
28
+ _template: any;
29
+ };
30
+ _rawData: {
31
+ _collection: any;
32
+ _template: any;
33
+ };
34
+ _collection: any;
35
+ _template: any;
36
+ __typename: string;
37
+ id: string;
38
+ };
39
+ relativePath: string;
40
+ }>;
41
+ export declare function findUserInCollection(users: any[], userField: any, userSub: string): any;
42
+ /**
43
+ * A stored hash only carries over to a user with the same uid, so a new or
44
+ * renamed user saved without a password could never sign in.
45
+ */
46
+ export declare function assertNewUsersHavePasswords(collection: Collection<true>, newBody: Record<string, unknown>, existingData?: Record<string, unknown>): void;
47
+ export declare function handleAuthenticate({ tinaSchema, resolver, sub, password, isSignIn, }: {
5
48
  tinaSchema: TinaSchema;
6
49
  resolver: Resolver;
7
50
  sub?: string;
8
51
  password: string;
9
52
  info: GraphQLResolveInfo;
10
- ctxUser?: {
11
- sub?: string;
12
- };
53
+ isSignIn?: boolean;
13
54
  }): Promise<any>;
14
55
  export declare function handleAuthorize({ tinaSchema, resolver, sub, ctxUser, }: {
15
56
  tinaSchema: TinaSchema;
@@ -18,7 +59,7 @@ export declare function handleAuthorize({ tinaSchema, resolver, sub, ctxUser, }:
18
59
  info: GraphQLResolveInfo;
19
60
  ctxUser?: {
20
61
  sub?: string;
21
- };
62
+ } | null;
22
63
  }): Promise<any>;
23
64
  export declare function handleUpdatePassword({ tinaSchema, resolver, password, ctxUser, }: {
24
65
  tinaSchema: TinaSchema;
@@ -27,5 +68,5 @@ export declare function handleUpdatePassword({ tinaSchema, resolver, password, c
27
68
  info: GraphQLResolveInfo;
28
69
  ctxUser?: {
29
70
  sub?: string;
30
- };
71
+ } | null;
31
72
  }): Promise<boolean>;
@@ -4,11 +4,26 @@
4
4
  import { Database } from '../database';
5
5
  import type { Collectable, Collection, Template, TinaField, TinaSchema } from '@tinacms/schema-tools';
6
6
  import type { GraphQLConfig } from '../types';
7
+ export type AuthCollectionWriteOp = 'create' | 'update' | 'rename' | 'delete' | 'addPending' | 'createFolder';
8
+ /**
9
+ * The signed-in user behind a request. Leave it undefined only when the caller
10
+ * vouches for the call itself, and pass null when nobody is signed in.
11
+ */
12
+ export type CtxUser = {
13
+ sub?: string;
14
+ } | null | undefined;
15
+ type UpdateDocumentArgs = {
16
+ collectionName: string;
17
+ relativePath: string;
18
+ newRelativePath?: string;
19
+ newBody?: Record<string, unknown>;
20
+ };
7
21
  interface ResolverConfig {
8
22
  config?: GraphQLConfig;
9
23
  database: Database;
10
24
  tinaSchema: TinaSchema;
11
25
  isAudit: boolean;
26
+ ctxUser?: CtxUser;
12
27
  }
13
28
  export declare const createResolver: (args: ResolverConfig) => Resolver;
14
29
  export declare const resolveFieldData: ({ namespace, ...field }: TinaField<true>, rawData: unknown, accumulator: {
@@ -66,6 +81,7 @@ export declare class Resolver {
66
81
  database: Database;
67
82
  tinaSchema: TinaSchema;
68
83
  isAudit: boolean;
84
+ ctxUser: CtxUser;
69
85
  constructor(init: ResolverConfig);
70
86
  resolveCollection: (_args: any, collectionName: string, hasDocuments?: boolean) => Promise<{
71
87
  fields: TinaField<true>[];
@@ -248,6 +264,12 @@ export declare class Resolver {
248
264
  */
249
265
  private static validateRelativePath;
250
266
  private validatePath;
267
+ private assertAuthCollectionWrite;
268
+ private assertReferenceUpdates;
269
+ private isAuthCollectionPath;
270
+ private withAuthCollectionLock;
271
+ private isStoredInCollection;
272
+ private isStoredUser;
251
273
  /**
252
274
  * Helper method to get collection and construct validated path.
253
275
  * This encapsulates the common pattern of getting a collection, joining paths,
@@ -349,12 +371,7 @@ export declare class Resolver {
349
371
  __typename: string;
350
372
  id: string;
351
373
  }>;
352
- resolveUpdateDocument: ({ collectionName, relativePath, newRelativePath, newBody, }: {
353
- collectionName: string;
354
- relativePath: string;
355
- newRelativePath?: string;
356
- newBody?: Record<string, unknown>;
357
- }) => Promise<{
374
+ resolveUpdateDocument: (args: UpdateDocumentArgs) => Promise<{
358
375
  _sys: {
359
376
  title: any;
360
377
  basename: string;
@@ -380,6 +397,12 @@ export declare class Resolver {
380
397
  __typename: string;
381
398
  id: string;
382
399
  }>;
400
+ private updateDocument;
401
+ /**
402
+ * Rewrites the auth collection's user store without the admin check, so the
403
+ * caller must check the request user.
404
+ */
405
+ updateAuthDocumentInternal: (update: (rawData: Record<string, any>) => Record<string, any>) => Promise<void>;
383
406
  resolveDeleteDocument: ({ collectionName, relativePath, }: {
384
407
  collectionName: string;
385
408
  relativePath: string;
@@ -570,6 +593,14 @@ export declare class Resolver {
570
593
  endCursor: string;
571
594
  };
572
595
  }>;
596
+ /**
597
+ * Repoints every reference to `from` at `to`, or clears it when `to` is null.
598
+ *
599
+ * Each referring document is re-walked rather than addressed by the locators the index stored,
600
+ * since a stored path cannot address a reference inside rich text. Only a document the walk
601
+ * changed is written back.
602
+ */
603
+ private rewriteReferences;
573
604
  /**
574
605
  * Checks if a document has references to it
575
606
  * @param id The id of the document to check for references
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tinacms/graphql",
3
3
  "type": "module",
4
- "version": "3.0.0",
4
+ "version": "4.0.1",
5
5
  "main": "dist/index.js",
6
6
  "module": "./dist/index.js",
7
7
  "files": [
@@ -36,15 +36,15 @@
36
36
  "gray-matter": "^4.0.3",
37
37
  "isomorphic-git": "^1.29.0",
38
38
  "js-sha1": "^0.6.0",
39
- "js-yaml": "^3.15.1",
39
+ "js-yaml": "^3.15.2",
40
40
  "jsonpath-plus": "^10.3.0",
41
41
  "many-level": "^2.0.0",
42
42
  "micromatch": "4.0.8",
43
43
  "normalize-path": "^3.0.0",
44
44
  "readable-stream": "^4.7.0",
45
45
  "yup": "^1.6.1",
46
- "@tinacms/mdx": "^2.2.3",
47
- "@tinacms/schema-tools": "^2.10.0"
46
+ "@tinacms/mdx": "^2.4.0",
47
+ "@tinacms/schema-tools": "^2.11.0"
48
48
  },
49
49
  "publishConfig": {
50
50
  "registry": "https://registry.npmjs.org"
@@ -72,8 +72,8 @@
72
72
  "vite": "^4.5.9",
73
73
  "vitest": "^0.32.4",
74
74
  "zod": "^3.24.2",
75
- "@tinacms/schema-tools": "2.10.0",
76
- "@tinacms/scripts": "1.6.4"
75
+ "@tinacms/scripts": "1.6.4",
76
+ "@tinacms/schema-tools": "2.11.0"
77
77
  },
78
78
  "scripts": {
79
79
  "types": "pnpm tsc",