@braidhq/source-loader-gdrive 0.1.0 → 0.2.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.
- package/LICENSE +21 -0
- package/README.md +42 -0
- package/dist/{driveClient.d.ts → DriveClient.d.ts} +3 -3
- package/dist/{driveClient.d.ts.map → DriveClient.d.ts.map} +1 -1
- package/dist/{driveClient.js → DriveClient.js} +2 -2
- package/dist/{driveClient.js.map → DriveClient.js.map} +1 -1
- package/dist/GoogleDriveSourceLoaderPlugin.d.ts +46 -0
- package/dist/GoogleDriveSourceLoaderPlugin.d.ts.map +1 -0
- package/dist/{GoogleDriveLoader.js → GoogleDriveSourceLoaderPlugin.js} +55 -51
- package/dist/GoogleDriveSourceLoaderPlugin.js.map +1 -0
- package/dist/Manifest.d.ts +6 -5
- package/dist/Manifest.d.ts.map +1 -1
- package/dist/Manifest.js +5 -4
- package/dist/Manifest.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +21 -26
- package/dist/GoogleDriveLoader.d.ts +0 -78
- package/dist/GoogleDriveLoader.d.ts.map +0 -1
- package/dist/GoogleDriveLoader.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mroops0111
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# @braidhq/source-loader-gdrive
|
|
2
|
+
|
|
3
|
+
Braid keeps a product's intent and its code aligned in one knowledge graph, and lets plugins feed that graph from outside sources. `@braidhq/source-loader-gdrive` is the plugin that exports Google Docs from a Drive folder as markdown, so a team's design docs become a Braid source.
|
|
4
|
+
|
|
5
|
+
## Role
|
|
6
|
+
|
|
7
|
+
The drive loader walks a Drive folder, exports every Google Doc it finds as markdown, and keeps a manifest so later syncs touch only what changed.
|
|
8
|
+
|
|
9
|
+
- **The Export**: Each doc is exported to `<destination>/<sanitised-title>/index.md`, and its inlined base64 images are decoded into sibling files, so the markdown stays readable for humans and models.
|
|
10
|
+
- **The Manifest**: A `.braid-gdrive-manifest.json` records each doc's id, title, and modified time, so sync can add, update, rename, or remove docs against the prior state instead of re-downloading everything.
|
|
11
|
+
- **The Auth**: A fresh OAuth access token is resolved per workspace and source through an injected callback, so credentials stay in the composition root, never in config.
|
|
12
|
+
|
|
13
|
+
## Structure
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
src/
|
|
17
|
+
├── GoogleDriveSourceLoaderPlugin.ts the gdrive loader, config, walk, export, manifest-diff sync
|
|
18
|
+
├── DriveClient.ts the Drive REST client, list children and export a doc
|
|
19
|
+
├── Manifest.ts the on-disk sync-state manifest, read and write
|
|
20
|
+
└── index.ts re-exports the factory and its config type
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- **GoogleDriveSourceLoaderPlugin**: The `createGoogleDriveLoader` factory. It walks the folder, filters by title, exports each doc, extracts inline images, and diffs against the manifest on sync.
|
|
24
|
+
- **DriveClient**: The thin Drive REST wrapper, listing folder children and exporting a doc to a given mime type.
|
|
25
|
+
- **Manifest**: The read and write of `.braid-gdrive-manifest.json`, the record sync diffs against.
|
|
26
|
+
|
|
27
|
+
## Export and Layout
|
|
28
|
+
|
|
29
|
+
Drive folder hierarchy is flattened. Every matched doc lands in its own directory directly under the destination, named from the sanitised Drive title, so two docs that sanitise to the same name collide and one must be renamed in Drive. Auto-created `Copy of` duplicates are skipped, and title `include` and `exclude` regexes narrow what is exported while subfolders are still traversed when `recursive` is set.
|
|
30
|
+
|
|
31
|
+
Only Google Docs are in scope. Sheets, Slides, Drawings, and Forms are left for a different plugin. The `folderId` alias `root` is rejected outright, since it would mirror an entire My Drive.
|
|
32
|
+
|
|
33
|
+
## Boundaries
|
|
34
|
+
|
|
35
|
+
- **Owns Its Directory**: The destination and its manifest are the loader's to write. Provision wipes and rebuilds it, sync reconciles it against Drive.
|
|
36
|
+
- **No Credentials On Disk**: The access token is resolved at run time through the injected callback. Only exported markdown and images land in the destination.
|
|
37
|
+
- **A Plugin, Not A Service**: It implements core's `SourceLoader` port through the sdk factory, and depends on the host to supply OAuth token resolution.
|
|
38
|
+
|
|
39
|
+
## Dependencies
|
|
40
|
+
|
|
41
|
+
- **Depends On**: `@braidhq/core` for the port, `@braidhq/schema` for shared types, `@braidhq/sdk` for the factory, and `zod`.
|
|
42
|
+
- **Consumed By**: The server composition root, where `composeFsApp` registers the gdrive loader and wires `resolveAccessToken` to its OAuth store.
|
|
@@ -3,7 +3,7 @@ import { Buffer } from 'node:buffer';
|
|
|
3
3
|
* Tiny Google Drive v3 client wrapper. We only use a few endpoints and
|
|
4
4
|
* don't need the full `googleapis` package (which ships > 1 MB of types).
|
|
5
5
|
*
|
|
6
|
-
* Inject `fetchFn` for tests
|
|
6
|
+
* Inject `fetchFn` for tests. Real callers use globalThis.fetch.
|
|
7
7
|
*/
|
|
8
8
|
export type FetchFn = typeof globalThis.fetch;
|
|
9
9
|
export interface DriveFileMetadata {
|
|
@@ -21,8 +21,8 @@ export declare class DriveClient {
|
|
|
21
21
|
listChildren(folderId: string): Promise<readonly DriveFileMetadata[]>;
|
|
22
22
|
/** Export a Google native doc (gdoc / gsheet / gslides) to a chosen format. */
|
|
23
23
|
exportDoc(fileId: string, mimeType: string): Promise<Buffer>;
|
|
24
|
-
/** Download a binary file (image, PDF,
|
|
24
|
+
/** Download a binary file (image, PDF, and so on) as-is. */
|
|
25
25
|
downloadFile(fileId: string): Promise<Buffer>;
|
|
26
26
|
private authHeader;
|
|
27
27
|
}
|
|
28
|
-
//# sourceMappingURL=
|
|
28
|
+
//# sourceMappingURL=DriveClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"DriveClient.d.ts","sourceRoot":"","sources":["../src/DriveClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAMpC;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,UAAU,CAAC,KAAK,CAAA;AAE7C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAED,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAA0B;IAGtD,sDAAsD;IAChD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC;IAsB3E,+EAA+E;IACzE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQlE,4DAA4D;IACtD,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQnD,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -39,7 +39,7 @@ export class DriveClient {
|
|
|
39
39
|
throw await driveError(response, `exportDoc(${fileId},${mimeType})`);
|
|
40
40
|
return globalBuffer().from(await response.arrayBuffer());
|
|
41
41
|
}
|
|
42
|
-
/** Download a binary file (image, PDF,
|
|
42
|
+
/** Download a binary file (image, PDF, and so on) as-is. */
|
|
43
43
|
async downloadFile(fileId) {
|
|
44
44
|
const url = `https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`;
|
|
45
45
|
const response = await this.fetchFn(url, { headers: this.authHeader() });
|
|
@@ -55,4 +55,4 @@ async function driveError(response, op) {
|
|
|
55
55
|
const text = await response.text().catch(() => '');
|
|
56
56
|
return new Error(`Drive ${op} failed: ${response.status} ${response.statusText} ${text}`);
|
|
57
57
|
}
|
|
58
|
-
//# sourceMappingURL=
|
|
58
|
+
//# sourceMappingURL=DriveClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"DriveClient.js","sourceRoot":"","sources":["../src/DriveClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { SourceLoaderContext, SourceLoaderPlugin } from '@braidhq/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { type DriveFileMetadata, type FetchFn } from './DriveClient.js';
|
|
4
|
+
export declare const GoogleDriveLoaderConfig: z.ZodObject<{
|
|
5
|
+
folderId: z.ZodString;
|
|
6
|
+
recursive: z.ZodDefault<z.ZodBoolean>;
|
|
7
|
+
include: z.ZodOptional<z.ZodString>;
|
|
8
|
+
exclude: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
export type GoogleDriveLoaderConfig = z.infer<typeof GoogleDriveLoaderConfig>;
|
|
11
|
+
export interface GoogleDriveLoaderDeps {
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a fresh access token for a given `(workspaceId, sourceId)`.
|
|
14
|
+
* The composition root implements this against its OAuth refresh-token store.
|
|
15
|
+
* Tests can return a static token regardless of context.
|
|
16
|
+
*/
|
|
17
|
+
resolveAccessToken: (context: SourceLoaderContext) => Promise<string>;
|
|
18
|
+
/** Inject for tests. Real callers use globalThis.fetch. */
|
|
19
|
+
fetchFn?: FetchFn;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build a Google Drive source loader. Walks a Drive folder, exports every
|
|
23
|
+
* Google Doc inside as markdown, extracts inlined base64 images into
|
|
24
|
+
* sibling files, and lays everything out as:
|
|
25
|
+
*
|
|
26
|
+
* <destination>/
|
|
27
|
+
* <sanitised-doc-title>/
|
|
28
|
+
* index.md
|
|
29
|
+
* <image-label>.png (one per inlined image)
|
|
30
|
+
* <sanitised-doc-title-2>/
|
|
31
|
+
* index.md
|
|
32
|
+
* .braid-gdrive-manifest.json (sync state)
|
|
33
|
+
*
|
|
34
|
+
* Drive folder hierarchy is not preserved on disk.
|
|
35
|
+
* Every matched doc is flattened into a sibling directory under `destination/`.
|
|
36
|
+
* Two docs with the same sanitised title will collide,
|
|
37
|
+
* so rename one in Drive to disambiguate.
|
|
38
|
+
*
|
|
39
|
+
* Out of scope (intentional): Google Sheets, Slides, Drawings, Forms, and standalone binaries.
|
|
40
|
+
* Mirrors redoc's PRD-focused workflow.
|
|
41
|
+
* When you need spreadsheets or slide decks, provision them through a different source-loader plugin.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createGoogleDriveLoader(deps: GoogleDriveLoaderDeps): SourceLoaderPlugin;
|
|
44
|
+
/** Note: the helper used by DriveClient.exportDoc returns Buffer. */
|
|
45
|
+
export type { DriveFileMetadata, FetchFn };
|
|
46
|
+
//# sourceMappingURL=GoogleDriveSourceLoaderPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GoogleDriveSourceLoaderPlugin.d.ts","sourceRoot":"","sources":["../src/GoogleDriveSourceLoaderPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAK5E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAe,KAAK,iBAAiB,EAAE,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAA;AA4BpF,eAAO,MAAM,uBAAuB;;;;;iBAiClC,CAAA;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAE7E,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,kBAAkB,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACrE,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAaD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,kBAAkB,CAgHvF;AA+GD,qEAAqE;AACrE,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -1,37 +1,39 @@
|
|
|
1
1
|
import { Buffer } from 'node:buffer';
|
|
2
2
|
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
import {
|
|
4
|
+
import { defineSourceLoaderPlugin } from '@braidhq/sdk';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
-
import { DriveClient } from './
|
|
6
|
+
import { DriveClient } from './DriveClient.js';
|
|
7
7
|
import { readManifest, writeManifest } from './Manifest.js';
|
|
8
8
|
const FOLDER_MIME = 'application/vnd.google-apps.folder';
|
|
9
9
|
const DOC_MIME = 'application/vnd.google-apps.document';
|
|
10
10
|
/**
|
|
11
|
-
* Drive auto-creates duplicates named "Copy of
|
|
12
|
-
*
|
|
13
|
-
* stale content that would conflict with the canonical doc,
|
|
14
|
-
* them silently. Same rule as redoc.
|
|
11
|
+
* Drive auto-creates duplicates named "Copy of" (English) or ending in "的副本" (Chinese),
|
|
12
|
+
* when users use the Make a Copy menu.
|
|
13
|
+
* They almost always carry stale content that would conflict with the canonical doc,
|
|
14
|
+
* so we skip them silently. Same rule as redoc.
|
|
15
15
|
*/
|
|
16
16
|
const COPY_PATTERNS = [/^Copy of /, /的副本$/];
|
|
17
17
|
/**
|
|
18
|
-
* Drive's `text/markdown` export inlines images as base64 data URIs
|
|
19
|
-
* reference-style link form:
|
|
18
|
+
* Drive's `text/markdown` export inlines images as base64 data URIs,
|
|
19
|
+
* in reference-style link form:
|
|
20
20
|
*
|
|
21
|
-
* [image0]: <data:image/png;base64,iVBORw0KG
|
|
21
|
+
* [image0]: <data:image/png;base64,iVBORw0KG...>
|
|
22
22
|
*
|
|
23
|
-
* Leaving those base64 blobs in the markdown bloats the file by ~33 % per
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* rewrite the link to a relative path.
|
|
23
|
+
* Leaving those base64 blobs in the markdown bloats the file by ~33 % per image,
|
|
24
|
+
* and is unreadable for both humans and LLMs.
|
|
25
|
+
* This regex matches one such reference line,
|
|
26
|
+
* so we can extract the image to its own file and rewrite the link to a relative path.
|
|
27
|
+
* Same approach as redoc.
|
|
27
28
|
*/
|
|
28
29
|
const INLINE_IMAGE_RE = /^\[([^\]]+)\]:\s*<data:image\/([\w+]+);base64,([^>]+)>$/gm;
|
|
29
30
|
export const GoogleDriveLoaderConfig = z.object({
|
|
30
31
|
/**
|
|
31
|
-
* Drive folder id (the long alphanumeric in the URL).
|
|
32
|
-
* `root` outright
|
|
33
|
-
*
|
|
34
|
-
* from an "intent docs" source
|
|
32
|
+
* Drive folder id (the long alphanumeric in the URL).
|
|
33
|
+
* Reject the alias `root` outright,
|
|
34
|
+
* since it expands to the user's entire My Drive and would mirror every file they own,
|
|
35
|
+
* which is almost never what someone wants from an "intent docs" source,
|
|
36
|
+
* and easily costs gigabytes and minutes.
|
|
35
37
|
* Make people pick a specific subfolder.
|
|
36
38
|
*/
|
|
37
39
|
folderId: z.string()
|
|
@@ -40,20 +42,22 @@ export const GoogleDriveLoaderConfig = z.object({
|
|
|
40
42
|
message: 'folderId "root" refers to the entire My Drive and is rejected. Create a dedicated subfolder and use its id instead.',
|
|
41
43
|
}),
|
|
42
44
|
/**
|
|
43
|
-
* Whether to traverse subfolders. Default true.
|
|
44
|
-
* is
|
|
45
|
-
* directly under `destination/`.
|
|
46
|
-
* children of `folderId`.
|
|
45
|
+
* Whether to traverse subfolders. Default true.
|
|
46
|
+
* Subfolder hierarchy is not preserved on disk.
|
|
47
|
+
* Every matching doc lives in its own dir directly under `destination/`.
|
|
48
|
+
* Disable to limit to immediate children of `folderId`.
|
|
47
49
|
*/
|
|
48
50
|
recursive: z.boolean().default(true),
|
|
49
51
|
/**
|
|
50
|
-
* Optional regex (string).
|
|
51
|
-
* matches this pattern are downloaded.
|
|
52
|
+
* Optional regex (string).
|
|
53
|
+
* When set, only docs whose *Drive title* matches this pattern are downloaded.
|
|
54
|
+
* Subfolders are still traversed.
|
|
52
55
|
*/
|
|
53
56
|
include: z.string().optional(),
|
|
54
57
|
/**
|
|
55
|
-
* Optional regex (string).
|
|
56
|
-
*
|
|
58
|
+
* Optional regex (string).
|
|
59
|
+
* When set, docs whose title matches are skipped.
|
|
60
|
+
* Evaluated after `include`, so exclude takes priority.
|
|
57
61
|
*/
|
|
58
62
|
exclude: z.string().optional(),
|
|
59
63
|
});
|
|
@@ -68,23 +72,22 @@ export const GoogleDriveLoaderConfig = z.object({
|
|
|
68
72
|
* <image-label>.png (one per inlined image)
|
|
69
73
|
* <sanitised-doc-title-2>/
|
|
70
74
|
* index.md
|
|
71
|
-
* .braid-manifest.json (sync state)
|
|
75
|
+
* .braid-gdrive-manifest.json (sync state)
|
|
72
76
|
*
|
|
73
|
-
* Drive folder hierarchy is
|
|
74
|
-
* is flattened into a sibling directory under `destination/`.
|
|
75
|
-
* with the same sanitised title will collide
|
|
76
|
-
* disambiguate.
|
|
77
|
+
* Drive folder hierarchy is not preserved on disk.
|
|
78
|
+
* Every matched doc is flattened into a sibling directory under `destination/`.
|
|
79
|
+
* Two docs with the same sanitised title will collide,
|
|
80
|
+
* so rename one in Drive to disambiguate.
|
|
77
81
|
*
|
|
78
|
-
* Out of scope (intentional): Google Sheets, Slides, Drawings, Forms,
|
|
79
|
-
*
|
|
80
|
-
* need spreadsheets
|
|
81
|
-
* source-loader plugin.
|
|
82
|
+
* Out of scope (intentional): Google Sheets, Slides, Drawings, Forms, and standalone binaries.
|
|
83
|
+
* Mirrors redoc's PRD-focused workflow.
|
|
84
|
+
* When you need spreadsheets or slide decks, provision them through a different source-loader plugin.
|
|
82
85
|
*/
|
|
83
86
|
export function createGoogleDriveLoader(deps) {
|
|
84
|
-
return
|
|
87
|
+
return defineSourceLoaderPlugin({
|
|
85
88
|
kind: 'gdrive',
|
|
86
89
|
configSchema: GoogleDriveLoaderConfig,
|
|
87
|
-
|
|
90
|
+
provision: async (config, destination, context) => {
|
|
88
91
|
await rm(destination, { recursive: true, force: true });
|
|
89
92
|
await mkdir(destination, { recursive: true });
|
|
90
93
|
const client = await buildClient(deps, context);
|
|
@@ -109,8 +112,8 @@ export function createGoogleDriveLoader(deps) {
|
|
|
109
112
|
sync: async (config, destination, context) => {
|
|
110
113
|
const cached = await readManifest(destination);
|
|
111
114
|
if (!cached) {
|
|
112
|
-
// No manifest yet (first sync after upgrade
|
|
113
|
-
// back to a clean
|
|
115
|
+
// No manifest yet (first sync after upgrade or cache wiped).
|
|
116
|
+
// Fall back to a clean provision so we end up in a known-good state.
|
|
114
117
|
const client = await buildClient(deps, context);
|
|
115
118
|
await rm(destination, { recursive: true, force: true });
|
|
116
119
|
await mkdir(destination, { recursive: true });
|
|
@@ -156,8 +159,8 @@ export function createGoogleDriveLoader(deps) {
|
|
|
156
159
|
added++;
|
|
157
160
|
}
|
|
158
161
|
else if (prior.localDir !== doc.localDir || prior.modifiedTime !== doc.modifiedTime) {
|
|
159
|
-
// Either content updated or the doc was renamed in Drive.
|
|
160
|
-
// cases
|
|
162
|
+
// Either content updated or the doc was renamed in Drive.
|
|
163
|
+
// Both cases re-download to the new dir, then rm the old dir.
|
|
161
164
|
if (prior.localDir !== doc.localDir)
|
|
162
165
|
await rm(join(destination, prior.localDir), { recursive: true, force: true });
|
|
163
166
|
await downloadOne(client, doc, destination);
|
|
@@ -216,9 +219,10 @@ async function walk(client, config) {
|
|
|
216
219
|
const localDir = sanitiseName(child.name);
|
|
217
220
|
const collides = seenDirs.get(localDir);
|
|
218
221
|
if (collides && collides !== child.id) {
|
|
219
|
-
// Two distinct Drive docs sanitise to the same dir name.
|
|
220
|
-
// the first one we walked into
|
|
221
|
-
//
|
|
222
|
+
// Two distinct Drive docs sanitise to the same dir name.
|
|
223
|
+
// Keep the first one we walked into.
|
|
224
|
+
// Skipping the second is safer than silently overwriting.
|
|
225
|
+
// User can rename in Drive.
|
|
222
226
|
continue;
|
|
223
227
|
}
|
|
224
228
|
seenDirs.set(localDir, child.id);
|
|
@@ -244,10 +248,10 @@ async function downloadOne(client, doc, destination) {
|
|
|
244
248
|
await writeFile(join(docDir, 'index.md'), rewritten, 'utf-8');
|
|
245
249
|
}
|
|
246
250
|
/**
|
|
247
|
-
* Pull every `[label]: <data:image/ext;base64,...>` reference out of the
|
|
248
|
-
*
|
|
249
|
-
* rewrite the reference to point at the new local file.
|
|
250
|
-
* cleaned markdown. Matches redoc's behaviour.
|
|
251
|
+
* Pull every `[label]: <data:image/ext;base64,...>` reference out of the markdown,
|
|
252
|
+
* write the decoded bytes as `<label>.<ext>` in `docDir`,
|
|
253
|
+
* and rewrite the reference to point at the new local file.
|
|
254
|
+
* Returns the cleaned markdown. Matches redoc's behaviour.
|
|
251
255
|
*/
|
|
252
256
|
async function extractInlineImages(markdown, docDir) {
|
|
253
257
|
const writes = [];
|
|
@@ -277,9 +281,9 @@ function entryOf(doc) {
|
|
|
277
281
|
};
|
|
278
282
|
}
|
|
279
283
|
function sanitiseName(name) {
|
|
280
|
-
// Replace path separators, control chars, and common shell-hostile
|
|
281
|
-
//
|
|
282
|
-
//
|
|
284
|
+
// Replace path separators, control chars, and common shell-hostile characters with `_`.
|
|
285
|
+
// Spaces stay so human-readable titles survive,
|
|
286
|
+
// for example "Roadmap Q3 2026" stays "Roadmap Q3 2026".
|
|
283
287
|
return name.replace(/[/\\:*?"<>|]/g, '_');
|
|
284
288
|
}
|
|
285
|
-
//# sourceMappingURL=
|
|
289
|
+
//# sourceMappingURL=GoogleDriveSourceLoaderPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GoogleDriveSourceLoaderPlugin.js","sourceRoot":"","sources":["../src/GoogleDriveSourceLoaderPlugin.ts"],"names":[],"mappings":"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"}
|
package/dist/Manifest.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Filename written inside `destination` to track per-file sync state. */
|
|
2
|
-
export declare const MANIFEST_FILENAME = ".braid-manifest.json";
|
|
2
|
+
export declare const MANIFEST_FILENAME = ".braid-gdrive-manifest.json";
|
|
3
3
|
export interface ManifestEntry {
|
|
4
|
-
/** Posix relative dir under `destination
|
|
4
|
+
/** Posix relative dir under `destination`, the per-doc package. */
|
|
5
5
|
localDir: string;
|
|
6
6
|
modifiedTime: string;
|
|
7
7
|
/** Drive title at the time of the last sync, for debugging only. */
|
|
@@ -14,9 +14,10 @@ export interface Manifest {
|
|
|
14
14
|
files: Record<string, ManifestEntry>;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* Read the manifest file from `destination`.
|
|
18
|
-
* file is missing or unparseable
|
|
19
|
-
*
|
|
17
|
+
* Read the manifest file from `destination`.
|
|
18
|
+
* Returns `undefined` when the file is missing or unparseable.
|
|
19
|
+
* Callers fall back to a clean provision in that case,
|
|
20
|
+
* since no manifest means no incremental state to diff against.
|
|
20
21
|
*/
|
|
21
22
|
export declare function readManifest(destination: string): Promise<Manifest | undefined>;
|
|
22
23
|
export declare function writeManifest(destination: string, manifest: Manifest): Promise<void>;
|
package/dist/Manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Manifest.d.ts","sourceRoot":"","sources":["../src/Manifest.ts"],"names":[],"mappings":"AAGA,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"Manifest.d.ts","sourceRoot":"","sources":["../src/Manifest.ts"],"names":[],"mappings":"AAGA,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,gCAAgC,CAAA;AAE9D,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;CACrC;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAQrF;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1F"}
|
package/dist/Manifest.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
/** Filename written inside `destination` to track per-file sync state. */
|
|
4
|
-
export const MANIFEST_FILENAME = '.braid-manifest.json';
|
|
4
|
+
export const MANIFEST_FILENAME = '.braid-gdrive-manifest.json';
|
|
5
5
|
/**
|
|
6
|
-
* Read the manifest file from `destination`.
|
|
7
|
-
* file is missing or unparseable
|
|
8
|
-
*
|
|
6
|
+
* Read the manifest file from `destination`.
|
|
7
|
+
* Returns `undefined` when the file is missing or unparseable.
|
|
8
|
+
* Callers fall back to a clean provision in that case,
|
|
9
|
+
* since no manifest means no incremental state to diff against.
|
|
9
10
|
*/
|
|
10
11
|
export async function readManifest(destination) {
|
|
11
12
|
try {
|
package/dist/Manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Manifest.js","sourceRoot":"","sources":["../src/Manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,0EAA0E;AAC1E,MAAM,CAAC,MAAM,iBAAiB,GAAG,
|
|
1
|
+
{"version":3,"file":"Manifest.js","sourceRoot":"","sources":["../src/Manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,0EAA0E;AAC1E,MAAM,CAAC,MAAM,iBAAiB,GAAG,6BAA6B,CAAA;AAiB9D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB;IACpD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAA;QACzE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAA;IACpC,CAAC;IACD,MAAM,CAAC;QACL,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,QAAkB;IACzE,MAAM,SAAS,CACb,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,EACpC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EACxC,OAAO,CACR,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
1
|
+
export * from './DriveClient.js';
|
|
2
|
+
export * from './GoogleDriveSourceLoaderPlugin.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,oCAAoC,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
1
|
+
export * from './DriveClient.js';
|
|
2
|
+
export * from './GoogleDriveSourceLoaderPlugin.js';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,oCAAoC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@braidhq/source-loader-gdrive",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"description": "Google Drive source-loader plugin for Braid. Export docs from Google Drive, requires OAuth on first use.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -10,40 +10,35 @@
|
|
|
10
10
|
"directory": "packages/source-loader-gdrive"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
|
-
".":
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
}
|
|
14
17
|
},
|
|
15
|
-
"main": "./
|
|
16
|
-
"types": "./
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
17
20
|
"files": [
|
|
18
21
|
"README.md",
|
|
19
22
|
"dist"
|
|
20
23
|
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"build": "tsc -p tsconfig.json",
|
|
23
|
-
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
|
|
24
|
-
"test": "vitest run",
|
|
25
|
-
"clean": "rm -rf dist .turbo *.tsbuildinfo coverage"
|
|
26
|
-
},
|
|
27
24
|
"dependencies": {
|
|
28
|
-
"
|
|
29
|
-
"@braidhq/
|
|
30
|
-
"@braidhq/
|
|
31
|
-
"
|
|
25
|
+
"zod": "^4.2.1",
|
|
26
|
+
"@braidhq/core": "0.2.1",
|
|
27
|
+
"@braidhq/schema": "0.2.1",
|
|
28
|
+
"@braidhq/sdk": "0.2.1"
|
|
32
29
|
},
|
|
33
30
|
"devDependencies": {
|
|
34
|
-
"@braidhq/test-utils": "workspace:*",
|
|
35
31
|
"typescript": "^6.0.3",
|
|
36
|
-
"vitest": "^4.1.
|
|
32
|
+
"vitest": "^4.1.10",
|
|
33
|
+
"@braidhq/test-utils": "0.2.1"
|
|
37
34
|
},
|
|
38
35
|
"publishConfig": {
|
|
39
|
-
"access": "public"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
}
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc -p tsconfig.json",
|
|
40
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
|
|
41
|
+
"test": "vitest run --coverage",
|
|
42
|
+
"clean": "rm -rf dist .turbo *.tsbuildinfo coverage"
|
|
48
43
|
}
|
|
49
|
-
}
|
|
44
|
+
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import type { SourceLoaderContext, SourceLoaderPlugin } from '@braidhq/core';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { type DriveFileMetadata, type FetchFn } from './driveClient.js';
|
|
4
|
-
export declare const GoogleDriveLoaderConfig: z.ZodObject<{
|
|
5
|
-
/**
|
|
6
|
-
* Drive folder id (the long alphanumeric in the URL). Reject the alias
|
|
7
|
-
* `root` outright: it expands to the user's entire My Drive and would
|
|
8
|
-
* mirror every file they own, which is almost never what someone wants
|
|
9
|
-
* from an "intent docs" source and easily costs gigabytes + minutes.
|
|
10
|
-
* Make people pick a specific subfolder.
|
|
11
|
-
*/
|
|
12
|
-
folderId: z.ZodEffects<z.ZodString, string, string>;
|
|
13
|
-
/**
|
|
14
|
-
* Whether to traverse subfolders. Default true. Subfolder hierarchy
|
|
15
|
-
* is NOT preserved on disk; every matching doc lives in its own dir
|
|
16
|
-
* directly under `destination/`. Disable to limit to immediate
|
|
17
|
-
* children of `folderId`.
|
|
18
|
-
*/
|
|
19
|
-
recursive: z.ZodDefault<z.ZodBoolean>;
|
|
20
|
-
/**
|
|
21
|
-
* Optional regex (string). When set, only docs whose *Drive title*
|
|
22
|
-
* matches this pattern are downloaded. Subfolders are still traversed.
|
|
23
|
-
*/
|
|
24
|
-
include: z.ZodOptional<z.ZodString>;
|
|
25
|
-
/**
|
|
26
|
-
* Optional regex (string). When set, docs whose title matches are
|
|
27
|
-
* skipped. Evaluated after `include`, so exclude takes priority.
|
|
28
|
-
*/
|
|
29
|
-
exclude: z.ZodOptional<z.ZodString>;
|
|
30
|
-
}, "strip", z.ZodTypeAny, {
|
|
31
|
-
folderId: string;
|
|
32
|
-
recursive: boolean;
|
|
33
|
-
exclude?: string | undefined;
|
|
34
|
-
include?: string | undefined;
|
|
35
|
-
}, {
|
|
36
|
-
folderId: string;
|
|
37
|
-
exclude?: string | undefined;
|
|
38
|
-
recursive?: boolean | undefined;
|
|
39
|
-
include?: string | undefined;
|
|
40
|
-
}>;
|
|
41
|
-
export type GoogleDriveLoaderConfig = z.infer<typeof GoogleDriveLoaderConfig>;
|
|
42
|
-
export interface GoogleDriveLoaderDeps {
|
|
43
|
-
/**
|
|
44
|
-
* Resolve a fresh access token for a given `(workspaceId, sourceId)`.
|
|
45
|
-
* The composition root implements this against its OAuth refresh-token
|
|
46
|
-
* store; tests can return a static token regardless of context.
|
|
47
|
-
*/
|
|
48
|
-
resolveAccessToken: (context: SourceLoaderContext) => Promise<string>;
|
|
49
|
-
/** Inject for tests. Real callers use globalThis.fetch. */
|
|
50
|
-
fetchFn?: FetchFn;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Build a Google Drive source loader. Walks a Drive folder, exports every
|
|
54
|
-
* Google Doc inside as markdown, extracts inlined base64 images into
|
|
55
|
-
* sibling files, and lays everything out as:
|
|
56
|
-
*
|
|
57
|
-
* <destination>/
|
|
58
|
-
* <sanitised-doc-title>/
|
|
59
|
-
* index.md
|
|
60
|
-
* <image-label>.png (one per inlined image)
|
|
61
|
-
* <sanitised-doc-title-2>/
|
|
62
|
-
* index.md
|
|
63
|
-
* .braid-manifest.json (sync state)
|
|
64
|
-
*
|
|
65
|
-
* Drive folder hierarchy is NOT preserved on disk; every matched doc
|
|
66
|
-
* is flattened into a sibling directory under `destination/`. Two docs
|
|
67
|
-
* with the same sanitised title will collide; rename one in Drive to
|
|
68
|
-
* disambiguate.
|
|
69
|
-
*
|
|
70
|
-
* Out of scope (intentional): Google Sheets, Slides, Drawings, Forms,
|
|
71
|
-
* and standalone binaries. Mirrors redoc's PRD-focused workflow. If you
|
|
72
|
-
* need spreadsheets / slide decks, ingest them through a different
|
|
73
|
-
* source-loader plugin.
|
|
74
|
-
*/
|
|
75
|
-
export declare function createGoogleDriveLoader(deps: GoogleDriveLoaderDeps): SourceLoaderPlugin;
|
|
76
|
-
/** Note: the helper used by DriveClient.exportDoc returns Buffer. */
|
|
77
|
-
export type { DriveFileMetadata, FetchFn };
|
|
78
|
-
//# sourceMappingURL=GoogleDriveLoader.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GoogleDriveLoader.d.ts","sourceRoot":"","sources":["../src/GoogleDriveLoader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAK5E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAe,KAAK,iBAAiB,EAAE,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAA;AA2BpF,eAAO,MAAM,uBAAuB;IAClC;;;;;;OAMG;;IAMH;;;;;OAKG;;IAEH;;;OAGG;;IAEH;;;OAGG;;;;;;;;;;;;EAEH,CAAA;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAE7E,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,kBAAkB,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACrE,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAaD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,kBAAkB,CAgHvF;AA8GD,qEAAqE;AACrE,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GoogleDriveLoader.js","sourceRoot":"","sources":["../src/GoogleDriveLoader.ts"],"names":[],"mappings":"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"}
|