digital-objects 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +25 -0
- package/LICENSE +21 -0
- package/README.md +476 -0
- package/dist/ai-database-adapter.d.ts +49 -0
- package/dist/ai-database-adapter.d.ts.map +1 -0
- package/dist/ai-database-adapter.js +89 -0
- package/dist/ai-database-adapter.js.map +1 -0
- package/dist/errors.d.ts +47 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +72 -0
- package/dist/errors.js.map +1 -0
- package/dist/http-schemas.d.ts +165 -0
- package/dist/http-schemas.d.ts.map +1 -0
- package/dist/http-schemas.js +55 -0
- package/dist/http-schemas.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/linguistic.d.ts +54 -0
- package/dist/linguistic.d.ts.map +1 -0
- package/dist/linguistic.js +226 -0
- package/dist/linguistic.js.map +1 -0
- package/dist/memory-provider.d.ts +46 -0
- package/dist/memory-provider.d.ts.map +1 -0
- package/dist/memory-provider.js +279 -0
- package/dist/memory-provider.js.map +1 -0
- package/dist/ns-client.d.ts +88 -0
- package/dist/ns-client.d.ts.map +1 -0
- package/dist/ns-client.js +253 -0
- package/dist/ns-client.js.map +1 -0
- package/dist/ns-exports.d.ts +23 -0
- package/dist/ns-exports.d.ts.map +1 -0
- package/dist/ns-exports.js +21 -0
- package/dist/ns-exports.js.map +1 -0
- package/dist/ns.d.ts +60 -0
- package/dist/ns.d.ts.map +1 -0
- package/dist/ns.js +818 -0
- package/dist/ns.js.map +1 -0
- package/dist/r2-persistence.d.ts +112 -0
- package/dist/r2-persistence.d.ts.map +1 -0
- package/dist/r2-persistence.js +252 -0
- package/dist/r2-persistence.js.map +1 -0
- package/dist/schema-validation.d.ts +80 -0
- package/dist/schema-validation.d.ts.map +1 -0
- package/dist/schema-validation.js +233 -0
- package/dist/schema-validation.js.map +1 -0
- package/dist/types.d.ts +184 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +26 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
- package/src/ai-database-adapter.test.ts +610 -0
- package/src/ai-database-adapter.ts +189 -0
- package/src/benchmark.test.ts +109 -0
- package/src/errors.ts +91 -0
- package/src/http-schemas.ts +67 -0
- package/src/index.ts +87 -0
- package/src/linguistic.test.ts +1107 -0
- package/src/linguistic.ts +253 -0
- package/src/memory-provider.ts +470 -0
- package/src/ns-client.test.ts +1360 -0
- package/src/ns-client.ts +342 -0
- package/src/ns-exports.ts +23 -0
- package/src/ns.test.ts +1381 -0
- package/src/ns.ts +1215 -0
- package/src/provider.test.ts +675 -0
- package/src/r2-persistence.test.ts +263 -0
- package/src/r2-persistence.ts +367 -0
- package/src/schema-validation.test.ts +167 -0
- package/src/schema-validation.ts +330 -0
- package/src/types.ts +252 -0
- package/test/action-status.test.ts +42 -0
- package/test/batch-limits.test.ts +165 -0
- package/test/docs.test.ts +48 -0
- package/test/errors.test.ts +148 -0
- package/test/http-validation.test.ts +401 -0
- package/test/ns-client-errors.test.ts +208 -0
- package/test/ns-namespace.test.ts +307 -0
- package/test/performance.test.ts +168 -0
- package/test/schema-validation-error.test.ts +213 -0
- package/test/schema-validation.test.ts +440 -0
- package/test/search-escaping.test.ts +359 -0
- package/test/security.test.ts +322 -0
- package/tsconfig.json +10 -0
- package/wrangler.jsonc +16 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linguistic utilities for auto-deriving noun and verb forms
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Derive noun forms from a PascalCase name
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* deriveNoun('Post') => { singular: 'post', plural: 'posts', slug: 'post' }
|
|
10
|
+
* deriveNoun('BlogPost') => { singular: 'blog post', plural: 'blog posts', slug: 'blog-post' }
|
|
11
|
+
* deriveNoun('Person') => { singular: 'person', plural: 'persons', slug: 'person' }
|
|
12
|
+
*/
|
|
13
|
+
export function deriveNoun(name: string): { singular: string; plural: string; slug: string } {
|
|
14
|
+
// Convert PascalCase to words
|
|
15
|
+
const words = name
|
|
16
|
+
.replace(/([A-Z])/g, ' $1')
|
|
17
|
+
.trim()
|
|
18
|
+
.toLowerCase()
|
|
19
|
+
const singular = words
|
|
20
|
+
const slug = words.replace(/\s+/g, '-')
|
|
21
|
+
const plural = pluralize(singular)
|
|
22
|
+
|
|
23
|
+
return { singular, plural, slug }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Pluralize a word
|
|
28
|
+
*
|
|
29
|
+
* Handles common English pluralization rules:
|
|
30
|
+
* - Words ending in 's', 'x', 'z', 'ch', 'sh' -> add 'es'
|
|
31
|
+
* - Words ending in consonant + 'y' -> replace 'y' with 'ies'
|
|
32
|
+
* - Words ending in 'f' or 'fe' -> replace with 'ves'
|
|
33
|
+
* - Special cases (person->people, child->children, etc.)
|
|
34
|
+
* - Default: add 's'
|
|
35
|
+
*/
|
|
36
|
+
export function pluralize(word: string): string {
|
|
37
|
+
// Handle multi-word phrases (pluralize last word only)
|
|
38
|
+
const parts = word.split(' ')
|
|
39
|
+
if (parts.length > 1) {
|
|
40
|
+
const lastIdx = parts.length - 1
|
|
41
|
+
parts[lastIdx] = pluralize(parts[lastIdx]!)
|
|
42
|
+
return parts.join(' ')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const w = word.toLowerCase()
|
|
46
|
+
|
|
47
|
+
// Irregular plurals
|
|
48
|
+
const irregulars: Record<string, string> = {
|
|
49
|
+
person: 'people',
|
|
50
|
+
child: 'children',
|
|
51
|
+
man: 'men',
|
|
52
|
+
woman: 'women',
|
|
53
|
+
foot: 'feet',
|
|
54
|
+
tooth: 'teeth',
|
|
55
|
+
goose: 'geese',
|
|
56
|
+
mouse: 'mice',
|
|
57
|
+
ox: 'oxen',
|
|
58
|
+
index: 'indices',
|
|
59
|
+
vertex: 'vertices',
|
|
60
|
+
matrix: 'matrices',
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (irregulars[w]) return irregulars[w]
|
|
64
|
+
|
|
65
|
+
// Words ending in 's', 'x', 'z', 'ch', 'sh' -> add 'es'
|
|
66
|
+
if (/[sxz]$/.test(w) || /[sc]h$/.test(w)) {
|
|
67
|
+
return w + 'es'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Words ending in consonant + 'y' -> replace 'y' with 'ies'
|
|
71
|
+
if (/[^aeiou]y$/.test(w)) {
|
|
72
|
+
return w.slice(0, -1) + 'ies'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Words ending in 'f' -> replace with 'ves'
|
|
76
|
+
if (/f$/.test(w)) {
|
|
77
|
+
return w.slice(0, -1) + 'ves'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Words ending in 'fe' -> replace with 'ves'
|
|
81
|
+
if (/fe$/.test(w)) {
|
|
82
|
+
return w.slice(0, -2) + 'ves'
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Default: add 's'
|
|
86
|
+
return w + 's'
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Singularize a word (reverse of pluralize)
|
|
91
|
+
*/
|
|
92
|
+
export function singularize(word: string): string {
|
|
93
|
+
// Handle multi-word phrases
|
|
94
|
+
const parts = word.split(' ')
|
|
95
|
+
if (parts.length > 1) {
|
|
96
|
+
const lastIdx = parts.length - 1
|
|
97
|
+
parts[lastIdx] = singularize(parts[lastIdx]!)
|
|
98
|
+
return parts.join(' ')
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const w = word.toLowerCase()
|
|
102
|
+
|
|
103
|
+
// Irregular singulars (reverse of irregulars)
|
|
104
|
+
const irregulars: Record<string, string> = {
|
|
105
|
+
people: 'person',
|
|
106
|
+
children: 'child',
|
|
107
|
+
men: 'man',
|
|
108
|
+
women: 'woman',
|
|
109
|
+
feet: 'foot',
|
|
110
|
+
teeth: 'tooth',
|
|
111
|
+
geese: 'goose',
|
|
112
|
+
mice: 'mouse',
|
|
113
|
+
oxen: 'ox',
|
|
114
|
+
indices: 'index',
|
|
115
|
+
vertices: 'vertex',
|
|
116
|
+
matrices: 'matrix',
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (irregulars[w]) return irregulars[w]
|
|
120
|
+
|
|
121
|
+
// Words ending in 'ies' -> replace with 'y'
|
|
122
|
+
if (/ies$/.test(w)) {
|
|
123
|
+
return w.slice(0, -3) + 'y'
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Words ending in 'ves' -> replace with 'f' or 'fe'
|
|
127
|
+
if (/ves$/.test(w)) {
|
|
128
|
+
// Default to 'f' (most common, e.g., 'leaves' -> 'leaf')
|
|
129
|
+
const fSingular = w.slice(0, -3) + 'f'
|
|
130
|
+
return fSingular
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Words ending in 'es' (but not 'ies' or 'ves')
|
|
134
|
+
if (/[sxz]es$/.test(w) || /[sc]hes$/.test(w)) {
|
|
135
|
+
return w.slice(0, -2)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Words ending in 's' (but not 'es')
|
|
139
|
+
if (/s$/.test(w) && !/ss$/.test(w)) {
|
|
140
|
+
return w.slice(0, -1)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return w
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Derive verb conjugations from base form
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* deriveVerb('create') => {
|
|
151
|
+
* action: 'create',
|
|
152
|
+
* act: 'creates',
|
|
153
|
+
* activity: 'creating',
|
|
154
|
+
* event: 'created',
|
|
155
|
+
* reverseBy: 'createdBy',
|
|
156
|
+
* reverseAt: 'createdAt'
|
|
157
|
+
* }
|
|
158
|
+
*/
|
|
159
|
+
export function deriveVerb(name: string): {
|
|
160
|
+
action: string
|
|
161
|
+
act: string
|
|
162
|
+
activity: string
|
|
163
|
+
event: string
|
|
164
|
+
reverseBy: string
|
|
165
|
+
reverseAt: string
|
|
166
|
+
reverseIn: string
|
|
167
|
+
} {
|
|
168
|
+
const base = name.toLowerCase()
|
|
169
|
+
|
|
170
|
+
// Known irregular verbs
|
|
171
|
+
const irregulars: Record<string, { act: string; activity: string; event: string }> = {
|
|
172
|
+
write: { act: 'writes', activity: 'writing', event: 'written' },
|
|
173
|
+
read: { act: 'reads', activity: 'reading', event: 'read' },
|
|
174
|
+
run: { act: 'runs', activity: 'running', event: 'run' },
|
|
175
|
+
begin: { act: 'begins', activity: 'beginning', event: 'begun' },
|
|
176
|
+
do: { act: 'does', activity: 'doing', event: 'done' },
|
|
177
|
+
go: { act: 'goes', activity: 'going', event: 'gone' },
|
|
178
|
+
have: { act: 'has', activity: 'having', event: 'had' },
|
|
179
|
+
be: { act: 'is', activity: 'being', event: 'been' },
|
|
180
|
+
set: { act: 'sets', activity: 'setting', event: 'set' },
|
|
181
|
+
get: { act: 'gets', activity: 'getting', event: 'got' },
|
|
182
|
+
put: { act: 'puts', activity: 'putting', event: 'put' },
|
|
183
|
+
cut: { act: 'cuts', activity: 'cutting', event: 'cut' },
|
|
184
|
+
hit: { act: 'hits', activity: 'hitting', event: 'hit' },
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (irregulars[base]) {
|
|
188
|
+
const irr = irregulars[base]
|
|
189
|
+
return {
|
|
190
|
+
action: base,
|
|
191
|
+
act: irr.act,
|
|
192
|
+
activity: irr.activity,
|
|
193
|
+
event: irr.event,
|
|
194
|
+
reverseBy: `${irr.event}By`,
|
|
195
|
+
reverseAt: `${irr.event}At`,
|
|
196
|
+
reverseIn: `${irr.event}In`,
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Regular verb conjugations
|
|
201
|
+
let act: string
|
|
202
|
+
let activity: string
|
|
203
|
+
let event: string
|
|
204
|
+
|
|
205
|
+
// Third person singular (act)
|
|
206
|
+
if (
|
|
207
|
+
base.endsWith('s') ||
|
|
208
|
+
base.endsWith('x') ||
|
|
209
|
+
base.endsWith('z') ||
|
|
210
|
+
base.endsWith('ch') ||
|
|
211
|
+
base.endsWith('sh')
|
|
212
|
+
) {
|
|
213
|
+
act = base + 'es'
|
|
214
|
+
} else if (base.endsWith('y') && !/[aeiou]y$/.test(base)) {
|
|
215
|
+
act = base.slice(0, -1) + 'ies'
|
|
216
|
+
} else {
|
|
217
|
+
act = base + 's'
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Present participle (activity) - gerund
|
|
221
|
+
if (base.endsWith('e') && !base.endsWith('ee')) {
|
|
222
|
+
activity = base.slice(0, -1) + 'ing'
|
|
223
|
+
} else if (base.endsWith('ie')) {
|
|
224
|
+
activity = base.slice(0, -2) + 'ying'
|
|
225
|
+
} else if (/[^aeiou][aeiou][bcdfghlmnprstvwz]$/.test(base) && base.length <= 6) {
|
|
226
|
+
// Double final consonant for short words (CVC pattern)
|
|
227
|
+
activity = base + base[base.length - 1] + 'ing'
|
|
228
|
+
} else {
|
|
229
|
+
activity = base + 'ing'
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Past participle (event)
|
|
233
|
+
if (base.endsWith('e')) {
|
|
234
|
+
event = base + 'd'
|
|
235
|
+
} else if (base.endsWith('y') && !/[aeiou]y$/.test(base)) {
|
|
236
|
+
event = base.slice(0, -1) + 'ied'
|
|
237
|
+
} else if (/[^aeiou][aeiou][bcdfghlmnprstvwz]$/.test(base) && base.length <= 6) {
|
|
238
|
+
// Double final consonant for short words
|
|
239
|
+
event = base + base[base.length - 1] + 'ed'
|
|
240
|
+
} else {
|
|
241
|
+
event = base + 'ed'
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
action: base,
|
|
246
|
+
act,
|
|
247
|
+
activity,
|
|
248
|
+
event,
|
|
249
|
+
reverseBy: `${event}By`,
|
|
250
|
+
reverseAt: `${event}At`,
|
|
251
|
+
reverseIn: `${event}In`,
|
|
252
|
+
}
|
|
253
|
+
}
|