@blinkk/root-cms 3.0.1 → 3.0.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 (161) hide show
  1. package/dist/app.js +5 -5
  2. package/dist/{chunk-KGAUXTJ6.js → chunk-7Z5IRD2G.js} +176 -83
  3. package/dist/{chunk-2BSW7SIH.js → chunk-N4K6ICFR.js} +4 -4
  4. package/dist/{chunk-BGTUWIV6.js → chunk-PNLLZXVY.js} +4 -4
  5. package/dist/{chunk-C245C557.js → chunk-RXWDB3K4.js} +3 -3
  6. package/dist/{chunk-XLX37FRL.js → chunk-TEKMLYXS.js} +3 -4
  7. package/dist/cli/cli.d.ts +12 -0
  8. package/dist/cli/docs.d.ts +49 -0
  9. package/dist/cli/export.d.ts +11 -0
  10. package/dist/cli/generate-types.d.ts +6 -0
  11. package/dist/cli/import.d.ts +13 -0
  12. package/dist/cli/init-firebase.d.ts +7 -0
  13. package/dist/cli/utils.d.ts +27 -0
  14. package/dist/cli.js +10 -10
  15. package/dist/client.js +1 -1
  16. package/dist/core/ai-tools.d.ts +156 -0
  17. package/dist/core/ai.d.ts +330 -0
  18. package/dist/core/api.d.ts +21 -0
  19. package/dist/core/app.d.ts +16 -0
  20. package/dist/core/checks-translations.d.ts +13 -0
  21. package/dist/core/checks.d.ts +48 -0
  22. package/dist/core/client.d.ts +715 -0
  23. package/dist/core/core.d.ts +5 -0
  24. package/dist/core/cron.d.ts +19 -0
  25. package/dist/core/csv.d.ts +5 -0
  26. package/dist/core/functions.d.ts +9 -0
  27. package/dist/core/plugin.d.ts +357 -0
  28. package/dist/{project.d.ts → core/project.d.ts} +8 -12
  29. package/dist/core/richtext.d.ts +101 -0
  30. package/dist/{core.d.ts → core/route.d.ts} +13 -66
  31. package/dist/core/runtime.d.ts +46 -0
  32. package/dist/{schema-Db_xODoi.d.ts → core/schema.d.ts} +47 -100
  33. package/dist/core/search-extract.d.ts +70 -0
  34. package/dist/core/search-index.d.ts +182 -0
  35. package/dist/core/search-query.d.ts +68 -0
  36. package/dist/core/security.d.ts +6 -0
  37. package/dist/core/server-version.d.ts +5 -0
  38. package/dist/core/services-notifications.d.ts +57 -0
  39. package/dist/core/services.d.ts +44 -0
  40. package/dist/core/sse.d.ts +10 -0
  41. package/dist/core/translations-manager.d.ts +187 -0
  42. package/dist/core/translations.d.ts +83 -0
  43. package/dist/core/url-safety.d.ts +19 -0
  44. package/dist/core/validation.d.ts +30 -0
  45. package/dist/core/values.d.ts +9 -0
  46. package/dist/core/versions.d.ts +48 -0
  47. package/dist/core.js +1 -1
  48. package/dist/edit-M4PN4SGX.js +7 -0
  49. package/dist/functions.js +4 -4
  50. package/dist/{generate-types-SPV7I3A5.js → generate-types-JWIG4QVI.js} +1 -1
  51. package/dist/plugin.js +124 -129
  52. package/dist/shared/marshal.d.ts +68 -0
  53. package/dist/shared/objects.d.ts +9 -0
  54. package/dist/shared/richtext.d.ts +74 -0
  55. package/dist/shared/safe-json.d.ts +11 -0
  56. package/dist/shared/sanitize.d.ts +12 -0
  57. package/dist/shared/slug.d.ts +19 -0
  58. package/dist/shared/sse.d.ts +16 -0
  59. package/dist/shared/strings.d.ts +23 -0
  60. package/dist/ui/AIPage-2LUC2PWC.js +1 -0
  61. package/dist/ui/AssetsPage-PODV4QAB.js +1 -0
  62. package/dist/ui/CollectionPage-4DMKW5YB.js +1 -0
  63. package/dist/ui/ComparePage-JMJE5A5Y.js +1 -0
  64. package/dist/ui/DataPage-MVLZT2BU.js +1 -0
  65. package/dist/ui/DataSourcePage-4RPBXRI2.js +1 -0
  66. package/dist/ui/DocTranslationsPage-XJSPKGVX.js +1 -0
  67. package/dist/ui/DocumentPage-R2PVNG24.js +1 -0
  68. package/dist/ui/EditDataSourcePage-3SHAARNL.js +1 -0
  69. package/dist/ui/EditReleasePage-G5VW2OGW.js +1 -0
  70. package/dist/ui/ImageEditorDialog-4H665KK2.js +81 -0
  71. package/dist/ui/ImageEditorDialog-4H665KK2.js.LEGAL.txt +17 -0
  72. package/dist/ui/LogsPage-K6KYEG2P.js +1 -0
  73. package/dist/ui/NewDataSourcePage-O2VQEOJG.js +1 -0
  74. package/dist/ui/NewReleasePage-RSVS32RZ.js +1 -0
  75. package/dist/ui/NotFoundPage-ZYD5ILG6.js +1 -0
  76. package/dist/ui/ProjectPage-X3YQBWL4.js +1 -0
  77. package/dist/ui/ReleasePage-FJHHXNNB.js +1 -0
  78. package/dist/ui/ReleasesPage-VGWIBNEZ.js +1 -0
  79. package/dist/ui/SettingsPage-C4RXOQ6T.js +1 -0
  80. package/dist/ui/SidebarToolsPage-ZBOKPEMP.js +1 -0
  81. package/dist/ui/TaskPage-BQ4OX5WN.js +1 -0
  82. package/dist/ui/TasksPage-3IGQYVYS.js +1 -0
  83. package/dist/ui/TranslationsArbPage-GGHCWPQL.js +2 -0
  84. package/dist/ui/TranslationsEditPage-E2BCMKYV.js +1 -0
  85. package/dist/ui/TranslationsPage-MC4O4ZNI.js +162 -0
  86. package/dist/ui/ai-tools-5E5ELLZX.js +1 -0
  87. package/dist/ui/chunk-3IYZCUPI.js +1 -0
  88. package/dist/ui/chunk-4KE2SZKH.js +1 -0
  89. package/dist/ui/chunk-4W73RW5I.js +1 -0
  90. package/dist/ui/chunk-54DVDYU6.js +1 -0
  91. package/dist/ui/chunk-5MV6XVGA.js +1 -0
  92. package/dist/ui/chunk-62UWGWON.js +1 -0
  93. package/dist/ui/chunk-6IFGKSIE.js +1 -0
  94. package/dist/ui/chunk-767BAQ53.js +1 -0
  95. package/dist/ui/chunk-AFWBSIPL.js +1 -0
  96. package/dist/ui/chunk-AL3TN2KI.js +1 -0
  97. package/dist/ui/chunk-B6BLDN24.js +141 -0
  98. package/dist/ui/chunk-B6BLDN24.js.LEGAL.txt +106 -0
  99. package/dist/ui/chunk-BZIRGB4W.js +1 -0
  100. package/dist/ui/chunk-C5NH23G4.js +3 -0
  101. package/dist/ui/chunk-CGCKJFL4.js +1 -0
  102. package/dist/ui/chunk-DEGMKEHP.js +1 -0
  103. package/dist/ui/chunk-DTMZLUNY.js +15 -0
  104. package/dist/ui/chunk-DTMZLUNY.js.LEGAL.txt +237 -0
  105. package/dist/ui/chunk-DUJYIOLE.js +5 -0
  106. package/dist/ui/chunk-E2RCCK2T.js +1 -0
  107. package/dist/ui/chunk-EGEB6N4J.js +22 -0
  108. package/dist/ui/chunk-EGEB6N4J.js.LEGAL.txt +1059 -0
  109. package/dist/ui/chunk-GXSAEPU3.js +1 -0
  110. package/dist/ui/chunk-HHMG665Z.js +1 -0
  111. package/dist/ui/chunk-HKINZLMW.js +84 -0
  112. package/dist/ui/chunk-HLMBCVRX.js +1 -0
  113. package/dist/ui/chunk-HRGYNHZ3.js +1 -0
  114. package/dist/ui/chunk-I6ICVKEC.js +1 -0
  115. package/dist/ui/chunk-IU36W2TB.js +1 -0
  116. package/dist/ui/chunk-JDW4UORS.js +1 -0
  117. package/dist/ui/chunk-JHBAMPGB.js +1 -0
  118. package/dist/ui/chunk-JYFLU7DM.js +19 -0
  119. package/dist/ui/chunk-JZFTZ4X4.js +87 -0
  120. package/dist/ui/chunk-JZFTZ4X4.js.LEGAL.txt +9 -0
  121. package/dist/ui/chunk-KFAZBEPV.js +1 -0
  122. package/dist/ui/chunk-KKEWCXVV.js +1 -0
  123. package/dist/ui/chunk-KUCVLANF.js +1 -0
  124. package/dist/ui/chunk-KYDOSLTO.js +1 -0
  125. package/dist/ui/chunk-L4RHGQUG.js +1 -0
  126. package/dist/ui/chunk-MDUBCXU2.js +1 -0
  127. package/dist/ui/chunk-NXQVLOTK.js +1 -0
  128. package/dist/ui/chunk-NZHF733K.js +7 -0
  129. package/dist/ui/chunk-NZHF733K.js.LEGAL.txt +146 -0
  130. package/dist/ui/chunk-ONTGW2VA.js +1 -0
  131. package/dist/ui/chunk-ORXEMIQC.js +1 -0
  132. package/dist/ui/chunk-PHBMVORG.js +1 -0
  133. package/dist/ui/chunk-PJA7YP4A.js +1 -0
  134. package/dist/ui/chunk-PVAE643M.js +1 -0
  135. package/dist/ui/chunk-PWKJDYE2.js +1 -0
  136. package/dist/ui/chunk-RSVO46S3.js +1 -0
  137. package/dist/ui/chunk-SKEP5WYH.js +10 -0
  138. package/dist/ui/chunk-SKEP5WYH.js.LEGAL.txt +176 -0
  139. package/dist/ui/chunk-SQRKKWRG.js +3 -0
  140. package/dist/ui/chunk-UEON4JAT.js +1 -0
  141. package/dist/ui/chunk-V7S4IAGB.js +1 -0
  142. package/dist/ui/chunk-VMT7JFAM.js +1 -0
  143. package/dist/ui/chunk-W3BJ2EZX.js +1 -0
  144. package/dist/ui/chunk-W3HIZQ4Z.js +1 -0
  145. package/dist/ui/chunk-X2WHBGTP.js +1 -0
  146. package/dist/ui/chunk-XOQ3KDSR.js +3 -0
  147. package/dist/ui/chunk-YDO2EDVY.js +1 -0
  148. package/dist/ui/chunk-YFA6U2CV.js +1 -0
  149. package/dist/ui/gcs-L33FIRZU.js +1 -0
  150. package/dist/ui/prerender-Q4YSDCPB.js +1 -0
  151. package/dist/ui/signin.js +1 -1
  152. package/dist/ui/ui.css +1 -1
  153. package/dist/ui/ui.js +1 -630
  154. package/dist/ui/ui.js.LEGAL.txt +19 -732
  155. package/package.json +20 -20
  156. package/dist/client-1puwLgNx.d.ts +0 -1552
  157. package/dist/client.d.ts +0 -5
  158. package/dist/edit-MT4B37QK.js +0 -7
  159. package/dist/functions.d.ts +0 -13
  160. package/dist/plugin.d.ts +0 -5
  161. package/dist/richtext.d.ts +0 -104
@@ -0,0 +1,715 @@
1
+ import { type RootConfig } from '@blinkk/root';
2
+ import { App } from 'firebase-admin/app';
3
+ import { Firestore, Query, Timestamp, WriteBatch } from 'firebase-admin/firestore';
4
+ import { CMSPlugin } from './plugin.js';
5
+ import { Collection } from './schema.js';
6
+ import { TranslationsManager } from './translations-manager.js';
7
+ export interface Doc<Fields = any> {
8
+ /** The id of the doc, e.g. "Pages/foo-bar". */
9
+ id: string;
10
+ /** The collection id of the doc, e.g. "Pages". */
11
+ collection: string;
12
+ /** The slug of the doc, e.g. "foo-bar". */
13
+ slug: string;
14
+ sys: {
15
+ createdAt: number;
16
+ createdBy: string;
17
+ modifiedAt: number;
18
+ modifiedBy: string;
19
+ firstPublishedAt?: number;
20
+ firstPublishedBy?: string;
21
+ publishedAt?: number;
22
+ publishedBy?: string;
23
+ publishingLocked: {
24
+ lockedAt: string;
25
+ lockedBy: string;
26
+ reason: string;
27
+ until?: Timestamp;
28
+ };
29
+ locales?: string[];
30
+ };
31
+ fields: Fields;
32
+ }
33
+ export type DocMode = 'draft' | 'published';
34
+ export type UserRole = 'ADMIN' | 'EDITOR' | 'CONTRIBUTOR' | 'VIEWER';
35
+ export type HttpMethod = 'GET' | 'POST';
36
+ export type CronUnit = 'minutes' | 'hours' | 'days';
37
+ export interface DataSourceCron {
38
+ enabled: boolean;
39
+ interval: number;
40
+ unit: CronUnit;
41
+ autoPublish?: boolean;
42
+ }
43
+ export interface DataSource {
44
+ id: string;
45
+ description?: string;
46
+ type: 'http' | 'gsheet';
47
+ url: string;
48
+ /**
49
+ * Currently only used by gsheet. `array` returns the sheet as an array of
50
+ * arrays, `map` returns the sheet as an array of objects.
51
+ */
52
+ dataFormat?: 'array' | 'map';
53
+ /**
54
+ * Options for HTTP requests.
55
+ */
56
+ httpOptions?: {
57
+ method: HttpMethod;
58
+ headers?: Record<string, string>;
59
+ body?: string;
60
+ };
61
+ cron?: DataSourceCron;
62
+ createdAt: Timestamp;
63
+ createdBy: string;
64
+ syncedAt?: Timestamp;
65
+ syncedBy?: string;
66
+ publishedAt?: Timestamp;
67
+ publishedBy?: string;
68
+ archivedAt?: Timestamp;
69
+ archivedBy?: string;
70
+ }
71
+ export interface DataSourceData<T = any> {
72
+ dataSource: DataSource;
73
+ data: T;
74
+ /** Optional list of column headers (for gsheet sources). */
75
+ headers?: string[];
76
+ }
77
+ export type DataSourceMode = 'draft' | 'published';
78
+ export interface GetDocOptions {
79
+ /** Mode, either "draft" or "published". */
80
+ mode: DocMode;
81
+ }
82
+ export interface SetDocOptions {
83
+ /** Mode, either "draft" or "published". */
84
+ mode: DocMode;
85
+ }
86
+ export interface SaveDraftOptions {
87
+ /**
88
+ * Locales to enable.
89
+ */
90
+ locales?: string[];
91
+ /**
92
+ * Email of user modifying the doc. If blank, defaults to `root-cms-client`.
93
+ */
94
+ modifiedBy?: string;
95
+ /**
96
+ * Whether to validate fieldsData against the collection schema before saving.
97
+ * If validation fails, an error will be thrown with details about the validation errors.
98
+ */
99
+ validate?: boolean;
100
+ }
101
+ export interface UpdateDraftOptions {
102
+ /**
103
+ * Whether to validate the updated field against the collection schema.
104
+ * If validation fails, an error will be thrown with details about the validation errors.
105
+ */
106
+ validate?: boolean;
107
+ }
108
+ export interface ListDocsOptions {
109
+ mode: DocMode;
110
+ offset?: number;
111
+ limit?: number;
112
+ orderBy?: string;
113
+ orderByDirection?: 'asc' | 'desc';
114
+ query?: (query: Query) => Query;
115
+ /**
116
+ * Whether to fetch the "raw" version of the doc (for use in conjunction with
117
+ * `setRawDoc()`).
118
+ */
119
+ raw?: boolean;
120
+ }
121
+ export interface GetCountOptions {
122
+ mode: DocMode;
123
+ query?: (query: Query) => Query;
124
+ }
125
+ export interface Translation {
126
+ [locale: string]: string;
127
+ source: string;
128
+ }
129
+ export interface TranslationsMap {
130
+ [hash: string]: Translation;
131
+ }
132
+ export interface LocaleTranslations {
133
+ [source: string]: string;
134
+ }
135
+ export interface LoadTranslationsOptions {
136
+ tags?: string[];
137
+ }
138
+ export interface Release {
139
+ id: string;
140
+ description?: string;
141
+ docIds?: string[];
142
+ dataSourceIds?: string[];
143
+ createdAt?: Timestamp;
144
+ createdBy?: string;
145
+ scheduledAt?: Timestamp;
146
+ scheduledBy?: string;
147
+ publishedAt?: Timestamp;
148
+ publishedBy?: string;
149
+ }
150
+ export interface Action<T = any> {
151
+ /**
152
+ * The name of the action.
153
+ */
154
+ action: string;
155
+ /**
156
+ * The user's email that performed the action (or "system").
157
+ */
158
+ by?: string;
159
+ /**
160
+ * Timestamp when the action occurred.
161
+ */
162
+ timestamp: Timestamp;
163
+ /**
164
+ * Metadata for the action.
165
+ */
166
+ metadata?: T;
167
+ /**
168
+ * Optional list of quick links to display in the UI.
169
+ */
170
+ links?: {
171
+ label: string;
172
+ url: string;
173
+ target?: string;
174
+ }[];
175
+ }
176
+ export interface ListActionsOptions {
177
+ /**
178
+ * Filter by a specific action. Defaults to all actions.
179
+ */
180
+ action?: string;
181
+ /**
182
+ * Filter by a specific user. Defaults to all users.
183
+ */
184
+ by?: string;
185
+ /**
186
+ * Max number of actions to return. Defaults to 100.
187
+ */
188
+ limit?: number;
189
+ }
190
+ export declare class RootCMSClient {
191
+ readonly rootConfig: RootConfig;
192
+ readonly cmsPlugin: CMSPlugin;
193
+ readonly projectId: string;
194
+ readonly app: App;
195
+ readonly db: Firestore;
196
+ constructor(rootConfig: RootConfig);
197
+ /**
198
+ * Converts a doc mode to the Firestore collection name.
199
+ */
200
+ private getModeCollection;
201
+ /**
202
+ * Retrieves doc data from Root.js CMS.
203
+ */
204
+ getDoc<Fields = any>(collectionId: string, slug: string, options: GetDocOptions): Promise<Doc<Fields> | null>;
205
+ /**
206
+ * Retrieves raw doc data as stored in the database. Only use this if you know
207
+ * what you are doing.
208
+ */
209
+ getRawDoc(collectionId: string, slug: string, options: GetDocOptions): Promise<any | null>;
210
+ /**
211
+ * Firestore path for a collection.
212
+ */
213
+ dbCollectionDocsPath(collectionId: string, options: {
214
+ mode: 'draft' | 'published';
215
+ }): string;
216
+ /**
217
+ * Firestore path for a content doc.
218
+ */
219
+ dbDocPath(collectionId: string, slug: string, options: {
220
+ mode: 'draft' | 'published';
221
+ }): string;
222
+ /**
223
+ * Firestore doc ref for a content doc.
224
+ */
225
+ dbDocRef(collectionId: string, slug: string, options: {
226
+ mode: 'draft' | 'published';
227
+ }): FirebaseFirestore.DocumentReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
228
+ /**
229
+ * Returns a collection's schema definition as defined in
230
+ * `/collections/<id>.schema.ts`.
231
+ */
232
+ getCollection(collectionId: string): Promise<Collection | null>;
233
+ /**
234
+ * Saves draft data to a doc.
235
+ *
236
+ * Note: this saves data to the "fields" attr of the draft doc. If you need to
237
+ * modify the sys-level attributes of the doc, use `setRawDoc()`.
238
+ */
239
+ saveDraftData(docId: string, fieldsData: any, options?: SaveDraftOptions): Promise<void>;
240
+ /**
241
+ * Updates a specific field path in a draft doc.
242
+ *
243
+ * This allows partial updates to nested fields without replacing the entire document.
244
+ * For example: `updateDraftData('Pages/home', 'hero.title', 'New Title')`
245
+ *
246
+ * @param docId - The document ID (e.g., 'Pages/home')
247
+ * @param path - JSON path to the field (e.g., 'hero.title' or 'content.0.text')
248
+ * @param fieldValue - The value to set at the specified path
249
+ * @param options - Update options including validation
250
+ */
251
+ updateDraftData(docId: string, path: string, fieldValue: any, options?: UpdateDraftOptions): Promise<void>;
252
+ /**
253
+ * Sets the raw document data directly in Firestore.
254
+ *
255
+ * CAUTION Prefer using `saveDraftData('Pages/foo', data)` in most cases.
256
+ * Only use this method if you need to manipulate system-level (sys) fields
257
+ * directly or if you're implementing low-level data operations.
258
+ *
259
+ * ## Validation & Normalization
260
+ *
261
+ * This method automatically validates and normalizes `sys` fields to prevent
262
+ * data integrity issues that can cause runtime errors like
263
+ * "e.toMillis is not a function".
264
+ *
265
+ * ### Timestamp Fields (auto-converted)
266
+ * The following fields accept multiple formats and are automatically converted
267
+ * to Firestore Timestamp objects:
268
+ * - `sys.createdAt`
269
+ * - `sys.modifiedAt`
270
+ * - `sys.publishedAt`
271
+ * - `sys.firstPublishedAt`
272
+ *
273
+ * Accepted formats:
274
+ * - Firestore `Timestamp` object (unchanged)
275
+ * - `number` - Interpreted as milliseconds since epoch, converted to Timestamp
276
+ * - `Date` object - Converted to Timestamp
277
+ *
278
+ * ### Required Fields (auto-populated with defaults if missing)
279
+ * - `sys.createdAt` - Defaults to current time if not provided
280
+ * - `sys.modifiedAt` - Defaults to current time if not provided
281
+ * - `sys.createdBy` - Defaults to 'root-cms-client' if not provided
282
+ * - `sys.modifiedBy` - Defaults to 'root-cms-client' if not provided
283
+ * - `sys.locales` - Defaults to ['en'] if not provided
284
+ *
285
+ * ### Optional Fields (validated if present)
286
+ * - `sys.publishedBy` - String identifier
287
+ * - `sys.firstPublishedBy` - String identifier
288
+ * - `sys.publishingLocked` - Object with optional `until` Timestamp
289
+ *
290
+ * ### Document Identity
291
+ * The `id`, `collection`, and `slug` fields are always set to match the
292
+ * provided parameters, overwriting any existing values to prevent data
293
+ * inconsistencies.
294
+ *
295
+ * @param collectionId - The collection ID (e.g., 'Pages')
296
+ * @param slug - The document slug (e.g., 'home')
297
+ * @param data - The complete document data including sys and fields
298
+ * @param options - Options specifying mode ('draft' or 'published')
299
+ *
300
+ * @throws {Error} If sys fields are invalid or missing required fields
301
+ * @throws {Error} If timestamp fields have invalid types
302
+ *
303
+ * @example
304
+ * ```typescript
305
+ * // Minimal example - sys fields use defaults
306
+ * await client.setRawDoc('Pages', 'home', {
307
+ * sys: {}, // All sys fields will be auto-populated with defaults
308
+ * fields: {
309
+ * title: 'Home Page'
310
+ * }
311
+ * }, { mode: 'draft' });
312
+ *
313
+ * // Full example - with number timestamps (auto-converted)
314
+ * await client.setRawDoc('Pages', 'home', {
315
+ * id: 'Pages/home',
316
+ * collection: 'Pages',
317
+ * slug: 'home',
318
+ * sys: {
319
+ * createdAt: Date.now(), // Auto-converted to Timestamp.
320
+ * createdBy: 'user@example.com',
321
+ * modifiedAt: Date.now(), // Auto-converted to Timestamp.
322
+ * modifiedBy: 'user@example.com',
323
+ * locales: ['en', 'es']
324
+ * },
325
+ * fields: {
326
+ * title: 'Home Page'
327
+ * }
328
+ * }, { mode: 'draft' });
329
+ * ```
330
+ */
331
+ setRawDoc(collectionId: string, slug: string, data: any, options: SetDocOptions): Promise<void>;
332
+ /**
333
+ * Lists docs from a Root.js CMS collection.
334
+ */
335
+ listDocs<T>(collectionId: string, options: ListDocsOptions): Promise<{
336
+ docs: T[];
337
+ }>;
338
+ /**
339
+ * Returns the number of docs in a Root.js CMS collection.
340
+ */
341
+ getDocsCount(collectionId: string, options: GetCountOptions): Promise<number>;
342
+ /**
343
+ * Batch publishes a set of docs by id.
344
+ */
345
+ publishDocs(docIds: string[], options?: {
346
+ publishedBy: string;
347
+ batch?: WriteBatch;
348
+ releaseId?: string;
349
+ }): Promise<any[]>;
350
+ /**
351
+ * Batch unpublishes a set of docs by id.
352
+ */
353
+ unpublishDocs(docIds: string[], options?: {
354
+ unpublishedBy?: string;
355
+ batch?: WriteBatch;
356
+ }): Promise<any[]>;
357
+ /**
358
+ * Publishes scheduled docs.
359
+ */
360
+ publishScheduledDocs(): Promise<any[]>;
361
+ /**
362
+ * Publishes docs in scheduled releases.
363
+ */
364
+ publishScheduledReleases(): Promise<void>;
365
+ /**
366
+ * Syncs data sources that have cron scheduling enabled and are due for sync.
367
+ */
368
+ syncScheduledDataSources(): Promise<void>;
369
+ /**
370
+ * Checks if a doc is currently "locked" for publishing.
371
+ */
372
+ testPublishingLocked(doc: Doc): boolean;
373
+ /**
374
+ * Returns a `TranslationsManager` object for managing translations.
375
+ *
376
+ * To get translations:
377
+ * ```
378
+ * await tm.loadTranslations({
379
+ * ids: ['Global/strings', 'Pages/index'],
380
+ * locales: ['es'],
381
+ * });
382
+ * ```
383
+ *
384
+ * NOTE: The `TranslationsManager` is a v2 feature that will eventually
385
+ * replace the v1 translations system.
386
+ */
387
+ getTranslationsManager(): TranslationsManager;
388
+ /**
389
+ * Loads translations saved in the translations collection, optionally
390
+ * filtered by tag.
391
+ *
392
+ * Returns a map like:
393
+ * ```
394
+ * {
395
+ * "<hash>": {"source": "Hello", "es": "Hola", "fr": "Bonjour"},
396
+ * }
397
+ * ```
398
+ */
399
+ loadTranslations(options?: LoadTranslationsOptions): Promise<TranslationsMap>;
400
+ /**
401
+ * Saves a map of translations, e.g.:
402
+ * ```
403
+ * await client.saveTranslations({
404
+ * "Hello": {"es": "Hola", "fr": "Bonjour"},
405
+ * });
406
+ * ```
407
+ */
408
+ saveTranslations(translations: {
409
+ [source: string]: {
410
+ [locale: string]: string;
411
+ };
412
+ }, tags?: string[]): Promise<void>;
413
+ /**
414
+ * Returns the "key" used for a translation as stored in the db. Translations
415
+ * are stored under `Projects/<project id>/Translations/<sha1 hash>`.
416
+ */
417
+ getTranslationKey(source: string): string;
418
+ /**
419
+ * Cleans a string that's used for translations. Performs the following:
420
+ * - Removes any leading/trailing whitespace
421
+ * - Removes spaces at the end of any line
422
+ */
423
+ normalizeString(str: string): string;
424
+ /**
425
+ * Loads translations for a particular locale.
426
+ *
427
+ * Returns a map like:
428
+ * ```
429
+ * {
430
+ * "Hello": "Bonjour",
431
+ * }
432
+ * ```
433
+ */
434
+ loadTranslationsForLocale(locale: string, options?: LoadTranslationsOptions): Promise<LocaleTranslations>;
435
+ /**
436
+ * Firestore path for a translations file.
437
+ */
438
+ dbTranslationsPath(translationsId: string, options: {
439
+ mode: 'draft' | 'published';
440
+ }): string;
441
+ /**
442
+ * Firestore doc ref for a translations file.
443
+ */
444
+ dbTranslationsRef(translationsId: string, options: {
445
+ mode: 'draft' | 'published';
446
+ }): FirebaseFirestore.DocumentReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
447
+ /**
448
+ * Returns a data source configuration object.
449
+ */
450
+ getDataSource(dataSourceId: string): Promise<DataSource | null>;
451
+ /**
452
+ * Archives a data source. Archived data sources cannot be synced or published.
453
+ */
454
+ archiveDataSource(dataSourceId: string, options?: {
455
+ archivedBy?: string;
456
+ }): Promise<void>;
457
+ /**
458
+ * Unarchives a data source.
459
+ */
460
+ unarchiveDataSource(dataSourceId: string): Promise<void>;
461
+ /**
462
+ * Syncs a data source to draft state.
463
+ */
464
+ syncDataSource(dataSourceId: string, options?: {
465
+ syncedBy?: string;
466
+ }): Promise<void>;
467
+ publishDataSource(dataSourceId: string, options?: {
468
+ publishedBy?: string;
469
+ }): Promise<void>;
470
+ /**
471
+ * Unpublishes a data source. Removes the `publishedAt`/`publishedBy`
472
+ * metadata from the DataSource doc and deletes the `Data/published` doc.
473
+ */
474
+ unpublishDataSource(dataSourceId: string): Promise<void>;
475
+ publishDataSources(dataSourceIds: string[], options?: {
476
+ publishedBy: string;
477
+ batch?: WriteBatch;
478
+ commitBatch?: boolean;
479
+ }): Promise<void>;
480
+ private fetchData;
481
+ private fetchHttpData;
482
+ /**
483
+ * Fetches data from a Google Sheet using the Google Sheets API v4.
484
+ *
485
+ * ## Setup
486
+ *
487
+ * For the server-side service account to access the Google Sheet:
488
+ *
489
+ * 1. **Enable the Google Sheets API** in the Google Cloud Console for the
490
+ * project associated with the service account.
491
+ * https://console.cloud.google.com/apis/library/sheets.googleapis.com
492
+ *
493
+ * 2. **Share the Google Sheet** with the service account's email address
494
+ * (e.g. `my-service-account@my-project.iam.gserviceaccount.com`).
495
+ * Open the sheet in Google Sheets, click "Share", and add the service
496
+ * account email as a Viewer.
497
+ *
498
+ * - For **App Engine**: the service account email is typically
499
+ * `<project-id>@appspot.gserviceaccount.com`.
500
+ * - For **Cloud Run**: check the service account configured for the
501
+ * Cloud Run service in the Google Cloud Console.
502
+ * - For **local development**: use the service account email from the
503
+ * JSON key file specified in `GOOGLE_APPLICATION_CREDENTIALS`.
504
+ */
505
+ private fetchGsheetData;
506
+ /**
507
+ * Fetches data from a data source.
508
+ */
509
+ getFromDataSource<T = any>(dataSourceId: string, options?: {
510
+ mode?: 'draft' | 'published';
511
+ }): Promise<DataSourceData<T> | null>;
512
+ /**
513
+ * Firestore path for a datasource data.
514
+ */
515
+ dbDataSourceDataPath(dataSourceId: string, options: {
516
+ mode: 'draft' | 'published';
517
+ }): string;
518
+ /**
519
+ * Firestore doc ref for a datasource data.
520
+ */
521
+ dbDataSourceDataRef(dataSourceId: string, options: {
522
+ mode: 'draft' | 'published';
523
+ }): FirebaseFirestore.DocumentReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
524
+ /**
525
+ * Gets the user's role from the project's ACL.
526
+ */
527
+ getUserRole(email: string): Promise<UserRole | null>;
528
+ /**
529
+ * Verifies user exists in the ACL list.
530
+ */
531
+ userExistsInAcl(email: string): Promise<boolean>;
532
+ /**
533
+ * Lists action logs from the database.
534
+ */
535
+ listActions(options?: ListActionsOptions): Promise<Action[]>;
536
+ logAction(action: string, options?: {
537
+ by?: string;
538
+ metadata?: any;
539
+ links?: {
540
+ label: string;
541
+ url: string;
542
+ target?: string;
543
+ }[];
544
+ }): Promise<void>;
545
+ /**
546
+ * Creates a batch request that is capable of fetching one or more docs,
547
+ * corresponding translations, and dataSources.
548
+ */
549
+ createBatchRequest(options: BatchRequestOptions): BatchRequest;
550
+ }
551
+ /**
552
+ * Returns true if the `data` is a rich text data object.
553
+ */
554
+ export declare function isRichTextData(data: any): boolean;
555
+ export declare function getCmsPlugin(rootConfig: RootConfig): CMSPlugin;
556
+ /**
557
+ * Walks the data tree and converts any array of objects into "array objects"
558
+ * for storage in firestore.
559
+ */
560
+ export declare function marshalData(data: any): any;
561
+ /**
562
+ * Walks the data tree and converts any Timestamp objects to millis and any
563
+ * _array maps to normal arrays.
564
+ *
565
+ * E.g.:
566
+ *
567
+ * normalizeData({
568
+ * sys: {modifiedAt: Timestamp(123)},
569
+ * fields: {
570
+ * _array: ['asdf'],
571
+ * asdf: {title: 'hello'}
572
+ * }
573
+ * })
574
+ * // => {sys: {modifiedAt: 123}, fields: {foo: [{title: 'hello'}]}}
575
+ */
576
+ export declare function unmarshalData(data: any): any;
577
+ /** @deprecated Use `unmarshalData()` instead. */
578
+ export declare function normalizeData(data: any): any;
579
+ export interface ArrayObject {
580
+ [key: string]: any;
581
+ _array: string[];
582
+ }
583
+ /**
584
+ * Serializes an array into an `ArrayObject`, e.g.:
585
+ *
586
+ * ```
587
+ * marshalArray([1, 2, 3])
588
+ * // => {a: 1, b: 2, c: 3, _array: ['a', 'b', 'c']}
589
+ * ```
590
+ *
591
+ * This database storage method makes it easier to update a single field in a
592
+ * deeply nested array object.
593
+ */
594
+ export declare function toArrayObject(arr: any[]): ArrayObject;
595
+ export declare const marshalArray: typeof toArrayObject;
596
+ /**
597
+ * Converts an `ArrayObject` to a normal array.
598
+ */
599
+ export declare function unmarshalArray(arrObject: ArrayObject): any[];
600
+ /**
601
+ * Converts a translations map from `loadTranslations()` to a map of source to
602
+ * translated string for a particular locale.
603
+ *
604
+ * Returns a map like:
605
+ * ```
606
+ * {
607
+ * "Hello": "Bonjour",
608
+ * }
609
+ * ```
610
+ */
611
+ export declare function translationsForLocale(translationsMap: TranslationsMap, locale: string): LocaleTranslations;
612
+ /**
613
+ * Parses a docId (e.g. `Pages/foo`) and returns the `collection` and `slug`.
614
+ */
615
+ export declare function parseDocId(docId: string): {
616
+ collection: string;
617
+ slug: string;
618
+ };
619
+ export interface BatchRequestOptions {
620
+ mode: 'draft' | 'published';
621
+ /**
622
+ * Whether to automatically fetch translations for the docs retrieved in the
623
+ * request.
624
+ */
625
+ translate?: boolean;
626
+ }
627
+ export interface BatchRequestQuery {
628
+ queryId: string;
629
+ collectionId: string;
630
+ queryOptions?: BatchRequestQueryOptions;
631
+ }
632
+ export interface BatchRequestQueryOptions {
633
+ offset?: number;
634
+ limit?: number;
635
+ orderBy?: string;
636
+ orderByDirection?: 'asc' | 'desc';
637
+ query?: (query: Query) => Query;
638
+ }
639
+ export interface TranslationsDoc {
640
+ id: string;
641
+ sys: {
642
+ modifiedAt: Timestamp;
643
+ modifiedBy: string;
644
+ publishedAt?: Timestamp;
645
+ publishedBy?: string;
646
+ linkedSheet?: {
647
+ spreadsheetId: string;
648
+ gid: number;
649
+ linkedAt: Timestamp;
650
+ linkedBy: string;
651
+ };
652
+ tags?: string[];
653
+ };
654
+ strings: TranslationsMap;
655
+ }
656
+ export declare class BatchRequest {
657
+ cmsClient: RootCMSClient;
658
+ private options;
659
+ private db;
660
+ private docIds;
661
+ private dataSourceIds;
662
+ private queries;
663
+ private translationsIds;
664
+ constructor(cmsClient: RootCMSClient, options: BatchRequestOptions);
665
+ /**
666
+ * Adds a doc to the batch request.
667
+ */
668
+ addDoc(docId: string): void;
669
+ /**
670
+ * Adds a data source to the batch request.
671
+ */
672
+ addDataSource(dataSourceId: string): void;
673
+ /**
674
+ * Adds a collection-based query to the batch request.
675
+ */
676
+ addQuery(queryId: string, collectionId: string, queryOptions?: BatchRequestQueryOptions): void;
677
+ /**
678
+ * Adds a translation file to the request.
679
+ */
680
+ addTranslations(translationsId: string): void;
681
+ /**
682
+ * Fetches data from the DB.
683
+ */
684
+ fetch(): Promise<BatchResponse>;
685
+ private fetchDocs;
686
+ private fetchQueries;
687
+ private fetchDataSources;
688
+ private fetchTranslations;
689
+ }
690
+ export declare class BatchResponse {
691
+ docs: Record<string, Doc>;
692
+ queries: Record<string, Doc[]>;
693
+ dataSources: Record<string, DataSourceData>;
694
+ translations: Record<string, TranslationsDoc>;
695
+ /**
696
+ * Returns a map of translations for a given locale or locale fallbacks.
697
+ *
698
+ * The input is either a single locale (e.g. "de") or an array of locales
699
+ * representing the fallback tree, e.g. ["en-CA", "en-GB", "en"].
700
+ *
701
+ * TODO(stevenle): support the locale fallback tree.
702
+ *
703
+ * The returned value is a flat map of source string to translated string,
704
+ * e.g.:
705
+ * {"<source>": "<translation>"}
706
+ */
707
+ getTranslations(locale: string): LocaleTranslations;
708
+ /**
709
+ * Merges the strings from all translations files retrieved in the request.
710
+ * The returned value is a map of string to translations, e.g.:
711
+ *
712
+ * {"<hash>": {"source": "<source>", "<locale>": "<translation>"}}
713
+ */
714
+ private getTranslationsMap;
715
+ }