@nonext/husk 0.2.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.
- package/CHANGELOG.md +148 -0
- package/LICENSE +166 -0
- package/README.md +140 -0
- package/api/public-api.md +1070 -0
- package/dist/adapter-C_0mhENy.d.ts +320 -0
- package/dist/admin/admin.css +5 -0
- package/dist/admin/index.d.ts +265 -0
- package/dist/admin/index.js +393 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/tokens.css +597 -0
- package/dist/admin/ui.d.ts +3013 -0
- package/dist/admin/ui.js +9783 -0
- package/dist/admin/ui.js.map +1 -0
- package/dist/auth/index.d.ts +4 -0
- package/dist/auth/index.js +9 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth-B2gBtHl5.d.ts +28 -0
- package/dist/can-Chy7zmx7.d.ts +69 -0
- package/dist/chunk-3I6337WJ.js +83 -0
- package/dist/chunk-3I6337WJ.js.map +1 -0
- package/dist/chunk-4Z6P3XCE.js +62 -0
- package/dist/chunk-4Z6P3XCE.js.map +1 -0
- package/dist/chunk-6E3ZS5Z5.js +1007 -0
- package/dist/chunk-6E3ZS5Z5.js.map +1 -0
- package/dist/chunk-77JDRXXU.js +3 -0
- package/dist/chunk-77JDRXXU.js.map +1 -0
- package/dist/chunk-FHYWJCG6.js +171 -0
- package/dist/chunk-FHYWJCG6.js.map +1 -0
- package/dist/chunk-JAE7HHMM.js +506 -0
- package/dist/chunk-JAE7HHMM.js.map +1 -0
- package/dist/chunk-NPDBQBLW.js +68 -0
- package/dist/chunk-NPDBQBLW.js.map +1 -0
- package/dist/chunk-ORMYARXD.js +6 -0
- package/dist/chunk-ORMYARXD.js.map +1 -0
- package/dist/chunk-R4O7APIX.js +51 -0
- package/dist/chunk-R4O7APIX.js.map +1 -0
- package/dist/chunk-ROLKRJWI.js +187 -0
- package/dist/chunk-ROLKRJWI.js.map +1 -0
- package/dist/chunk-SOTQ3WP5.js +31 -0
- package/dist/chunk-SOTQ3WP5.js.map +1 -0
- package/dist/chunk-TCFFHTY3.js +97 -0
- package/dist/chunk-TCFFHTY3.js.map +1 -0
- package/dist/chunk-TS7Y7GEZ.js +7 -0
- package/dist/chunk-TS7Y7GEZ.js.map +1 -0
- package/dist/chunk-VLGR5PZX.js +3 -0
- package/dist/chunk-VLGR5PZX.js.map +1 -0
- package/dist/chunk-ZW2PUSVS.js +40 -0
- package/dist/chunk-ZW2PUSVS.js.map +1 -0
- package/dist/chunk-ZYNBMYJ6.js +392 -0
- package/dist/chunk-ZYNBMYJ6.js.map +1 -0
- package/dist/cli/nonext-husk.js +3360 -0
- package/dist/cli/nonext-husk.js.map +1 -0
- package/dist/cli/templates/firestore.rules +393 -0
- package/dist/cli/templates/storage.rules +165 -0
- package/dist/client/index.d.ts +27 -0
- package/dist/client/index.js +15 -0
- package/dist/client/index.js.map +1 -0
- package/dist/cms-9fSA3uQV.d.ts +158 -0
- package/dist/core/index.d.ts +1267 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/entry-D3kiE8T1.d.ts +163 -0
- package/dist/field-Diyf5siF.d.ts +158 -0
- package/dist/field-type-D25Vojb0.d.ts +157 -0
- package/dist/firebase/index.d.ts +251 -0
- package/dist/firebase/index.js +991 -0
- package/dist/firebase/index.js.map +1 -0
- package/dist/index-5ylaMBUH.d.ts +155 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/permissions/index.d.ts +101 -0
- package/dist/permissions/index.js +7 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/registry-CUC25qay.d.ts +59 -0
- package/dist/richtext/index.d.ts +85 -0
- package/dist/richtext/index.js +127 -0
- package/dist/richtext/index.js.map +1 -0
- package/dist/schema/index.d.ts +50 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/server/index.d.ts +39 -0
- package/dist/server/index.js +25 -0
- package/dist/server/index.js.map +1 -0
- package/dist/types/index.d.ts +36 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/write-limits-Djmm6L3R.d.ts +215 -0
- package/package.json +136 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the media library accepts, in one place.
|
|
3
|
+
*
|
|
4
|
+
* This file is the single definition of the allowed MIME types, their file extensions and
|
|
5
|
+
* their size ceilings. Three things read it and they must not drift apart:
|
|
6
|
+
*
|
|
7
|
+
* 1. The upload path in `firebase/media-upload.ts`, which refuses a bad file before it
|
|
8
|
+
* spends a customer's bandwidth on it.
|
|
9
|
+
* 2. The admin's file input, which sets `accept` and says why a file was refused.
|
|
10
|
+
* 3. `storage.rules` and the `media/{mediaId}` block of `firestore.rules`, which are the
|
|
11
|
+
* actual enforcement. A rule cannot import TypeScript, so the two are kept in step by
|
|
12
|
+
* `media-constraints.test.ts`, which reads the rules files and fails when a type or a
|
|
13
|
+
* limit is present here and absent there.
|
|
14
|
+
*
|
|
15
|
+
* It deliberately contains no Firebase import: the constraint is a product rule, not a
|
|
16
|
+
* storage detail, and the admin has to be able to state it without crossing the adapter
|
|
17
|
+
* boundary.
|
|
18
|
+
*/
|
|
19
|
+
type MediaCategory = "image" | "video" | "audio" | "document";
|
|
20
|
+
interface MediaTypeRule {
|
|
21
|
+
/** The exact MIME type. No wildcards: see the note on `image/*` below. */
|
|
22
|
+
readonly type: string;
|
|
23
|
+
readonly category: MediaCategory;
|
|
24
|
+
readonly maxBytes: number;
|
|
25
|
+
/** Lowercase, with the dot. The first one is what a sanitized name is given. */
|
|
26
|
+
readonly extensions: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The hard ceiling, whatever the type. Large enough for a brochure or a short clip, small
|
|
30
|
+
* enough that one mistaken upload cannot fill a customer's bucket.
|
|
31
|
+
*/
|
|
32
|
+
declare const MAX_MEDIA_BYTES: number;
|
|
33
|
+
/**
|
|
34
|
+
* Images are held to a lower ceiling than the rest.
|
|
35
|
+
*
|
|
36
|
+
* A 25 MB image is never what a website wants, and since Husk stores originals only (see
|
|
37
|
+
* .docs/decisions/2026-09-18-media-variants.md) the original is what a visitor's browser
|
|
38
|
+
* eventually fetches. The limit is the one place that fact is enforced rather than hoped
|
|
39
|
+
* for.
|
|
40
|
+
*/
|
|
41
|
+
declare const MAX_IMAGE_BYTES: number;
|
|
42
|
+
/**
|
|
43
|
+
* The allowlist.
|
|
44
|
+
*
|
|
45
|
+
* Note what is missing, because each absence is a decision rather than an oversight:
|
|
46
|
+
*
|
|
47
|
+
* - `image/svg+xml`. An SVG is a script container. It is served from the Storage host, so
|
|
48
|
+
* it cannot reach a customer's own origin, but it can still be handed to a visitor as an
|
|
49
|
+
* executable document under the customer's brand. Nothing in the CMS needs it.
|
|
50
|
+
* - `image/tiff`, `image/bmp`, `video/quicktime`. No browser renders the first two and the
|
|
51
|
+
* third is a phone-camera container that no `<video>` tag can be pointed at. A file that
|
|
52
|
+
* cannot be displayed on the site it was uploaded for is a support ticket in waiting.
|
|
53
|
+
* - Everything else, including archives and office documents. Adding one is a line here,
|
|
54
|
+
* a line in `storage.rules`, and a test; that friction is the point.
|
|
55
|
+
*/
|
|
56
|
+
declare const ALLOWED_MEDIA_TYPES: readonly MediaTypeRule[];
|
|
57
|
+
/** Value for an `<input type="file">` accept attribute. The UI courtesy, not the rule. */
|
|
58
|
+
declare const MEDIA_ACCEPT_ATTRIBUTE: string;
|
|
59
|
+
/**
|
|
60
|
+
* The rule for a declared MIME type, or null when the type is not accepted.
|
|
61
|
+
*
|
|
62
|
+
* Parameters are stripped (`text/plain; charset=utf-8`) and the type is lowercased, because
|
|
63
|
+
* a browser is free to report either form and neither is the user's doing.
|
|
64
|
+
*/
|
|
65
|
+
declare function mediaTypeRule(type: string): MediaTypeRule | null;
|
|
66
|
+
declare function normalizeMediaType(type: string): string;
|
|
67
|
+
/** The extension including the dot, lowercased, or the empty string when there is none. */
|
|
68
|
+
declare function fileExtension(name: string): string;
|
|
69
|
+
type MediaRejectionCode = "type-not-allowed" | "too-large" | "empty" | "extension-mismatch";
|
|
70
|
+
interface MediaRejection {
|
|
71
|
+
code: MediaRejectionCode;
|
|
72
|
+
/** Written for an editor to read, because it is what the upload row will show. */
|
|
73
|
+
message: string;
|
|
74
|
+
}
|
|
75
|
+
interface MediaFileFacts {
|
|
76
|
+
name: string;
|
|
77
|
+
type: string;
|
|
78
|
+
size: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Why this file may not be uploaded, or null when it may.
|
|
82
|
+
*
|
|
83
|
+
* Every check here is repeated in `storage.rules`. This one exists so a refusal is
|
|
84
|
+
* immediate and explains itself; the rule exists because this one runs on the client and a
|
|
85
|
+
* client can be replaced.
|
|
86
|
+
*/
|
|
87
|
+
declare function checkMediaFile(file: MediaFileFacts): MediaRejection | null;
|
|
88
|
+
/**
|
|
89
|
+
* A file name safe to put in a Storage path.
|
|
90
|
+
*
|
|
91
|
+
* Lowercased, stripped of anything outside `[a-z0-9._-]`, with the extension preserved
|
|
92
|
+
* because the rules match on it. A name that sanitizes to nothing becomes `file`, so an
|
|
93
|
+
* upload never produces an object path ending in a bare dot.
|
|
94
|
+
*/
|
|
95
|
+
declare function safeFileName(name: string, type: string): string;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* What a single write may weigh, and how often one document may be written.
|
|
99
|
+
*
|
|
100
|
+
* Two layers, and they are not the same strength. Be exact about which is which:
|
|
101
|
+
*
|
|
102
|
+
* - **Enforced by firestore.rules.** The top-level field count of an incoming document,
|
|
103
|
+
* and a minimum interval between two writes to the same document. A rule can see both,
|
|
104
|
+
* so a client that skips the adapter is still refused. The numbers live here and are
|
|
105
|
+
* repeated in firestore.rules, because a rules file cannot import.
|
|
106
|
+
* - **Enforced by the adapter only.** Estimated document size, nesting depth, array
|
|
107
|
+
* length, and the burst limiter below. A Firestore rule cannot see the byte size of a
|
|
108
|
+
* document and cannot count a caller's writes across documents, so these catch a
|
|
109
|
+
* mistake and refuse it with a message a person can act on. They are not a guarantee
|
|
110
|
+
* against a determined client holding a Firebase config: that client's real ceiling is
|
|
111
|
+
* Firestore's own 1 MiB per document and the per-document floor in the rules.
|
|
112
|
+
*
|
|
113
|
+
* The two do not overlap, deliberately. The adapter does not repeat the per-document
|
|
114
|
+
* interval: the rules already refuse that write, repeating it here would only move the
|
|
115
|
+
* refusal earlier for callers who never needed it, and a legitimate script that creates an
|
|
116
|
+
* entry and immediately corrects it would be stopped by Husk before the database had a
|
|
117
|
+
* chance to say yes. Each guard lives at exactly one layer, and it is the layer that can
|
|
118
|
+
* see the thing it is guarding.
|
|
119
|
+
*
|
|
120
|
+
* Anything a customer can hit by accident should fail here, with a sentence naming the
|
|
121
|
+
* field, rather than at Firestore with `INVALID_ARGUMENT`.
|
|
122
|
+
*/
|
|
123
|
+
/** Firestore's own hard ceiling for one document. Nothing here may exceed it. */
|
|
124
|
+
declare const FIRESTORE_DOCUMENT_BYTES = 1048576;
|
|
125
|
+
/**
|
|
126
|
+
* Husk's ceiling, deliberately under Firestore's.
|
|
127
|
+
*
|
|
128
|
+
* The gap is headroom for the fields the adapter adds after the values are measured
|
|
129
|
+
* (`mediaRefs`, the audit stamps, the status) plus the difference between the estimate
|
|
130
|
+
* below and Firestore's own accounting, which counts field names and type tags.
|
|
131
|
+
*/
|
|
132
|
+
declare const MAX_WRITE_BYTES = 900000;
|
|
133
|
+
/** Top-level fields on an entry document. Mirrored in firestore.rules. */
|
|
134
|
+
declare const MAX_ENTRY_FIELDS = 200;
|
|
135
|
+
/** Fields on one content type. Mirrored in firestore.rules on `schemas/{slug}`. */
|
|
136
|
+
declare const MAX_CONTENT_TYPE_FIELDS = 100;
|
|
137
|
+
/** Top-level keys of one settings document. Mirrored in firestore.rules. */
|
|
138
|
+
declare const MAX_SETTINGS_FIELDS = 100;
|
|
139
|
+
/** Firestore refuses deeper nesting than this, so refusing it here names the cause. */
|
|
140
|
+
declare const MAX_NESTING_DEPTH = 20;
|
|
141
|
+
/** Items in one stored array, which in practice is a repeater or a multi-relation. */
|
|
142
|
+
declare const MAX_ARRAY_ITEMS = 1000;
|
|
143
|
+
/**
|
|
144
|
+
* The floor between two writes to the same document. Mirrored in firestore.rules.
|
|
145
|
+
*
|
|
146
|
+
* Chosen so a human cannot reach it and a loop cannot ignore it: 200 ms throttles a
|
|
147
|
+
* runaway client to five writes a second on one document, while the fastest a person can
|
|
148
|
+
* meaningfully save the same entry twice is an order of magnitude slower.
|
|
149
|
+
*/
|
|
150
|
+
declare const MIN_WRITE_INTERVAL_MS = 200;
|
|
151
|
+
/**
|
|
152
|
+
* The adapter-side burst window: at most this many writes in this many milliseconds.
|
|
153
|
+
*
|
|
154
|
+
* A loop detector, not a quota. It has to sit above everything the product does on
|
|
155
|
+
* purpose, and the product does bulk writes: a media replace rewrites the url on up to 500
|
|
156
|
+
* referencing entries, a field purge clears 250, a migration batch moves 50. Twenty writes
|
|
157
|
+
* a second is far past any of those and still nowhere near a runaway loop, which does
|
|
158
|
+
* thousands. Set it too low and the first thing it breaks is a legitimate operation.
|
|
159
|
+
*/
|
|
160
|
+
declare const WRITE_BURST_LIMIT = 200;
|
|
161
|
+
declare const WRITE_BURST_WINDOW_MS = 10000;
|
|
162
|
+
type WriteLimitCode = "too-many-fields" | "too-large" | "too-deep" | "too-many-items" | "too-fast";
|
|
163
|
+
interface WriteLimitRejection {
|
|
164
|
+
code: WriteLimitCode;
|
|
165
|
+
/** Dotted path to the offending value, or "" when the document as a whole is at fault. */
|
|
166
|
+
path: string;
|
|
167
|
+
message: string;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* A rough byte count for a value on its way to Firestore.
|
|
171
|
+
*
|
|
172
|
+
* Deliberately an estimate. Firestore's accounting adds the field name plus one byte per
|
|
173
|
+
* value and counts strings as UTF-8 plus one, and reproducing it exactly would be a second
|
|
174
|
+
* implementation to keep in step for no gain: the number is used against a ceiling that is
|
|
175
|
+
* already 148 KB below the real one. What it must not do is undercount badly, which is why
|
|
176
|
+
* strings are measured in UTF-8 bytes rather than in code units.
|
|
177
|
+
*/
|
|
178
|
+
declare function approximateBytes(value: unknown): number;
|
|
179
|
+
interface PayloadLimits {
|
|
180
|
+
/** Top-level field cap. Defaults to the entry cap. */
|
|
181
|
+
maxFields?: number;
|
|
182
|
+
/** Byte ceiling. Defaults to MAX_WRITE_BYTES. */
|
|
183
|
+
maxBytes?: number;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Checks one document's worth of values. Returns the first problem, or null.
|
|
187
|
+
*
|
|
188
|
+
* First problem rather than all of them on purpose: these are not field validation errors
|
|
189
|
+
* a form routes to inputs, they are a refusal to write at all, and the caller shows one
|
|
190
|
+
* sentence. Field validation already ran; this is the guard behind it.
|
|
191
|
+
*/
|
|
192
|
+
declare function checkWritePayload(values: Record<string, unknown>, limits?: PayloadLimits): WriteLimitRejection | null;
|
|
193
|
+
/** Reads a clock. Injected so a test does not have to sleep to cross a window. */
|
|
194
|
+
type Clock = () => number;
|
|
195
|
+
interface WriteRateLimiter {
|
|
196
|
+
/**
|
|
197
|
+
* Records an attempted write and says whether it is refused.
|
|
198
|
+
*
|
|
199
|
+
* One question only: is this process writing faster than anything but a loop would? The
|
|
200
|
+
* per-document interval is not asked here, because firestore.rules asks it of every
|
|
201
|
+
* write whether or not it came through this adapter.
|
|
202
|
+
*/
|
|
203
|
+
check(): WriteLimitRejection | null;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The adapter's burst guard.
|
|
207
|
+
*
|
|
208
|
+
* Honest about what it is: one process's memory. A second tab has its own, and a script
|
|
209
|
+
* holding the customer's Firebase config has none at all. It exists to turn a runaway loop
|
|
210
|
+
* in the admin into one clear refusal instead of a few thousand writes and a bill, and the
|
|
211
|
+
* rules-side per-document floor is what covers the case this cannot see.
|
|
212
|
+
*/
|
|
213
|
+
declare function createWriteRateLimiter(clock?: Clock): WriteRateLimiter;
|
|
214
|
+
|
|
215
|
+
export { ALLOWED_MEDIA_TYPES as A, type Clock as C, FIRESTORE_DOCUMENT_BYTES as F, MAX_ARRAY_ITEMS as M, type PayloadLimits as P, WRITE_BURST_LIMIT as W, MAX_CONTENT_TYPE_FIELDS as a, MAX_ENTRY_FIELDS as b, MAX_IMAGE_BYTES as c, MAX_MEDIA_BYTES as d, MAX_NESTING_DEPTH as e, MAX_SETTINGS_FIELDS as f, MAX_WRITE_BYTES as g, MEDIA_ACCEPT_ATTRIBUTE as h, MIN_WRITE_INTERVAL_MS as i, type MediaCategory as j, type MediaFileFacts as k, type MediaRejection as l, type MediaRejectionCode as m, type MediaTypeRule as n, WRITE_BURST_WINDOW_MS as o, type WriteLimitCode as p, type WriteLimitRejection as q, type WriteRateLimiter as r, approximateBytes as s, checkMediaFile as t, checkWritePayload as u, createWriteRateLimiter as v, fileExtension as w, mediaTypeRule as x, normalizeMediaType as y, safeFileName as z };
|
package/package.json
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nonext/husk",
|
|
3
|
+
"version": "0.2.3",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Nonext CMS (Husk): schema-driven CMS for Next.js and Firebase",
|
|
6
|
+
"license": "PolyForm-Shield-1.0.0",
|
|
7
|
+
"author": "Nonext",
|
|
8
|
+
"homepage": "https://github.com/nonext-at/nonext-husk#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/nonext-at/nonext-husk.git",
|
|
12
|
+
"directory": "packages/cms"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/nonext-at/nonext-husk/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"cms",
|
|
19
|
+
"nextjs",
|
|
20
|
+
"firebase",
|
|
21
|
+
"firestore",
|
|
22
|
+
"headless-cms"
|
|
23
|
+
],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public",
|
|
26
|
+
"provenance": false
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=22"
|
|
30
|
+
},
|
|
31
|
+
"type": "module",
|
|
32
|
+
"sideEffects": [
|
|
33
|
+
"**/*.css"
|
|
34
|
+
],
|
|
35
|
+
"bin": {
|
|
36
|
+
"nonext-husk": "./dist/cli/nonext-husk.js"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"api/public-api.md",
|
|
41
|
+
"CHANGELOG.md"
|
|
42
|
+
],
|
|
43
|
+
"exports": {
|
|
44
|
+
".": {
|
|
45
|
+
"types": "./dist/index.d.ts",
|
|
46
|
+
"default": "./dist/index.js"
|
|
47
|
+
},
|
|
48
|
+
"./admin": {
|
|
49
|
+
"types": "./dist/admin/index.d.ts",
|
|
50
|
+
"default": "./dist/admin/index.js"
|
|
51
|
+
},
|
|
52
|
+
"./admin/ui": {
|
|
53
|
+
"types": "./dist/admin/ui.d.ts",
|
|
54
|
+
"default": "./dist/admin/ui.js"
|
|
55
|
+
},
|
|
56
|
+
"./auth": {
|
|
57
|
+
"types": "./dist/auth/index.d.ts",
|
|
58
|
+
"default": "./dist/auth/index.js"
|
|
59
|
+
},
|
|
60
|
+
"./client": {
|
|
61
|
+
"types": "./dist/client/index.d.ts",
|
|
62
|
+
"default": "./dist/client/index.js"
|
|
63
|
+
},
|
|
64
|
+
"./server": {
|
|
65
|
+
"types": "./dist/server/index.d.ts",
|
|
66
|
+
"default": "./dist/server/index.js"
|
|
67
|
+
},
|
|
68
|
+
"./core": {
|
|
69
|
+
"types": "./dist/core/index.d.ts",
|
|
70
|
+
"default": "./dist/core/index.js"
|
|
71
|
+
},
|
|
72
|
+
"./permissions": {
|
|
73
|
+
"types": "./dist/permissions/index.d.ts",
|
|
74
|
+
"default": "./dist/permissions/index.js"
|
|
75
|
+
},
|
|
76
|
+
"./firebase": {
|
|
77
|
+
"types": "./dist/firebase/index.d.ts",
|
|
78
|
+
"default": "./dist/firebase/index.js"
|
|
79
|
+
},
|
|
80
|
+
"./richtext": {
|
|
81
|
+
"types": "./dist/richtext/index.d.ts",
|
|
82
|
+
"default": "./dist/richtext/index.js"
|
|
83
|
+
},
|
|
84
|
+
"./schema": {
|
|
85
|
+
"types": "./dist/schema/index.d.ts",
|
|
86
|
+
"default": "./dist/schema/index.js"
|
|
87
|
+
},
|
|
88
|
+
"./types": {
|
|
89
|
+
"types": "./dist/types/index.d.ts",
|
|
90
|
+
"default": "./dist/types/index.js"
|
|
91
|
+
},
|
|
92
|
+
"./admin.css": "./dist/admin/admin.css"
|
|
93
|
+
},
|
|
94
|
+
"peerDependencies": {
|
|
95
|
+
"firebase": "^12.0.0",
|
|
96
|
+
"next": "^16.0.0",
|
|
97
|
+
"react": "^19.0.0",
|
|
98
|
+
"react-dom": "^19.0.0"
|
|
99
|
+
},
|
|
100
|
+
"devDependencies": {
|
|
101
|
+
"@types/react": "^19.3.0",
|
|
102
|
+
"@types/react-dom": "^19.3.0",
|
|
103
|
+
"firebase": "^12.19.0",
|
|
104
|
+
"next": "^16.3.5",
|
|
105
|
+
"react": "^19.3.0",
|
|
106
|
+
"react-dom": "^19.3.0",
|
|
107
|
+
"tsup": "^8.5.1",
|
|
108
|
+
"typescript": "^5.9.3"
|
|
109
|
+
},
|
|
110
|
+
"dependencies": {
|
|
111
|
+
"@tiptap/core": "^3.31.3",
|
|
112
|
+
"@tiptap/extension-blockquote": "^3.31.3",
|
|
113
|
+
"@tiptap/extension-bold": "^3.31.3",
|
|
114
|
+
"@tiptap/extension-document": "^3.31.3",
|
|
115
|
+
"@tiptap/extension-hard-break": "^3.31.3",
|
|
116
|
+
"@tiptap/extension-heading": "^3.31.3",
|
|
117
|
+
"@tiptap/extension-italic": "^3.31.3",
|
|
118
|
+
"@tiptap/extension-link": "^3.31.3",
|
|
119
|
+
"@tiptap/extension-list": "^3.31.3",
|
|
120
|
+
"@tiptap/extension-paragraph": "^3.31.3",
|
|
121
|
+
"@tiptap/extension-strike": "^3.31.3",
|
|
122
|
+
"@tiptap/extension-text": "^3.31.3",
|
|
123
|
+
"@tiptap/extensions": "^3.31.3",
|
|
124
|
+
"@tiptap/pm": "^3.31.3",
|
|
125
|
+
"@tiptap/react": "^3.31.3",
|
|
126
|
+
"@tiptap/static-renderer": "3.31.3",
|
|
127
|
+
"lucide": "1.47.0",
|
|
128
|
+
"lucide-react": "^1.47.0",
|
|
129
|
+
"morphicons": "^1.7.1"
|
|
130
|
+
},
|
|
131
|
+
"scripts": {
|
|
132
|
+
"build": "node --eval \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsup",
|
|
133
|
+
"typecheck": "tsc --noEmit",
|
|
134
|
+
"api": "node scripts/write-public-api.mjs"
|
|
135
|
+
}
|
|
136
|
+
}
|