@blinkk/root-cms 3.0.2 → 3.0.4

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-2BSW7SIH.js → chunk-N4K6ICFR.js} +4 -4
  3. package/dist/{chunk-BGTUWIV6.js → chunk-PNLLZXVY.js} +4 -4
  4. package/dist/{chunk-3HARN4U6.js → chunk-RLZFZT42.js} +176 -83
  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 +128 -133
  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-YI3RFK5F.js +1 -0
  61. package/dist/ui/AssetsPage-4JNAOFYF.js +1 -0
  62. package/dist/ui/CollectionPage-JWHH5G55.js +1 -0
  63. package/dist/ui/ComparePage-YZE3EMU4.js +1 -0
  64. package/dist/ui/DataPage-VRCQSZZG.js +1 -0
  65. package/dist/ui/DataSourcePage-WMSPBZ3W.js +1 -0
  66. package/dist/ui/DocTranslationsPage-RY2LOZBX.js +1 -0
  67. package/dist/ui/DocumentPage-EEGTJMIW.js +1 -0
  68. package/dist/ui/EditDataSourcePage-LLCX6K4J.js +1 -0
  69. package/dist/ui/EditReleasePage-WQYXXMZQ.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-IP2DKEYR.js +1 -0
  73. package/dist/ui/NewDataSourcePage-RDYJC4DH.js +1 -0
  74. package/dist/ui/NewReleasePage-DGMFU2JN.js +1 -0
  75. package/dist/ui/NotFoundPage-WDZ2K7EF.js +1 -0
  76. package/dist/ui/ProjectPage-HYJOQUWR.js +1 -0
  77. package/dist/ui/ReleasePage-2KSF23TK.js +1 -0
  78. package/dist/ui/ReleasesPage-NZIBBXU4.js +1 -0
  79. package/dist/ui/SettingsPage-36XFWV62.js +1 -0
  80. package/dist/ui/SidebarToolsPage-5C6YBWJ7.js +1 -0
  81. package/dist/ui/TaskPage-SPIFPGPP.js +1 -0
  82. package/dist/ui/TasksPage-ZOXRPBQV.js +1 -0
  83. package/dist/ui/TranslationsArbPage-UHANA7JD.js +2 -0
  84. package/dist/ui/TranslationsEditPage-PQY6W5YG.js +1 -0
  85. package/dist/ui/TranslationsPage-V2PQFCN5.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-767BAQ53.js +1 -0
  94. package/dist/ui/chunk-AFWBSIPL.js +1 -0
  95. package/dist/ui/chunk-AL3TN2KI.js +1 -0
  96. package/dist/ui/chunk-BZIRGB4W.js +1 -0
  97. package/dist/ui/chunk-C5NH23G4.js +3 -0
  98. package/dist/ui/chunk-CGCKJFL4.js +1 -0
  99. package/dist/ui/chunk-DEGMKEHP.js +1 -0
  100. package/dist/ui/chunk-DTMZLUNY.js +15 -0
  101. package/dist/ui/chunk-DTMZLUNY.js.LEGAL.txt +237 -0
  102. package/dist/ui/chunk-DUJYIOLE.js +5 -0
  103. package/dist/ui/chunk-E2RCCK2T.js +1 -0
  104. package/dist/ui/chunk-EGEB6N4J.js +22 -0
  105. package/dist/ui/chunk-EGEB6N4J.js.LEGAL.txt +1059 -0
  106. package/dist/ui/chunk-FBJURT7Z.js +1 -0
  107. package/dist/ui/chunk-GXSAEPU3.js +1 -0
  108. package/dist/ui/chunk-HHMG665Z.js +1 -0
  109. package/dist/ui/chunk-HKINZLMW.js +84 -0
  110. package/dist/ui/chunk-HLMBCVRX.js +1 -0
  111. package/dist/ui/chunk-HRGYNHZ3.js +1 -0
  112. package/dist/ui/chunk-I6ICVKEC.js +1 -0
  113. package/dist/ui/chunk-JDW4UORS.js +1 -0
  114. package/dist/ui/chunk-JHBAMPGB.js +1 -0
  115. package/dist/ui/chunk-JT5L6GPZ.js +141 -0
  116. package/dist/ui/chunk-JT5L6GPZ.js.LEGAL.txt +106 -0
  117. package/dist/ui/chunk-JYFLU7DM.js +19 -0
  118. package/dist/ui/chunk-JZFTZ4X4.js +87 -0
  119. package/dist/ui/chunk-JZFTZ4X4.js.LEGAL.txt +9 -0
  120. package/dist/ui/chunk-KFAZBEPV.js +1 -0
  121. package/dist/ui/chunk-KKEWCXVV.js +1 -0
  122. package/dist/ui/chunk-KUCVLANF.js +1 -0
  123. package/dist/ui/chunk-KYDOSLTO.js +1 -0
  124. package/dist/ui/chunk-L4RHGQUG.js +1 -0
  125. package/dist/ui/chunk-MDUBCXU2.js +1 -0
  126. package/dist/ui/chunk-NXQVLOTK.js +1 -0
  127. package/dist/ui/chunk-NZHF733K.js +7 -0
  128. package/dist/ui/chunk-NZHF733K.js.LEGAL.txt +146 -0
  129. package/dist/ui/chunk-ONTGW2VA.js +1 -0
  130. package/dist/ui/chunk-ORXEMIQC.js +1 -0
  131. package/dist/ui/chunk-P3NETZZP.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-TJBVMFNQ.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,46 @@
1
+ /** @deprecated Use client.ts instead. */
2
+ import { RootConfig } from '@blinkk/root';
3
+ import { Query } from 'firebase-admin/firestore';
4
+ import { LoadTranslationsOptions, LocaleTranslations, TranslationsMap } from './client.js';
5
+ /**
6
+ * Retrieves a doc from Root.js CMS.
7
+ * @deprecated Use RootCMSClient.getDoc() instead.
8
+ */
9
+ export declare function getDoc<T>(rootConfig: RootConfig, collectionId: string, slug: string, options: {
10
+ mode: 'draft' | 'published';
11
+ }): Promise<T | null>;
12
+ /**
13
+ * Lists docs from a Root.js CMS collection.
14
+ * @deprecated Use RootCMSClient.listDocs() instead.
15
+ */
16
+ export declare function listDocs<T>(rootConfig: RootConfig, collectionId: string, options: {
17
+ mode: 'draft' | 'published';
18
+ offset?: number;
19
+ limit?: number;
20
+ orderBy?: string;
21
+ orderByDirection?: 'asc' | 'desc';
22
+ query?: (query: Query) => Query;
23
+ }): Promise<{
24
+ docs: T[];
25
+ }>;
26
+ /**
27
+ * Returns the number of docs in a Root.js CMS collection.
28
+ * @deprecated Use RootCMSClient.getDocsCount() instead.
29
+ */
30
+ export declare function numDocs(rootConfig: RootConfig, collectionId: string, options: {
31
+ mode: 'draft' | 'published';
32
+ query?: (query: Query) => Query;
33
+ }): Promise<number>;
34
+ /**
35
+ * Publishes scheduled docs.
36
+ * @deprecated Use RootCMSClient.publishScheduledDocs() instead.
37
+ */
38
+ export declare function publishScheduledDocs(rootConfig: RootConfig): Promise<any[]>;
39
+ /**
40
+ * @deprecated Use `RootCMSClient.loadTranslations()`.
41
+ */
42
+ export declare function loadTranslations(rootConfig: RootConfig, options?: LoadTranslationsOptions): Promise<TranslationsMap>;
43
+ /**
44
+ * @deprecated Use `RootCMSClient.loadTranslationsForLocale()`.
45
+ */
46
+ export declare function loadTranslationsForLocale(rootConfig: RootConfig, locale: string, options?: LoadTranslationsOptions): Promise<LocaleTranslations>;
@@ -1,4 +1,4 @@
1
- interface CommonFieldProps {
1
+ export interface CommonFieldProps {
2
2
  /** The type that defines the structure of the field and its UI component. */
3
3
  type: string;
4
4
  /** The ID provides a key for the field in the data. */
@@ -17,7 +17,7 @@ interface CommonFieldProps {
17
17
  /** Hides just the field label in the CMS UI. */
18
18
  hideLabel?: boolean;
19
19
  }
20
- type StringField = CommonFieldProps & {
20
+ export type StringField = CommonFieldProps & {
21
21
  type: 'string';
22
22
  default?: string;
23
23
  translate?: boolean;
@@ -37,18 +37,18 @@ type StringField = CommonFieldProps & {
37
37
  */
38
38
  autosize?: boolean;
39
39
  };
40
- declare function string(field: Omit<StringField, 'type'>): StringField;
41
- type NumberField = CommonFieldProps & {
40
+ export declare function string(field: Omit<StringField, 'type'>): StringField;
41
+ export type NumberField = CommonFieldProps & {
42
42
  type: 'number';
43
43
  default?: number;
44
44
  };
45
- declare function number(field: Omit<NumberField, 'type'>): NumberField;
46
- type DateField = CommonFieldProps & {
45
+ export declare function number(field: Omit<NumberField, 'type'>): NumberField;
46
+ export type DateField = CommonFieldProps & {
47
47
  type: 'date';
48
48
  default?: string;
49
49
  };
50
- declare function date(field: Omit<DateField, 'type'>): DateField;
51
- type DateTimeField = CommonFieldProps & {
50
+ export declare function date(field: Omit<DateField, 'type'>): DateField;
51
+ export type DateTimeField = CommonFieldProps & {
52
52
  type: 'datetime';
53
53
  default?: string;
54
54
  /**
@@ -57,14 +57,14 @@ type DateTimeField = CommonFieldProps & {
57
57
  */
58
58
  timezone?: string;
59
59
  };
60
- declare function datetime(field: Omit<DateTimeField, 'type'>): DateTimeField;
61
- type BooleanField = CommonFieldProps & {
60
+ export declare function datetime(field: Omit<DateTimeField, 'type'>): DateTimeField;
61
+ export type BooleanField = CommonFieldProps & {
62
62
  type: 'boolean';
63
63
  default?: boolean;
64
64
  checkboxLabel?: string;
65
65
  };
66
- declare function boolean(field: Omit<BooleanField, 'type'>): BooleanField;
67
- type SelectField = CommonFieldProps & {
66
+ export declare function boolean(field: Omit<BooleanField, 'type'>): BooleanField;
67
+ export type SelectField = CommonFieldProps & {
68
68
  type: 'select';
69
69
  default?: string;
70
70
  options?: Array<{
@@ -74,15 +74,15 @@ type SelectField = CommonFieldProps & {
74
74
  translate?: boolean;
75
75
  searchable?: boolean;
76
76
  };
77
- declare function select(field: Omit<SelectField, 'type'>): SelectField;
78
- type MultiSelectField = Omit<SelectField, 'type'> & {
77
+ export declare function select(field: Omit<SelectField, 'type'>): SelectField;
78
+ export type MultiSelectField = Omit<SelectField, 'type'> & {
79
79
  type: 'multiselect';
80
80
  /** Set to `true` to allow users to create arbitrary values. */
81
81
  creatable?: boolean;
82
82
  translate?: boolean;
83
83
  };
84
- declare function multiselect(field: Omit<MultiSelectField, 'type'>): MultiSelectField;
85
- type ImageField = CommonFieldProps & {
84
+ export declare function multiselect(field: Omit<MultiSelectField, 'type'>): MultiSelectField;
85
+ export type ImageField = CommonFieldProps & {
86
86
  type: 'image';
87
87
  translate?: boolean;
88
88
  /** List of supported exts, e.g. `['.mp4']`. */
@@ -94,8 +94,8 @@ type ImageField = CommonFieldProps & {
94
94
  /** Set to `false` to disable the alt text input. */
95
95
  alt?: boolean;
96
96
  };
97
- declare function image(field: Omit<ImageField, 'type'>): ImageField;
98
- type FileField = CommonFieldProps & {
97
+ export declare function image(field: Omit<ImageField, 'type'>): ImageField;
98
+ export type FileField = CommonFieldProps & {
99
99
  type: 'file';
100
100
  /** List of supported exts, e.g. `['.mp4']`. */
101
101
  exts?: string[];
@@ -111,8 +111,8 @@ type FileField = CommonFieldProps & {
111
111
  /** Set to `false` to disable the alt text input. */
112
112
  alt?: boolean;
113
113
  };
114
- declare function file(field: Omit<FileField, 'type'>): FileField;
115
- type ObjectField = CommonFieldProps & {
114
+ export declare function file(field: Omit<FileField, 'type'>): FileField;
115
+ export type ObjectField = CommonFieldProps & {
116
116
  type: 'object';
117
117
  fields: FieldWithId[];
118
118
  /** Defaults to "drawer". */
@@ -128,8 +128,8 @@ type ObjectField = CommonFieldProps & {
128
128
  inline?: boolean;
129
129
  };
130
130
  };
131
- declare function object(field: Omit<ObjectField, 'type'>): ObjectField;
132
- type ArrayField = CommonFieldProps & {
131
+ export declare function object(field: Omit<ObjectField, 'type'>): ObjectField;
132
+ export type ArrayField = CommonFieldProps & {
133
133
  type: 'array';
134
134
  default?: any[];
135
135
  /**
@@ -161,13 +161,13 @@ type ArrayField = CommonFieldProps & {
161
161
  */
162
162
  defaultOpen?: boolean;
163
163
  };
164
- declare function array(field: Omit<ArrayField, 'type'>): ArrayField;
164
+ export declare function array(field: Omit<ArrayField, 'type'>): ArrayField;
165
165
  /**
166
166
  * A schema pattern that is resolved at project load time. This allows schemas
167
167
  * to reference other schemas by glob pattern without causing circular import
168
168
  * issues, since resolution is deferred until all schemas are loaded.
169
169
  */
170
- interface SchemaPattern {
170
+ export interface SchemaPattern {
171
171
  /** Marker to identify this as a schema pattern. */
172
172
  _schemaPattern: true;
173
173
  /** Glob pattern to match schema files. */
@@ -177,7 +177,7 @@ interface SchemaPattern {
177
177
  /** Field IDs to omit from the matched schemas. */
178
178
  omitFields?: string[];
179
179
  }
180
- type OneOfField = CommonFieldProps & {
180
+ export type OneOfField = CommonFieldProps & {
181
181
  type: 'oneof';
182
182
  /**
183
183
  * UI variant for the oneOf field.
@@ -195,8 +195,8 @@ type OneOfField = CommonFieldProps & {
195
195
  */
196
196
  types: Schema[] | string[] | Array<Schema | string> | SchemaPattern;
197
197
  };
198
- declare function oneOf(field: Omit<OneOfField, 'type'>): OneOfField;
199
- type RichTextField = CommonFieldProps & {
198
+ export declare function oneOf(field: Omit<OneOfField, 'type'>): OneOfField;
199
+ export type RichTextField = CommonFieldProps & {
200
200
  type: 'richtext';
201
201
  translate?: boolean;
202
202
  placeholder?: string;
@@ -210,8 +210,8 @@ type RichTextField = CommonFieldProps & {
210
210
  /** Custom inline component definitions to include in the rich text editor. */
211
211
  inlineComponents?: Schema[];
212
212
  };
213
- declare function richtext(field: Omit<RichTextField, 'type'>): RichTextField;
214
- type ReferenceField = CommonFieldProps & {
213
+ export declare function richtext(field: Omit<RichTextField, 'type'>): RichTextField;
214
+ export type ReferenceField = CommonFieldProps & {
215
215
  type: 'reference';
216
216
  /** List of collection ids the reference can be chosen from. */
217
217
  collections?: string[];
@@ -220,8 +220,8 @@ type ReferenceField = CommonFieldProps & {
220
220
  /** Label for the button. Defaults to "Select". */
221
221
  buttonLabel?: string;
222
222
  };
223
- declare function reference(field: Omit<ReferenceField, 'type'>): ReferenceField;
224
- type ReferencesField = CommonFieldProps & {
223
+ export declare function reference(field: Omit<ReferenceField, 'type'>): ReferenceField;
224
+ export type ReferencesField = CommonFieldProps & {
225
225
  type: 'references';
226
226
  /** List of collection ids the references can be chosen from. */
227
227
  collections?: string[];
@@ -230,15 +230,15 @@ type ReferencesField = CommonFieldProps & {
230
230
  /** Label for the button. Defaults to "Select". */
231
231
  buttonLabel?: string;
232
232
  };
233
- declare function references(field: Omit<ReferencesField, 'type'>): ReferencesField;
234
- type Field = StringField | NumberField | DateField | DateTimeField | BooleanField | SelectField | MultiSelectField | ImageField | FileField | ObjectField | ArrayField | OneOfField | RichTextField | ReferenceField | ReferencesField;
233
+ export declare function references(field: Omit<ReferencesField, 'type'>): ReferencesField;
234
+ export type Field = StringField | NumberField | DateField | DateTimeField | BooleanField | SelectField | MultiSelectField | ImageField | FileField | ObjectField | ArrayField | OneOfField | RichTextField | ReferenceField | ReferencesField;
235
235
  /**
236
236
  * Similar to {@link Field} but with a required `id`.
237
237
  * TODO(stevenle): fix this.
238
238
  */
239
- type FieldWithId = Field;
240
- type ObjectLikeField = ImageField | FileField | ObjectField | OneOfField | ReferenceField;
241
- interface SchemaPreset<T = Record<string, any>> {
239
+ export type FieldWithId = Field;
240
+ export type ObjectLikeField = ImageField | FileField | ObjectField | OneOfField | ReferenceField;
241
+ export interface SchemaPreset<T = Record<string, any>> {
242
242
  /** Unique identifier for the preset within the schema. */
243
243
  id: string;
244
244
  /** Display title for the preset. Defaults to the preset id. */
@@ -257,7 +257,7 @@ interface SchemaPreset<T = Record<string, any>> {
257
257
  */
258
258
  data?: T;
259
259
  }
260
- interface Schema {
260
+ export interface Schema {
261
261
  /** The name of the content type. Used as the field key. */
262
262
  name: string;
263
263
  /** Label to use for UI strings. */
@@ -304,13 +304,13 @@ interface Schema {
304
304
  image?: string | string[];
305
305
  };
306
306
  }
307
- type SchemaWithTypes = Schema & {
307
+ export type SchemaWithTypes = Schema & {
308
308
  /** Reusable type definitions used by the schema, e.g. for oneOf() fields. */
309
309
  types?: Record<string, Schema>;
310
310
  };
311
- declare function defineSchema(schema: Schema): Schema;
311
+ export declare function defineSchema(schema: Schema): Schema;
312
312
  /** Defines the schema for a collection or reusable component. */
313
- declare const define: typeof defineSchema;
313
+ export declare const define: typeof defineSchema;
314
314
  /**
315
315
  * Defines a preset for use within `schema.define({presets: [...]})`. The
316
316
  * optional generic parameter `T` constrains the shape of the preset's `data`
@@ -326,10 +326,10 @@ declare const define: typeof defineSchema;
326
326
  * });
327
327
  * ```
328
328
  */
329
- declare function definePreset<T = Record<string, any>>(preset: SchemaPreset<T>): SchemaPreset<T>;
329
+ export declare function definePreset<T = Record<string, any>>(preset: SchemaPreset<T>): SchemaPreset<T>;
330
330
  /** Alias for {@link definePreset}. */
331
- declare const preset: typeof definePreset;
332
- type Collection = SchemaWithTypes & {
331
+ export declare const preset: typeof definePreset;
332
+ export type Collection = SchemaWithTypes & {
333
333
  /**
334
334
  * The ID of the collection. This comes from the schema filename, e.g
335
335
  * `<id>.schema.ts`.
@@ -397,12 +397,12 @@ type Collection = SchemaWithTypes & {
397
397
  direction?: 'asc' | 'desc';
398
398
  }>;
399
399
  };
400
- declare function defineCollection(collection: Omit<Collection, 'id'>): Omit<Collection, 'id'>;
401
- declare const collection: typeof defineCollection;
400
+ export declare function defineCollection(collection: Omit<Collection, 'id'>): Omit<Collection, 'id'>;
401
+ export declare const collection: typeof defineCollection;
402
402
  /**
403
403
  * Options for `schema.glob()`.
404
404
  */
405
- interface GlobOptions {
405
+ export interface GlobOptions {
406
406
  /** Schema names to exclude from the matched results. */
407
407
  exclude?: string[];
408
408
  /** Field IDs to omit from the matched schemas. */
@@ -449,57 +449,4 @@ interface GlobOptions {
449
449
  * });
450
450
  * ```
451
451
  */
452
- declare function glob(pattern: string, options?: GlobOptions): SchemaPattern;
453
-
454
- type schema_ArrayField = ArrayField;
455
- type schema_BooleanField = BooleanField;
456
- type schema_Collection = Collection;
457
- type schema_CommonFieldProps = CommonFieldProps;
458
- type schema_DateField = DateField;
459
- type schema_DateTimeField = DateTimeField;
460
- type schema_Field = Field;
461
- type schema_FieldWithId = FieldWithId;
462
- type schema_FileField = FileField;
463
- type schema_GlobOptions = GlobOptions;
464
- type schema_ImageField = ImageField;
465
- type schema_MultiSelectField = MultiSelectField;
466
- type schema_NumberField = NumberField;
467
- type schema_ObjectField = ObjectField;
468
- type schema_ObjectLikeField = ObjectLikeField;
469
- type schema_OneOfField = OneOfField;
470
- type schema_ReferenceField = ReferenceField;
471
- type schema_ReferencesField = ReferencesField;
472
- type schema_RichTextField = RichTextField;
473
- type schema_Schema = Schema;
474
- type schema_SchemaPattern = SchemaPattern;
475
- type schema_SchemaPreset<T = Record<string, any>> = SchemaPreset<T>;
476
- type schema_SchemaWithTypes = SchemaWithTypes;
477
- type schema_SelectField = SelectField;
478
- type schema_StringField = StringField;
479
- declare const schema_array: typeof array;
480
- declare const schema_boolean: typeof boolean;
481
- declare const schema_collection: typeof collection;
482
- declare const schema_date: typeof date;
483
- declare const schema_datetime: typeof datetime;
484
- declare const schema_define: typeof define;
485
- declare const schema_defineCollection: typeof defineCollection;
486
- declare const schema_definePreset: typeof definePreset;
487
- declare const schema_defineSchema: typeof defineSchema;
488
- declare const schema_file: typeof file;
489
- declare const schema_glob: typeof glob;
490
- declare const schema_image: typeof image;
491
- declare const schema_multiselect: typeof multiselect;
492
- declare const schema_number: typeof number;
493
- declare const schema_object: typeof object;
494
- declare const schema_oneOf: typeof oneOf;
495
- declare const schema_preset: typeof preset;
496
- declare const schema_reference: typeof reference;
497
- declare const schema_references: typeof references;
498
- declare const schema_richtext: typeof richtext;
499
- declare const schema_select: typeof select;
500
- declare const schema_string: typeof string;
501
- declare namespace schema {
502
- export { type schema_ArrayField as ArrayField, type schema_BooleanField as BooleanField, type schema_Collection as Collection, type schema_CommonFieldProps as CommonFieldProps, type schema_DateField as DateField, type schema_DateTimeField as DateTimeField, type schema_Field as Field, type schema_FieldWithId as FieldWithId, type schema_FileField as FileField, type schema_GlobOptions as GlobOptions, type schema_ImageField as ImageField, type schema_MultiSelectField as MultiSelectField, type schema_NumberField as NumberField, type schema_ObjectField as ObjectField, type schema_ObjectLikeField as ObjectLikeField, type schema_OneOfField as OneOfField, type schema_ReferenceField as ReferenceField, type schema_ReferencesField as ReferencesField, type schema_RichTextField as RichTextField, type schema_Schema as Schema, type schema_SchemaPattern as SchemaPattern, type schema_SchemaPreset as SchemaPreset, type schema_SchemaWithTypes as SchemaWithTypes, type schema_SelectField as SelectField, type schema_StringField as StringField, schema_array as array, schema_boolean as boolean, schema_collection as collection, schema_date as date, schema_datetime as datetime, schema_define as define, schema_defineCollection as defineCollection, schema_definePreset as definePreset, schema_defineSchema as defineSchema, schema_file as file, schema_glob as glob, schema_image as image, schema_multiselect as multiselect, schema_number as number, schema_object as object, schema_oneOf as oneOf, schema_preset as preset, schema_reference as reference, schema_references as references, schema_richtext as richtext, schema_select as select, schema_string as string };
503
- }
504
-
505
- export { type Collection as C, type Schema as S, schema as s };
452
+ export declare function glob(pattern: string, options?: GlobOptions): SchemaPattern;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Pure (no I/O) extraction of searchable text from CMS doc data, guided by the
3
+ * collection's schema.
4
+ *
5
+ * Walks `fields: {...}` recursively and emits one record per leaf "text-bearing"
6
+ * field. The emitted `deepKey` matches the format used by the doc editor's
7
+ * deep-link system (see ui/hooks/useDeeplink.tsx) so that clicking a search
8
+ * result navigates the editor to the originating field.
9
+ *
10
+ * Reference for the deepKey format (see ui/components/DocEditor/DocEditor.tsx):
11
+ * - Top-level field: fields.<id>
12
+ * - Nested object field: fields.<id>.<sub>
13
+ * - Array item field: fields.<id>.<autokey>.<sub> (autokeys come from `_array`)
14
+ * - oneOf field: fields.<id>.<sub> (siblings of `_type`)
15
+ */
16
+ import type { Field, Schema } from './schema.js';
17
+ /** Hard cap for any single extracted text value. */
18
+ export declare const MAX_FIELD_TEXT_CHARS = 2000;
19
+ export interface ExtractedRecord {
20
+ /** Stable record id: `<docId>#<deepKey>`. */
21
+ id: string;
22
+ /** Doc id, e.g. `Pages/foo-bar`. */
23
+ docId: string;
24
+ collection: string;
25
+ slug: string;
26
+ /** Full deep-link path, e.g. `fields.author.name` or `fields.list.<key>.title`. */
27
+ deepKey: string;
28
+ /** Field type, e.g. `string`, `richtext`, `select`. */
29
+ fieldType: string;
30
+ /** UI label for the field (falls back to `id`). */
31
+ fieldLabel: string;
32
+ /** Extracted plain text, truncated to MAX_FIELD_TEXT_CHARS. */
33
+ text: string;
34
+ }
35
+ interface EmitContext {
36
+ docId: string;
37
+ collection: string;
38
+ slug: string;
39
+ }
40
+ type EmitFn = (record: ExtractedRecord) => void;
41
+ /** Strip HTML tags and decode common entities from a string. */
42
+ export declare function stripHtml(input: string): string;
43
+ interface RichTextLike {
44
+ blocks?: Array<{
45
+ type?: string;
46
+ data?: any;
47
+ }>;
48
+ }
49
+ /**
50
+ * Extracts plain text from a richtext value (EditorJS-shaped).
51
+ *
52
+ * Supported block types mirror those rendered in `core/richtext.tsx`:
53
+ * paragraph, heading, quote, ordered/unordered list, table, html. Unknown or
54
+ * non-textual blocks (e.g. delimiter, image) contribute nothing.
55
+ */
56
+ export declare function extractRichText(data: RichTextLike | unknown): string;
57
+ /**
58
+ * Walks a doc's `fields` against its collection schema and emits one record per
59
+ * text-bearing leaf field.
60
+ */
61
+ export declare function walkSchemaFields(fields: Field[], data: any, parentDeepKey: string, ctx: EmitContext, emit: EmitFn): void;
62
+ export interface ExtractDocOptions {
63
+ collection: string;
64
+ slug: string;
65
+ /** Top-level fields object as stored on the doc. */
66
+ fields: any;
67
+ }
68
+ /** Extracts every searchable record from a single doc. */
69
+ export declare function extractDocRecords(schema: Schema, options: ExtractDocOptions): ExtractedRecord[];
70
+ export {};
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Persisted full-text search index for the CMS.
3
+ *
4
+ * The index is built from the `Drafts` collection of every doc in the project,
5
+ * serialized via MiniSearch's `toJSON()`, sharded across Firestore docs (to
6
+ * stay under the 1 MB per-doc limit), and queried server-side by the
7
+ * `/cms/api/search.query` endpoint.
8
+ *
9
+ * Persistence layout:
10
+ * Projects/{projectId}/SearchIndex/_meta — {lastRun, shardCount, docCount, fieldCount}
11
+ * Projects/{projectId}/SearchIndex/_docMap — {records: {[docId]: recordIds[]}}
12
+ * Projects/{projectId}/SearchIndex/shard-0..N — {shardId, data} (chunks of toJSON())
13
+ *
14
+ * Build modes:
15
+ * - `force: false` (cron path) — incremental: discard records for docs whose
16
+ * `sys.modifiedAt >= lastRun`, re-extract them, addAll. Reconcile deletions
17
+ * by diffing _docMap against the live doc-id set per collection.
18
+ * - `force: true` — drop everything and re-index every doc.
19
+ */
20
+ import { RootConfig } from '@blinkk/root';
21
+ import { Timestamp } from 'firebase-admin/firestore';
22
+ import MiniSearch from 'minisearch';
23
+ import type { CMSSearchIndexConfig } from './plugin.js';
24
+ import type { Schema } from './schema.js';
25
+ import { ExtractedRecord } from './search-extract.js';
26
+ interface IndexableRecord extends ExtractedRecord {
27
+ /** Per-record boost: 2 for title-like fields, 1 otherwise. */
28
+ weight: number;
29
+ }
30
+ interface SearchIndexMeta {
31
+ lastRun: Timestamp;
32
+ shardCount: number;
33
+ docCount: number;
34
+ fieldCount: number;
35
+ /** How many incremental rebuilds have run since the last vacuum. */
36
+ runsSinceVacuum?: number;
37
+ }
38
+ export interface SearchHit {
39
+ id: string;
40
+ docId: string;
41
+ collection: string;
42
+ slug: string;
43
+ deepKey: string;
44
+ fieldLabel: string;
45
+ fieldType: string;
46
+ text: string;
47
+ score: number;
48
+ terms: string[];
49
+ }
50
+ export interface RebuildResult {
51
+ /** True if a full (force) rebuild was performed. */
52
+ forced: boolean;
53
+ /** True if the rebuild short-circuited (no work needed). */
54
+ skipped: boolean;
55
+ docCount: number;
56
+ fieldCount: number;
57
+ shardCount: number;
58
+ durationMs: number;
59
+ }
60
+ export interface SearchIndexStatus {
61
+ lastRun: number | null;
62
+ docCount: number;
63
+ fieldCount: number;
64
+ shardCount: number;
65
+ }
66
+ type DocMap = Record<string, string[]>;
67
+ /**
68
+ * Normalized form of `CMSSearchIndexConfig`. Empty arrays are treated as
69
+ * "unset" so the user can defensively pass an empty list without accidentally
70
+ * excluding everything via `includeCollections: []`.
71
+ */
72
+ interface ResolvedFilters {
73
+ includeCollections: Set<string> | null;
74
+ excludeCollections: Set<string> | null;
75
+ includeDocIds: Set<string> | null;
76
+ excludeDocIds: Set<string> | null;
77
+ }
78
+ export declare function resolveSearchIndexFilters(config?: CMSSearchIndexConfig): ResolvedFilters;
79
+ export declare function isCollectionIndexable(filters: ResolvedFilters, collectionId: string): boolean;
80
+ export declare function isDocIndexable(filters: ResolvedFilters, docId: string): boolean;
81
+ interface CachedIndex {
82
+ index: MiniSearch;
83
+ meta: SearchIndexMeta;
84
+ docMap: DocMap;
85
+ }
86
+ export declare function isTitleyDeepKey(deepKey: string): boolean;
87
+ export declare function withWeight(rec: ExtractedRecord): IndexableRecord;
88
+ /**
89
+ * Loader for a collection's schema. Pluggable so callers can provide a
90
+ * dev-mode loader (Vite SSR) and prod uses the default (`dist/...json`).
91
+ */
92
+ export type LoadSchemaFn = (collectionId: string) => Promise<Schema | null>;
93
+ export declare class SearchIndexService {
94
+ private readonly rootConfig;
95
+ private readonly projectId;
96
+ private readonly db;
97
+ private readonly loadSchema;
98
+ private readonly filters;
99
+ private cached;
100
+ constructor(rootConfig: RootConfig, loadSchema?: LoadSchemaFn, filtersOverride?: CMSSearchIndexConfig);
101
+ /** Returns true if the given collection passes the include/exclude filter. */
102
+ isCollectionIndexable(collectionId: string): boolean;
103
+ /**
104
+ * Returns true if the given doc id passes the include/exclude filter (and
105
+ * its collection is itself indexable). Doc ids are `<collectionId>/<slug>`.
106
+ */
107
+ isDocIndexable(docId: string): boolean;
108
+ /** Returns the MiniSearch options used by both writers and readers. */
109
+ static getMiniSearchOptions(): {
110
+ fields: string[];
111
+ storeFields: string[];
112
+ searchOptions: {
113
+ boost: {
114
+ fieldLabel: number;
115
+ };
116
+ prefix: boolean;
117
+ fuzzy: number;
118
+ };
119
+ };
120
+ private indexDocPath;
121
+ private indexCollectionPath;
122
+ /**
123
+ * Lists collection ids by globbing `<rootDir>/collections/*.schema.ts`,
124
+ * filtered by the include/exclude config.
125
+ */
126
+ listCollectionIds(): Promise<string[]>;
127
+ /**
128
+ * Default schema loader: reads `dist/collections/<id>.schema.json`. These
129
+ * files are produced by the CMS plugin's `preBuild` hook during a real
130
+ * `root build`. In dev there is no JSON file on disk, so callers should
131
+ * pass a dev-aware `loadSchema` callback to the constructor (the API
132
+ * endpoints do this — they delegate to the same Vite SSR path used by
133
+ * `/cms/api/collection.get`).
134
+ */
135
+ private loadCollectionSchemaFromDist;
136
+ private readMeta;
137
+ private readDocMap;
138
+ /** Reads all shard docs and returns the concatenated MiniSearch JSON string. */
139
+ private readShards;
140
+ /** Writes shards, _docMap, _meta in one batched commit. */
141
+ private writeIndex;
142
+ /** Drops every doc under the SearchIndex subcollection. */
143
+ private wipeIndex;
144
+ /**
145
+ * Lists the full set of live (collection, slug, doc) tuples for `Drafts`,
146
+ * filtered by the include/exclude config.
147
+ */
148
+ private listAllDocs;
149
+ /**
150
+ * Lists docs modified since `lastRun` across every collection, filtered by
151
+ * the include/exclude config.
152
+ */
153
+ private listChangedDocs;
154
+ /**
155
+ * Returns true when no docs have been modified since `lastRun` AND no
156
+ * deletions are pending (i.e. the doc-id set in `_docMap` matches the live
157
+ * doc-id set across all collections).
158
+ */
159
+ hasChangesSince(lastRun: Timestamp, docMap?: DocMap | null): Promise<boolean>;
160
+ /** Orchestrates a rebuild (incremental by default; full when `force: true`). */
161
+ rebuildIndex(opts?: {
162
+ force?: boolean;
163
+ }): Promise<RebuildResult>;
164
+ private fullRebuild;
165
+ private incrementalRebuild;
166
+ /**
167
+ * Returns the cached MiniSearch index, loading it from Firestore if
168
+ * necessary. The cache is keyed off `meta.lastRun` and survives across
169
+ * requests in the same process.
170
+ */
171
+ getIndex(): Promise<CachedIndex | null>;
172
+ /** Runs a query against the loaded index. */
173
+ search(q: string, options?: {
174
+ limit?: number;
175
+ }): Promise<{
176
+ hits: SearchHit[];
177
+ meta: SearchIndexStatus;
178
+ }>;
179
+ /** Lightweight metadata read for status endpoints / settings UI. */
180
+ getStatus(): Promise<SearchIndexStatus>;
181
+ }
182
+ export {};
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Google-style query parsing and execution for the CMS search index.
3
+ *
4
+ * The CMS spotlight passes raw user input straight through to MiniSearch, which
5
+ * means quotes, leading dashes, and multiple words all get tokenized the same
6
+ * way (fuzzy + prefix on every term, OR-combined). That produces noisy results
7
+ * — typing `homepage hero` returns every doc containing `homepage` *or* a
8
+ * fuzzy/prefix match for `hero`.
9
+ *
10
+ * This module preprocesses the query string into structured parts and runs
11
+ * each part with the appropriate MiniSearch options:
12
+ *
13
+ * - `"exact phrase"` — must appear verbatim (token-aligned) in the doc;
14
+ * fuzzy + prefix disabled.
15
+ * - `bare term` — fuzzy + prefix allowed (existing behavior).
16
+ * - `-foo` / `-"x y"` — must NOT appear in matching docs.
17
+ *
18
+ * Multiple parts are AND-combined so adding more terms narrows results, just
19
+ * like Google.
20
+ */
21
+ import MiniSearch, { SearchResult } from 'minisearch';
22
+ /** Structured form of a user query string. */
23
+ export interface ParsedQuery {
24
+ /** Quoted phrases that must appear verbatim (token-aligned). */
25
+ phrases: string[];
26
+ /** Free-form terms; fuzzy + prefix matching applies. */
27
+ terms: string[];
28
+ /** Bare terms that must NOT appear in matching docs. */
29
+ excluded: string[];
30
+ /** Quoted phrases that must NOT appear in matching docs. */
31
+ excludedPhrases: string[];
32
+ }
33
+ /**
34
+ * Splits a Google-style query string into phrases / terms / exclusions.
35
+ *
36
+ * Examples:
37
+ * `foo "bar baz" -qux` -> terms=[foo], phrases=[bar baz], excluded=[qux]
38
+ * `"exact phrase only"` -> phrases=[exact phrase only]
39
+ * `-"forbidden phrase"` -> excludedPhrases=[forbidden phrase]
40
+ *
41
+ * Notes:
42
+ * - Smart quotes (U+201C / U+201D / etc.) are normalized to straight `"`.
43
+ * - An unclosed quote is treated as if closed at end-of-input (matches
44
+ * Google's behavior — the rest of the query becomes a single phrase).
45
+ * - Empty or whitespace-only quotes (`""`, `" "`) are skipped.
46
+ * - A leading `-` only marks exclusion when followed by a non-whitespace
47
+ * character; standalone `-` is dropped.
48
+ */
49
+ export declare function parseQuery(input: string): ParsedQuery;
50
+ /**
51
+ * Returns true if `phrase` appears in `text` as a contiguous run of word
52
+ * tokens. Punctuation between tokens is ignored, but token boundaries are
53
+ * required (so `foo bar` does NOT match `foobar`).
54
+ */
55
+ export declare function containsPhrase(text: string, phrase: string): boolean;
56
+ /** True if this parsed query carries no positive constraints. */
57
+ export declare function isEmptyQuery(parsed: ParsedQuery): boolean;
58
+ /**
59
+ * Runs a parsed query against a MiniSearch index using Google-style semantics:
60
+ * - phrases match as exact contiguous word runs (no fuzzy / no prefix);
61
+ * - free terms keep the index's default fuzzy + prefix behavior;
62
+ * - all positive parts are AND-combined (a doc must satisfy each one);
63
+ * - excluded terms / phrases remove docs from the result.
64
+ *
65
+ * Per-record scores from each part are summed, so a doc that matches more
66
+ * constraints ranks above one that matches fewer.
67
+ */
68
+ export declare function executeQuery(index: MiniSearch, parsed: ParsedQuery): SearchResult[];