@divizend/scratch-core 1.0.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.
Files changed (61) hide show
  1. package/basic/demo.ts +11 -0
  2. package/basic/index.ts +490 -0
  3. package/core/Auth.ts +63 -0
  4. package/core/Currency.ts +16 -0
  5. package/core/Env.ts +186 -0
  6. package/core/Fragment.ts +43 -0
  7. package/core/FragmentServingMode.ts +37 -0
  8. package/core/JsonSchemaValidator.ts +173 -0
  9. package/core/ProjectRoot.ts +76 -0
  10. package/core/Scratch.ts +44 -0
  11. package/core/URI.ts +203 -0
  12. package/core/Universe.ts +406 -0
  13. package/core/index.ts +27 -0
  14. package/gsuite/core/GSuite.ts +237 -0
  15. package/gsuite/core/GSuiteAdmin.ts +81 -0
  16. package/gsuite/core/GSuiteOrgConfig.ts +47 -0
  17. package/gsuite/core/GSuiteUser.ts +115 -0
  18. package/gsuite/core/index.ts +21 -0
  19. package/gsuite/documents/Document.ts +173 -0
  20. package/gsuite/documents/Documents.ts +52 -0
  21. package/gsuite/documents/index.ts +19 -0
  22. package/gsuite/drive/Drive.ts +118 -0
  23. package/gsuite/drive/DriveFile.ts +147 -0
  24. package/gsuite/drive/index.ts +19 -0
  25. package/gsuite/gmail/Gmail.ts +430 -0
  26. package/gsuite/gmail/GmailLabel.ts +55 -0
  27. package/gsuite/gmail/GmailMessage.ts +428 -0
  28. package/gsuite/gmail/GmailMessagePart.ts +298 -0
  29. package/gsuite/gmail/GmailThread.ts +97 -0
  30. package/gsuite/gmail/index.ts +5 -0
  31. package/gsuite/gmail/utils.ts +184 -0
  32. package/gsuite/index.ts +28 -0
  33. package/gsuite/spreadsheets/CellValue.ts +71 -0
  34. package/gsuite/spreadsheets/Sheet.ts +128 -0
  35. package/gsuite/spreadsheets/SheetValues.ts +12 -0
  36. package/gsuite/spreadsheets/Spreadsheet.ts +76 -0
  37. package/gsuite/spreadsheets/Spreadsheets.ts +52 -0
  38. package/gsuite/spreadsheets/index.ts +25 -0
  39. package/gsuite/spreadsheets/utils.ts +52 -0
  40. package/gsuite/utils.ts +104 -0
  41. package/http-server/HttpServer.ts +110 -0
  42. package/http-server/NativeHttpServer.ts +1084 -0
  43. package/http-server/index.ts +3 -0
  44. package/http-server/middlewares/01-cors.ts +33 -0
  45. package/http-server/middlewares/02-static.ts +67 -0
  46. package/http-server/middlewares/03-request-logger.ts +159 -0
  47. package/http-server/middlewares/04-body-parser.ts +54 -0
  48. package/http-server/middlewares/05-no-cache.ts +23 -0
  49. package/http-server/middlewares/06-response-handler.ts +39 -0
  50. package/http-server/middlewares/handler-wrapper.ts +250 -0
  51. package/http-server/middlewares/index.ts +37 -0
  52. package/http-server/middlewares/types.ts +27 -0
  53. package/index.ts +24 -0
  54. package/package.json +37 -0
  55. package/queue/EmailQueue.ts +228 -0
  56. package/queue/RateLimiter.ts +54 -0
  57. package/queue/index.ts +2 -0
  58. package/resend/Resend.ts +190 -0
  59. package/resend/index.ts +11 -0
  60. package/s2/S2.ts +335 -0
  61. package/s2/index.ts +11 -0
@@ -0,0 +1,237 @@
1
+ /**
2
+ * GSuite - Google Workspace Integration Manager
3
+ *
4
+ * The GSuite class manages integration with Google Workspace (formerly G Suite)
5
+ * services including Gmail, Google Drive, Google Sheets, and Google Docs.
6
+ *
7
+ * This class handles:
8
+ * - Multi-organization Google Workspace setup
9
+ * - Service account authentication and JWT management
10
+ * - User directory management and domain validation
11
+ * - Centralized access to all Google Workspace APIs
12
+ *
13
+ * The system supports multiple organizations, each with their own service account
14
+ * credentials, enabling enterprise-scale deployments with proper isolation.
15
+ *
16
+ * @class GSuite
17
+ * @version 1.0.0
18
+ * @author Divizend GmbH
19
+ */
20
+
21
+ import { JWT } from "google-auth-library";
22
+ import { admin_directory_v1 } from "googleapis";
23
+ import { GSuiteOrgConfig, GSuiteUser, Universe } from "../..";
24
+ import { parseEnvGroup } from "../../core/Env";
25
+
26
+ export class GSuite {
27
+ /**
28
+ * Creates a new GSuite instance
29
+ *
30
+ * @param universe - Reference to the central Universe instance
31
+ * @param orgConfigs - Configuration for each organization
32
+ * @param usersDirectory - Cached user directory data for performance
33
+ */
34
+ constructor(
35
+ private readonly universe: Universe,
36
+ private readonly orgConfigs: { [org: string]: GSuiteOrgConfig },
37
+ private readonly usersDirectory: {
38
+ [email: string]: admin_directory_v1.Schema$User;
39
+ }
40
+ ) {}
41
+
42
+ /**
43
+ * Constructs and initializes a GSuite instance
44
+ *
45
+ * This factory method performs the following initialization steps:
46
+ * 1. Parses environment variables for GCP credentials
47
+ * 2. Creates JWT authentication functions for each organization
48
+ * 3. Fetches domain and user information for each organization
49
+ * 4. Builds the user directory cache for efficient lookups
50
+ *
51
+ * Environment Variables Required:
52
+ * - GCP_CLIENT_EMAIL_<identifier>: Service account email
53
+ * - GCP_PRIVATE_KEY_<identifier>: Service account private key
54
+ * - GCP_ADMIN_USER_<identifier>: Admin user email for the organization
55
+ *
56
+ * @param universe - Reference to the central Universe instance
57
+ * @returns Promise<GSuite> - Fully initialized GSuite instance
58
+ * @throws Error if required credentials are missing or invalid
59
+ */
60
+ static async construct(universe: Universe) {
61
+ // Parse environment variables grouped by organization identifier
62
+ const gcpCreds = parseEnvGroup<
63
+ {
64
+ clientEmail: string;
65
+ privateKey: string;
66
+ adminUser: string;
67
+ }
68
+ >(
69
+ ["GCP_CLIENT_EMAIL_", "GCP_PRIVATE_KEY_", "GCP_ADMIN_USER_"],
70
+ {
71
+ propertyMap: {
72
+ "GCP_CLIENT_EMAIL_": "clientEmail",
73
+ "GCP_PRIVATE_KEY_": "privateKey",
74
+ "GCP_ADMIN_USER_": "adminUser",
75
+ },
76
+ identifierExtractor: (key: string) => {
77
+ // For "GCP_CLIENT_EMAIL_ORG1", split by "_" gives ["GCP", "CLIENT", "EMAIL", "ORG1"]
78
+ // We want the 4th segment (index 3), lowercased
79
+ const parts = key.split("_");
80
+ return parts[3]?.toLowerCase() || "";
81
+ },
82
+ errorMessage:
83
+ "No GCP credentials found. Please set GCP_CLIENT_EMAIL_<identifier>, GCP_PRIVATE_KEY_<identifier> and GCP_ADMIN_USER_<identifier> environment variables.",
84
+ }
85
+ );
86
+
87
+ const orgConfigs: {
88
+ [org: string]: GSuiteOrgConfig;
89
+ } = {};
90
+
91
+ const rawAuths: { [org: string]: (subject: string) => JWT } = {};
92
+
93
+ // Create JWT authentication functions for each organization
94
+ for (const [identifier, creds] of Object.entries(gcpCreds)) {
95
+ if (!creds.clientEmail || !creds.privateKey || !creds.adminUser) {
96
+ throw new Error(
97
+ `Missing GCP credentials for ${identifier}. Please set GCP_CLIENT_EMAIL_${identifier}, GCP_PRIVATE_KEY_${identifier} and GCP_ADMIN_USER_${identifier} environment variables.`
98
+ );
99
+ }
100
+
101
+ // Create JWT authentication with required scopes
102
+ rawAuths[identifier] = (subject: string) =>
103
+ new JWT({
104
+ email: creds.clientEmail!,
105
+ key: creds.privateKey!,
106
+ scopes: [
107
+ "https://www.googleapis.com/auth/gmail.readonly",
108
+ "https://www.googleapis.com/auth/gmail.send",
109
+ "https://www.googleapis.com/auth/gmail.modify",
110
+ "https://www.googleapis.com/auth/gmail.settings.sharing",
111
+ "https://www.googleapis.com/auth/admin.directory.user.readonly",
112
+ "https://www.googleapis.com/auth/admin.directory.domain.readonly",
113
+ "https://www.googleapis.com/auth/spreadsheets",
114
+ "https://www.googleapis.com/auth/drive",
115
+ "https://www.googleapis.com/auth/documents",
116
+ ],
117
+ subject,
118
+ });
119
+ }
120
+
121
+ // Initialize organization configurations and user directory
122
+ const usersDirectory: { [email: string]: admin_directory_v1.Schema$User } =
123
+ {};
124
+
125
+ for (const [identifier, rawAuth] of Object.entries(rawAuths)) {
126
+ const adminUser = gcpCreds[identifier]!.adminUser!;
127
+
128
+ // Create admin user instance and fetch organization data
129
+ const admin = new GSuiteUser(
130
+ universe,
131
+ rawAuth(adminUser),
132
+ usersDirectory[adminUser]!
133
+ ).admin();
134
+
135
+ // Fetch domains for the organization
136
+ const domains = await admin.getDomains();
137
+ orgConfigs[identifier] = new GSuiteOrgConfig(rawAuth, domains, adminUser);
138
+
139
+ console.warn(
140
+ `${identifier} has ${orgConfigs[identifier].domains.length} domains`
141
+ );
142
+
143
+ // Fetch and cache user directory information
144
+ const users = await admin.getUsers();
145
+ for (const user of users) {
146
+ usersDirectory[user.primaryEmail!] = user;
147
+ }
148
+
149
+ console.warn(`${identifier} has ${users.length} users`);
150
+ for (const user of users) {
151
+ console.log(user.primaryEmail);
152
+ }
153
+ }
154
+
155
+ return new GSuite(universe, orgConfigs, usersDirectory);
156
+ }
157
+
158
+ /**
159
+ * Creates a GSuiteUser instance for the specified email address
160
+ *
161
+ * This method:
162
+ * 1. Determines which organization the user belongs to based on email domain
163
+ * 2. Retrieves the appropriate authentication configuration
164
+ * 3. Fetches user directory data for the specified user
165
+ * 4. Returns a configured GSuiteUser instance with proper permissions
166
+ *
167
+ * @param email - The user's email address
168
+ * @returns GSuiteUser instance configured for the specified user
169
+ * @throws Error if the user's domain is not found or user is not in directory
170
+ */
171
+ user(email: string): GSuiteUser {
172
+ // Find the organization configuration based on email domain
173
+ const emailDomain = email.split("@")[1]!;
174
+ const orgConfig = Object.values(this.orgConfigs).find((orgConfig) =>
175
+ orgConfig.domains.some((domain) => domain.domainName === emailDomain)
176
+ );
177
+
178
+ if (!orgConfig) {
179
+ throw new Error(`Domain of ${email} not found in any organization`);
180
+ }
181
+
182
+ // Retrieve user directory data for authentication and permissions
183
+ const directoryData = this.usersDirectory[email];
184
+ if (!directoryData) {
185
+ throw new Error(`User ${email} not found in directory`);
186
+ }
187
+
188
+ // Create and return configured user instance
189
+ return new GSuiteUser(
190
+ this.universe,
191
+ orgConfig.getAuth(email),
192
+ directoryData
193
+ );
194
+ }
195
+
196
+ /**
197
+ * Checks the health of the GSuite service
198
+ * Verifies connectivity by attempting to fetch domains from the first organization
199
+ *
200
+ * @returns Promise<{ status: string; message: string; connected: boolean; organization?: string }>
201
+ */
202
+ async getHealth(): Promise<{
203
+ status: string;
204
+ message: string;
205
+ connected: boolean;
206
+ organization?: string;
207
+ }> {
208
+ try {
209
+ if (!this.orgConfigs || Object.keys(this.orgConfigs).length === 0) {
210
+ return {
211
+ status: "error",
212
+ message: "No GSuite organizations configured",
213
+ connected: false,
214
+ };
215
+ }
216
+
217
+ const firstOrg = Object.keys(this.orgConfigs)[0];
218
+ const orgConfig = this.orgConfigs[firstOrg];
219
+ const gsuiteUser = this.user(orgConfig.adminUser);
220
+ const admin = gsuiteUser.admin();
221
+ await admin.getDomains();
222
+
223
+ return {
224
+ status: "ok",
225
+ message: "Google APIs connection active",
226
+ connected: true,
227
+ organization: firstOrg,
228
+ };
229
+ } catch (error) {
230
+ return {
231
+ status: "error",
232
+ message: error instanceof Error ? error.message : "Unknown error",
233
+ connected: false,
234
+ };
235
+ }
236
+ }
237
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * GSuiteAdmin - Google Workspace Administrative Operations
3
+ *
4
+ * The GSuiteAdmin class provides administrative access to Google Workspace
5
+ * organizational settings, including domain management and user directory operations.
6
+ *
7
+ * This class handles:
8
+ * - Domain listing and validation for multi-tenant organizations
9
+ * - User directory queries for authentication and permissions
10
+ * - Administrative operations that require elevated privileges
11
+ *
12
+ * All operations are performed using the Google Admin SDK Directory API
13
+ * with the authenticated user's administrative credentials.
14
+ *
15
+ * @class GSuiteAdmin
16
+ * @version 1.0.0
17
+ * @author Divizend GmbH
18
+ */
19
+
20
+ import { google, admin_directory_v1 } from "googleapis";
21
+ import { JWT } from "google-auth-library";
22
+ import { Universe } from "../..";
23
+
24
+ export class GSuiteAdmin {
25
+ /** Google Admin SDK Directory API client instance */
26
+ private admin: admin_directory_v1.Admin;
27
+
28
+ /**
29
+ * Creates a new GSuiteAdmin instance
30
+ *
31
+ * @param universe - Reference to the central Universe instance
32
+ * @param auth - JWT authentication with administrative privileges
33
+ */
34
+ constructor(private readonly universe: Universe, private auth: JWT) {
35
+ this.admin = google.admin({ version: "directory_v1", auth: this.auth });
36
+ }
37
+
38
+ /**
39
+ * Retrieves all domains associated with the organization
40
+ *
41
+ * This method queries the Google Admin SDK to list all domains
42
+ * that belong to the authenticated user's organization. This is
43
+ * essential for multi-domain organizations and user authentication.
44
+ *
45
+ * @returns Promise<admin_directory_v1.Schema$Domains[]> - Array of domain objects
46
+ * @throws Error if no domains are found or the API call fails
47
+ */
48
+ async getDomains(): Promise<admin_directory_v1.Schema$Domains[]> {
49
+ const response = await this.admin.domains.list({
50
+ customer: "my_customer",
51
+ });
52
+
53
+ if (!response.data.domains || response.data.domains.length === 0) {
54
+ throw new Error("No domains found");
55
+ }
56
+
57
+ return response.data.domains;
58
+ }
59
+
60
+ /**
61
+ * Retrieves all users in the organization
62
+ *
63
+ * This method queries the Google Admin SDK to list all users
64
+ * that belong to the authenticated user's organization. The user
65
+ * list is used for authentication, permissions, and directory lookups.
66
+ *
67
+ * @returns Promise<admin_directory_v1.Schema$User[]> - Array of user objects
68
+ * @throws Error if no users are found or the API call fails
69
+ */
70
+ async getUsers(): Promise<admin_directory_v1.Schema$User[]> {
71
+ const response = await this.admin.users.list({
72
+ customer: "my_customer",
73
+ });
74
+
75
+ if (!response.data.users || response.data.users.length === 0) {
76
+ throw new Error("No users found");
77
+ }
78
+
79
+ return response.data.users;
80
+ }
81
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * GSuiteOrgConfig - Organization Configuration Container
3
+ *
4
+ * The GSuiteOrgConfig class holds configuration information for a specific
5
+ * Google Workspace organization, including authentication details, domain
6
+ * information, and administrative user settings.
7
+ *
8
+ * This class serves as a data container that encapsulates all the necessary
9
+ * information to authenticate and operate within a specific organization's
10
+ * Google Workspace environment.
11
+ *
12
+ * @class GSuiteOrgConfig
13
+ * @version 1.0.0
14
+ * @author Divizend GmbH
15
+ */
16
+
17
+ import { JWT } from "google-auth-library";
18
+ import { admin_directory_v1 } from "googleapis";
19
+
20
+ export class GSuiteOrgConfig {
21
+ /**
22
+ * Creates a new GSuiteOrgConfig instance
23
+ *
24
+ * @param jwt - Function that creates JWT instances for organization users
25
+ * @param domains - Array of domains associated with the organization
26
+ * @param adminUser - Email address of the administrative user for the organization
27
+ */
28
+ constructor(
29
+ public readonly jwt: (subject: string) => JWT,
30
+ public readonly domains: admin_directory_v1.Schema$Domains[],
31
+ public readonly adminUser: string
32
+ ) {}
33
+
34
+ /**
35
+ * Creates a JWT authentication instance for a specific user
36
+ *
37
+ * This method uses the organization's service account credentials
38
+ * to create a JWT token that can impersonate the specified user
39
+ * within the organization's Google Workspace environment.
40
+ *
41
+ * @param subject - The email address of the user to authenticate as
42
+ * @returns JWT instance configured for the specified user
43
+ */
44
+ getAuth(subject: string): JWT {
45
+ return this.jwt(subject);
46
+ }
47
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * GSuiteUser - Google Workspace Service Facade
3
+ *
4
+ * The GSuiteUser class provides a unified interface for accessing all Google Workspace
5
+ * services on behalf of a specific user. It acts as a facade that simplifies access
6
+ * to Gmail, Google Drive, Google Sheets, Google Docs, and administrative functions.
7
+ *
8
+ * Each GSuiteUser instance is configured with:
9
+ * - JWT authentication for the specific user
10
+ * - User directory data for permissions and metadata
11
+ * - Access to all Google Workspace APIs through service-specific classes
12
+ *
13
+ * This class implements the Facade pattern, hiding the complexity of individual
14
+ * Google Workspace APIs behind a simple, consistent interface.
15
+ *
16
+ * @class GSuiteUser
17
+ * @version 1.0.0
18
+ * @author Divizend GmbH
19
+ */
20
+
21
+ import { JWT } from "google-auth-library";
22
+ import { admin_directory_v1 } from "googleapis";
23
+ import {
24
+ Documents,
25
+ Drive,
26
+ GSuiteAdmin,
27
+ Gmail,
28
+ Spreadsheets,
29
+ Universe,
30
+ } from "../..";
31
+
32
+ export class GSuiteUser {
33
+ /**
34
+ * Creates a new GSuiteUser instance
35
+ *
36
+ * @param universe - Reference to the central Universe instance
37
+ * @param auth - JWT authentication for the specific user
38
+ * @param directoryData - User directory information and metadata
39
+ */
40
+ constructor(
41
+ private readonly universe: Universe,
42
+ public readonly auth: JWT,
43
+ public readonly directoryData: admin_directory_v1.Schema$User
44
+ ) {}
45
+
46
+ /**
47
+ * Provides access to Google Workspace administrative functions
48
+ *
49
+ * Returns a GSuiteAdmin instance that can perform administrative
50
+ * operations like managing users, domains, and organizational settings.
51
+ *
52
+ * @returns GSuiteAdmin instance for administrative operations
53
+ */
54
+ admin(): GSuiteAdmin {
55
+ return new GSuiteAdmin(this.universe, this.auth);
56
+ }
57
+
58
+ /**
59
+ * Provides access to Google Docs services
60
+ *
61
+ * Returns a Documents instance that can create, read, update,
62
+ * and delete Google Docs documents programmatically.
63
+ *
64
+ * @returns Documents instance for Google Docs operations
65
+ */
66
+ documents(): Documents {
67
+ return new Documents(this.universe, this.auth);
68
+ }
69
+
70
+ /**
71
+ * Provides access to Google Drive services
72
+ *
73
+ * Returns a Drive instance that can manage files and folders,
74
+ * handle file uploads/downloads, and manage sharing permissions.
75
+ *
76
+ * @returns Drive instance for Google Drive operations
77
+ */
78
+ drive(): Drive {
79
+ return new Drive(this.universe, this.auth);
80
+ }
81
+
82
+ /**
83
+ * Provides access to Gmail services
84
+ *
85
+ * Returns a Gmail instance that can read emails, send messages,
86
+ * manage labels, and handle email processing workflows.
87
+ *
88
+ * @returns Gmail instance for Gmail operations
89
+ */
90
+ gmail(): Gmail {
91
+ return new Gmail(this.universe, this.auth);
92
+ }
93
+
94
+ /**
95
+ * Provides access to Google Sheets services
96
+ *
97
+ * Returns a Spreadsheets instance that can read/write spreadsheet
98
+ * data, manage sheets, and perform data analysis operations.
99
+ *
100
+ * @returns Spreadsheets instance for Google Sheets operations
101
+ */
102
+ spreadsheets(): Spreadsheets {
103
+ return new Spreadsheets(this.universe, this.auth);
104
+ }
105
+
106
+ /**
107
+ * The email address of the authenticated user
108
+ *
109
+ * This property provides convenient access to the user's email
110
+ * address for use in API calls and logging.
111
+ */
112
+ get email() {
113
+ return this.auth.subject;
114
+ }
115
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * GSuite Core Module - Foundation Components
3
+ *
4
+ * This module contains the core building blocks for Google Workspace integration:
5
+ * - GSuite: Main integration manager for multi-organization setups
6
+ * - GSuiteUser: User-specific service access facade
7
+ * - GSuiteAdmin: Administrative operations and directory management
8
+ * - GSuiteOrgConfig: Organization configuration and authentication
9
+ *
10
+ * These components provide the foundation for all Google Workspace services
11
+ * including authentication, user management, and organizational structure.
12
+ *
13
+ * @module GSuiteCore
14
+ * @version 1.0.0
15
+ * @author Divizend GmbH
16
+ */
17
+
18
+ export * from "./GSuite";
19
+ export * from "./GSuiteUser";
20
+ export * from "./GSuiteAdmin";
21
+ export * from "./GSuiteOrgConfig";
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Document - Individual Google Document Operations
3
+ *
4
+ * The Document class represents a single Google Docs document and provides
5
+ * methods for content manipulation, placeholder replacement, and document
6
+ * editing operations.
7
+ *
8
+ * Key Features:
9
+ * - Document metadata and properties access
10
+ * - Placeholder text replacement and customization
11
+ * - Batch update operations for efficiency
12
+ * - Integration with Google Docs API
13
+ *
14
+ * This class enables automated document generation workflows by providing
15
+ * programmatic access to document content and editing capabilities.
16
+ *
17
+ * @class Document
18
+ * @version 1.0.0
19
+ * @author Divizend GmbH
20
+ */
21
+
22
+ import { docs_v1 } from "googleapis";
23
+ import { Documents } from ".";
24
+ import TurndownService from "turndown";
25
+
26
+ /**
27
+ * Mapping of placeholder keys to replacement values
28
+ *
29
+ * This type defines the structure for placeholder replacement operations,
30
+ * where keys represent placeholder text (e.g., "{{DATE}}") and values
31
+ * represent the content to replace them with.
32
+ */
33
+ export type DocumentPlaceholderReplacements = { [key: string]: string };
34
+
35
+ export class Document {
36
+ /**
37
+ * Creates a new Document instance
38
+ *
39
+ * @param docs - Reference to the Documents service instance
40
+ * @param document - Raw Google Docs API document data
41
+ */
42
+ constructor(
43
+ private readonly docs: Documents,
44
+ public readonly document: docs_v1.Schema$Document
45
+ ) {}
46
+
47
+ /**
48
+ * Constructs a Document instance from a document ID
49
+ *
50
+ * This factory method fetches the document content from Google Docs
51
+ * and creates a Document instance ready for operations.
52
+ *
53
+ * @param docs - Documents service instance
54
+ * @param documentId - Google Docs document ID
55
+ * @returns Promise<Document> - Initialized document instance
56
+ */
57
+ static async construct(docs: Documents, documentId: string) {
58
+ const document = await docs.docs.documents.get({ documentId });
59
+ return new Document(docs, document.data);
60
+ }
61
+
62
+ /**
63
+ * Gets the unique identifier for this document
64
+ *
65
+ * The document ID is used for all Google Docs API operations
66
+ * and can be used to reference this document in other services.
67
+ */
68
+ get id(): string {
69
+ return this.document.documentId!;
70
+ }
71
+
72
+ /**
73
+ * Replaces placeholder text in the document with specified values
74
+ *
75
+ * This method performs batch replacement of placeholder text (e.g., "{{DATE}}")
76
+ * with actual values. It's commonly used in template-based document
77
+ * generation workflows to customize document content automatically.
78
+ *
79
+ * The method uses the Google Docs batchUpdate API for efficiency,
80
+ * processing all replacements in a single API call.
81
+ *
82
+ * @param replacements - Object mapping placeholder keys to replacement values
83
+ * @returns Promise containing the batch update response
84
+ * @throws Error if the batch update operation fails
85
+ */
86
+ async replacePlaceholders(replacements: DocumentPlaceholderReplacements) {
87
+ return this.docs.docs.documents.batchUpdate({
88
+ documentId: this.id,
89
+ requestBody: {
90
+ requests: Object.entries(replacements).map(([key, value]) => ({
91
+ replaceAllText: {
92
+ containsText: { text: `{{${key}}}`, matchCase: true },
93
+ replaceText: value,
94
+ },
95
+ })),
96
+ },
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Exports the document in the specified format
102
+ *
103
+ * This method uses the Google Drive API to export the document
104
+ * in the requested format, returning it exactly as exported by the API.
105
+ *
106
+ * @param mimeType - MIME type for export (e.g., "text/html", "text/plain")
107
+ * @returns Promise<string> - Document content in the requested format
108
+ * @throws Error if export fails
109
+ */
110
+ async export(mimeType: string): Promise<string> {
111
+ // Get the Drive service from the Documents instance
112
+ const userEmail = this.docs.auth.subject!;
113
+ const gsuiteUser = this.docs.universe.gsuite.user(userEmail);
114
+ const drive = gsuiteUser.drive();
115
+
116
+ // Export via Drive API
117
+ const buffer = await drive.drive.files.export(
118
+ {
119
+ fileId: this.id,
120
+ mimeType,
121
+ },
122
+ { responseType: "arraybuffer" }
123
+ );
124
+
125
+ const content = Buffer.from(buffer.data as any).toString("utf-8");
126
+
127
+ // Return the content exactly as exported by the API
128
+ return content;
129
+ }
130
+
131
+ /**
132
+ * Exports the document as HTML
133
+ *
134
+ * This method uses the Google Drive API to export the document
135
+ * as HTML directly, returning it exactly as exported by the API.
136
+ *
137
+ * @returns Promise<string> - Document content as HTML
138
+ * @throws Error if export fails
139
+ */
140
+ async toHTML(): Promise<string> {
141
+ return this.export("text/html");
142
+ }
143
+
144
+ /**
145
+ * Exports the document as plain text
146
+ *
147
+ * This method uses the Google Drive API to export the document
148
+ * as plain text directly, returning it exactly as exported by the API.
149
+ *
150
+ * @returns Promise<string> - Document content as plain text
151
+ * @throws Error if export fails
152
+ */
153
+ async toPlainText(): Promise<string> {
154
+ return this.export("text/plain");
155
+ }
156
+
157
+ /**
158
+ * Exports the document as Markdown
159
+ *
160
+ * This method exports the document as HTML first, then converts it
161
+ * to Markdown using Turndown. This provides a clean Markdown representation
162
+ * of the document content.
163
+ *
164
+ * @returns Promise<string> - Document content as Markdown
165
+ * @throws Error if export or conversion fails
166
+ */
167
+ async toMarkdown(): Promise<string> {
168
+ const html = await this.toHTML();
169
+ const turndownService = new TurndownService();
170
+ turndownService.remove(["script", "style"]);
171
+ return turndownService.turndown(html).trim();
172
+ }
173
+ }