longcelot-sheet-db 0.1.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/API.md +608 -0
- package/CHANGELOG.md +0 -0
- package/LICENSE +21 -0
- package/README.md +369 -0
- package/dist/adapter/crud.d.ts +20 -0
- package/dist/adapter/crud.d.ts.map +1 -0
- package/dist/adapter/crud.js +219 -0
- package/dist/adapter/crud.js.map +1 -0
- package/dist/adapter/sheetAdapter.d.ts +31 -0
- package/dist/adapter/sheetAdapter.d.ts.map +1 -0
- package/dist/adapter/sheetAdapter.js +110 -0
- package/dist/adapter/sheetAdapter.js.map +1 -0
- package/dist/adapter/sheetClient.d.ts +20 -0
- package/dist/adapter/sheetClient.d.ts.map +1 -0
- package/dist/adapter/sheetClient.js +112 -0
- package/dist/adapter/sheetClient.js.map +1 -0
- package/dist/auth/oauth.d.ts +15 -0
- package/dist/auth/oauth.d.ts.map +1 -0
- package/dist/auth/oauth.js +37 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/password.d.ts +7 -0
- package/dist/auth/password.d.ts.map +1 -0
- package/dist/auth/password.js +36 -0
- package/dist/auth/password.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +91 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +2 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +121 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +122 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/seed.d.ts +2 -0
- package/dist/cli/commands/seed.d.ts.map +1 -0
- package/dist/cli/commands/seed.js +119 -0
- package/dist/cli/commands/seed.js.map +1 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +106 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +2 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +152 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +2 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +91 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +46 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/errors/PermissionError.d.ts +5 -0
- package/dist/errors/PermissionError.d.ts.map +1 -0
- package/dist/errors/PermissionError.js +13 -0
- package/dist/errors/PermissionError.js.map +1 -0
- package/dist/errors/SchemaError.d.ts +5 -0
- package/dist/errors/SchemaError.d.ts.map +1 -0
- package/dist/errors/SchemaError.js +13 -0
- package/dist/errors/SchemaError.js.map +1 -0
- package/dist/errors/ValidationError.d.ts +5 -0
- package/dist/errors/ValidationError.d.ts.map +1 -0
- package/dist/errors/ValidationError.js +13 -0
- package/dist/errors/ValidationError.js.map +1 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +10 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/schema/columnBuilder.d.ts +23 -0
- package/dist/schema/columnBuilder.d.ts.map +1 -0
- package/dist/schema/columnBuilder.js +78 -0
- package/dist/schema/columnBuilder.js.map +1 -0
- package/dist/schema/defineTable.d.ts +12 -0
- package/dist/schema/defineTable.d.ts.map +1 -0
- package/dist/schema/defineTable.js +31 -0
- package/dist/schema/defineTable.js.map +1 -0
- package/dist/schema/types.d.ts +50 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +3 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/utils/env.d.ts +6 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +14 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +15 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +73 -0
package/API.md
ADDED
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
# API Documentation
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
- [Schema Definition](#schema-definition)
|
|
6
|
+
- [Column Builders](#column-builders)
|
|
7
|
+
- [Sheet Adapter](#sheet-adapter)
|
|
8
|
+
- [CRUD Operations](#crud-operations)
|
|
9
|
+
- [Authentication](#authentication)
|
|
10
|
+
- [CLI Commands](#cli-commands)
|
|
11
|
+
|
|
12
|
+
## Schema Definition
|
|
13
|
+
|
|
14
|
+
### `defineTable(config)`
|
|
15
|
+
|
|
16
|
+
Defines a table schema.
|
|
17
|
+
|
|
18
|
+
**Parameters:**
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
{
|
|
22
|
+
name: string; // Table name
|
|
23
|
+
actor: string; // Actor that owns this table
|
|
24
|
+
timestamps?: boolean; // Add _created_at, _updated_at (default: false)
|
|
25
|
+
softDelete?: boolean; // Add _deleted_at (default: false)
|
|
26
|
+
columns: {
|
|
27
|
+
[columnName: string]: ColumnBuilder | ColumnDefinition;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Returns:** `TableSchema`
|
|
33
|
+
|
|
34
|
+
**Example:**
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { defineTable, string, number } from 'longcelot-sheet-db';
|
|
38
|
+
|
|
39
|
+
const bookingsSchema = defineTable({
|
|
40
|
+
name: 'bookings',
|
|
41
|
+
actor: 'user',
|
|
42
|
+
timestamps: true,
|
|
43
|
+
columns: {
|
|
44
|
+
booking_id: string().required().unique(),
|
|
45
|
+
price: number().min(0),
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Column Builders
|
|
51
|
+
|
|
52
|
+
### `string()`
|
|
53
|
+
|
|
54
|
+
Creates a string column.
|
|
55
|
+
|
|
56
|
+
**Modifiers:**
|
|
57
|
+
|
|
58
|
+
- `.required()` - Cannot be null
|
|
59
|
+
- `.unique()` - Must be unique
|
|
60
|
+
- `.default(value)` - Default value
|
|
61
|
+
- `.min(length)` - Minimum length
|
|
62
|
+
- `.max(length)` - Maximum length
|
|
63
|
+
- `.enum(values)` - Allowed values
|
|
64
|
+
- `.pattern(regex)` - Regex validation
|
|
65
|
+
- `.primary()` - Primary key
|
|
66
|
+
- `.readonly()` - Cannot be updated
|
|
67
|
+
- `.ref(table.column)` - Foreign key reference
|
|
68
|
+
- `.index()` - Create index
|
|
69
|
+
|
|
70
|
+
**Example:**
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
email: string().required().unique().min(5).max(100)
|
|
74
|
+
status: string().enum(['active', 'inactive']).default('active')
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `number()`
|
|
78
|
+
|
|
79
|
+
Creates a number column.
|
|
80
|
+
|
|
81
|
+
**Modifiers:**
|
|
82
|
+
|
|
83
|
+
- `.required()`
|
|
84
|
+
- `.unique()`
|
|
85
|
+
- `.default(value)`
|
|
86
|
+
- `.min(value)` - Minimum value
|
|
87
|
+
- `.max(value)` - Maximum value
|
|
88
|
+
|
|
89
|
+
**Example:**
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
age: number().min(0).max(120)
|
|
93
|
+
price: number().min(0).required()
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### `boolean()`
|
|
97
|
+
|
|
98
|
+
Creates a boolean column.
|
|
99
|
+
|
|
100
|
+
**Modifiers:**
|
|
101
|
+
|
|
102
|
+
- `.required()`
|
|
103
|
+
- `.default(value)` - true or false
|
|
104
|
+
|
|
105
|
+
**Example:**
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
is_active: boolean().default(true)
|
|
109
|
+
verified: boolean().required()
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `date()`
|
|
113
|
+
|
|
114
|
+
Creates a date column (stored as ISO string).
|
|
115
|
+
|
|
116
|
+
**Modifiers:**
|
|
117
|
+
|
|
118
|
+
- `.required()`
|
|
119
|
+
- `.default(value)`
|
|
120
|
+
|
|
121
|
+
**Example:**
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
birth_date: date().required()
|
|
125
|
+
expires_at: date()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `json()`
|
|
129
|
+
|
|
130
|
+
Creates a JSON column (stored as JSON string).
|
|
131
|
+
|
|
132
|
+
**Modifiers:**
|
|
133
|
+
|
|
134
|
+
- `.required()`
|
|
135
|
+
- `.default(value)`
|
|
136
|
+
|
|
137
|
+
**Example:**
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
metadata: json()
|
|
141
|
+
settings: json().default({})
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Sheet Adapter
|
|
145
|
+
|
|
146
|
+
### `createSheetAdapter(config)`
|
|
147
|
+
|
|
148
|
+
Creates a new sheet adapter instance.
|
|
149
|
+
|
|
150
|
+
**Parameters:**
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
{
|
|
154
|
+
adminSheetId: string;
|
|
155
|
+
credentials: {
|
|
156
|
+
clientId: string;
|
|
157
|
+
clientSecret: string;
|
|
158
|
+
redirectUri: string;
|
|
159
|
+
};
|
|
160
|
+
tokens: any; // OAuth tokens
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Returns:** `SheetAdapter`
|
|
165
|
+
|
|
166
|
+
**Example:**
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const adapter = createSheetAdapter({
|
|
170
|
+
adminSheetId: process.env.ADMIN_SHEET_ID,
|
|
171
|
+
credentials: {
|
|
172
|
+
clientId: process.env.GOOGLE_CLIENT_ID,
|
|
173
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
174
|
+
redirectUri: process.env.GOOGLE_REDIRECT_URI,
|
|
175
|
+
},
|
|
176
|
+
tokens: userTokens,
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### `adapter.registerSchema(schema)`
|
|
181
|
+
|
|
182
|
+
Registers a single schema.
|
|
183
|
+
|
|
184
|
+
**Parameters:**
|
|
185
|
+
|
|
186
|
+
- `schema: TableSchema`
|
|
187
|
+
|
|
188
|
+
**Example:**
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
adapter.registerSchema(bookingsSchema);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### `adapter.registerSchemas(schemas)`
|
|
195
|
+
|
|
196
|
+
Registers multiple schemas at once.
|
|
197
|
+
|
|
198
|
+
**Parameters:**
|
|
199
|
+
|
|
200
|
+
- `schemas: TableSchema[]`
|
|
201
|
+
|
|
202
|
+
**Example:**
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
adapter.registerSchemas([usersSchema, bookingsSchema, paymentsSchema]);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### `adapter.withContext(context)`
|
|
209
|
+
|
|
210
|
+
Creates a new adapter instance with user context.
|
|
211
|
+
|
|
212
|
+
**Parameters:**
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
{
|
|
216
|
+
userId: string;
|
|
217
|
+
role: string;
|
|
218
|
+
actorSheetId?: string;
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Returns:** `SheetAdapter` with context
|
|
223
|
+
|
|
224
|
+
**Example:**
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
const userContext = adapter.withContext({
|
|
228
|
+
userId: 'user_123',
|
|
229
|
+
role: 'user',
|
|
230
|
+
actorSheetId: 'sheet-id-xyz',
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### `adapter.table(tableName)`
|
|
235
|
+
|
|
236
|
+
Gets CRUD operations for a table.
|
|
237
|
+
|
|
238
|
+
**Parameters:**
|
|
239
|
+
|
|
240
|
+
- `tableName: string`
|
|
241
|
+
|
|
242
|
+
**Returns:** `CRUDOperations`
|
|
243
|
+
|
|
244
|
+
**Example:**
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
const bookings = adapter.table('bookings');
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### `adapter.createUserSheet(userId, role, email)`
|
|
251
|
+
|
|
252
|
+
Creates a new sheet for a user.
|
|
253
|
+
|
|
254
|
+
**Parameters:**
|
|
255
|
+
|
|
256
|
+
- `userId: string` - Unique user ID
|
|
257
|
+
- `role: string` - User role/actor
|
|
258
|
+
- `email: string` - User email
|
|
259
|
+
|
|
260
|
+
**Returns:** `Promise<string>` - Sheet ID
|
|
261
|
+
|
|
262
|
+
**Example:**
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
const sheetId = await adapter.createUserSheet('user_123', 'student', 'student@school.com');
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### `adapter.syncSchema(schema)`
|
|
269
|
+
|
|
270
|
+
Syncs a schema to Google Sheets.
|
|
271
|
+
|
|
272
|
+
**Parameters:**
|
|
273
|
+
|
|
274
|
+
- `schema: TableSchema`
|
|
275
|
+
|
|
276
|
+
**Returns:** `Promise<void>`
|
|
277
|
+
|
|
278
|
+
**Example:**
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
await adapter.syncSchema(bookingsSchema);
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## CRUD Operations
|
|
285
|
+
|
|
286
|
+
### `table.create(data)`
|
|
287
|
+
|
|
288
|
+
Creates a new row.
|
|
289
|
+
|
|
290
|
+
**Parameters:**
|
|
291
|
+
|
|
292
|
+
- `data: Record<string, any>` - Row data
|
|
293
|
+
|
|
294
|
+
**Returns:** `Promise<Record<string, any>>` - Created row with generated fields
|
|
295
|
+
|
|
296
|
+
**Example:**
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
const booking = await table.create({
|
|
300
|
+
booking_id: 'bk_001',
|
|
301
|
+
service: 'Consultation',
|
|
302
|
+
date: new Date().toISOString(),
|
|
303
|
+
price: 100,
|
|
304
|
+
});
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### `table.findMany(options)`
|
|
308
|
+
|
|
309
|
+
Finds multiple rows.
|
|
310
|
+
|
|
311
|
+
**Parameters:**
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
{
|
|
315
|
+
where?: Record<string, any>;
|
|
316
|
+
limit?: number;
|
|
317
|
+
offset?: number;
|
|
318
|
+
orderBy?: string;
|
|
319
|
+
order?: 'asc' | 'desc';
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Returns:** `Promise<Record<string, any>[]>`
|
|
324
|
+
|
|
325
|
+
**Example:**
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
const bookings = await table.findMany({
|
|
329
|
+
where: { status: 'pending' },
|
|
330
|
+
orderBy: 'date',
|
|
331
|
+
order: 'desc',
|
|
332
|
+
limit: 10,
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### `table.findOne(options)`
|
|
337
|
+
|
|
338
|
+
Finds a single row.
|
|
339
|
+
|
|
340
|
+
**Parameters:**
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
{
|
|
344
|
+
where?: Record<string, any>;
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Returns:** `Promise<Record<string, any> | null>`
|
|
349
|
+
|
|
350
|
+
**Example:**
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
const booking = await table.findOne({
|
|
354
|
+
where: { booking_id: 'bk_001' },
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### `table.update(options)`
|
|
359
|
+
|
|
360
|
+
Updates rows matching criteria.
|
|
361
|
+
|
|
362
|
+
**Parameters:**
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
{
|
|
366
|
+
where: Record<string, any>;
|
|
367
|
+
data: Record<string, any>;
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**Returns:** `Promise<number>` - Number of rows updated
|
|
372
|
+
|
|
373
|
+
**Example:**
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
const updated = await table.update({
|
|
377
|
+
where: { booking_id: 'bk_001' },
|
|
378
|
+
data: { status: 'confirmed' },
|
|
379
|
+
});
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### `table.delete(options)`
|
|
383
|
+
|
|
384
|
+
Deletes rows matching criteria.
|
|
385
|
+
|
|
386
|
+
**Parameters:**
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
{
|
|
390
|
+
where: Record<string, any>;
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
**Returns:** `Promise<number>` - Number of rows deleted
|
|
395
|
+
|
|
396
|
+
**Example:**
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
const deleted = await table.delete({
|
|
400
|
+
where: { booking_id: 'bk_001' },
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Authentication
|
|
405
|
+
|
|
406
|
+
### `createOAuthManager(config)`
|
|
407
|
+
|
|
408
|
+
Creates an OAuth manager.
|
|
409
|
+
|
|
410
|
+
**Parameters:**
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
{
|
|
414
|
+
clientId: string;
|
|
415
|
+
clientSecret: string;
|
|
416
|
+
redirectUri: string;
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Returns:** `OAuthManager`
|
|
421
|
+
|
|
422
|
+
### `oauth.getAuthUrl()`
|
|
423
|
+
|
|
424
|
+
Gets the OAuth authorization URL.
|
|
425
|
+
|
|
426
|
+
**Returns:** `string`
|
|
427
|
+
|
|
428
|
+
**Example:**
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
const authUrl = oauth.getAuthUrl();
|
|
432
|
+
// Redirect user to authUrl
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### `oauth.getTokens(code)`
|
|
436
|
+
|
|
437
|
+
Exchanges authorization code for tokens.
|
|
438
|
+
|
|
439
|
+
**Parameters:**
|
|
440
|
+
|
|
441
|
+
- `code: string` - Authorization code from OAuth callback
|
|
442
|
+
|
|
443
|
+
**Returns:** `Promise<any>` - OAuth tokens
|
|
444
|
+
|
|
445
|
+
### `oauth.refreshTokens(refreshToken)`
|
|
446
|
+
|
|
447
|
+
Refreshes expired tokens.
|
|
448
|
+
|
|
449
|
+
**Parameters:**
|
|
450
|
+
|
|
451
|
+
- `refreshToken: string`
|
|
452
|
+
|
|
453
|
+
**Returns:** `Promise<any>` - New tokens
|
|
454
|
+
|
|
455
|
+
### `oauth.verifyToken(idToken)`
|
|
456
|
+
|
|
457
|
+
Verifies an ID token.
|
|
458
|
+
|
|
459
|
+
**Parameters:**
|
|
460
|
+
|
|
461
|
+
- `idToken: string`
|
|
462
|
+
|
|
463
|
+
**Returns:** `Promise<any>` - Token payload
|
|
464
|
+
|
|
465
|
+
### `hashPassword(password)`
|
|
466
|
+
|
|
467
|
+
Hashes a password using bcrypt.
|
|
468
|
+
|
|
469
|
+
**Parameters:**
|
|
470
|
+
|
|
471
|
+
- `password: string`
|
|
472
|
+
|
|
473
|
+
**Returns:** `Promise<string>` - Hashed password
|
|
474
|
+
|
|
475
|
+
**Example:**
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
const hash = await hashPassword('SecurePass123!');
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### `comparePassword(password, hash)`
|
|
482
|
+
|
|
483
|
+
Compares a password with a hash.
|
|
484
|
+
|
|
485
|
+
**Parameters:**
|
|
486
|
+
|
|
487
|
+
- `password: string` - Plain text password
|
|
488
|
+
- `hash: string` - Hashed password
|
|
489
|
+
|
|
490
|
+
**Returns:** `Promise<boolean>`
|
|
491
|
+
|
|
492
|
+
**Example:**
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
const isValid = await comparePassword('SecurePass123!', hash);
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### `validatePasswordStrength(password)`
|
|
499
|
+
|
|
500
|
+
Validates password strength.
|
|
501
|
+
|
|
502
|
+
**Parameters:**
|
|
503
|
+
|
|
504
|
+
- `password: string`
|
|
505
|
+
|
|
506
|
+
**Returns:**
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
{
|
|
510
|
+
valid: boolean;
|
|
511
|
+
errors: string[];
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
**Example:**
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
const { valid, errors } = validatePasswordStrength('weak');
|
|
519
|
+
if (!valid) {
|
|
520
|
+
console.log(errors); // ["Password must be at least 8 characters long", ...]
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
## CLI Commands
|
|
525
|
+
|
|
526
|
+
### `sheet-db init`
|
|
527
|
+
|
|
528
|
+
Initializes a new longcelot-sheet-db project.
|
|
529
|
+
|
|
530
|
+
**Creates:**
|
|
531
|
+
|
|
532
|
+
- `sheet-db.config.ts`
|
|
533
|
+
- `.env`
|
|
534
|
+
- `schemas/` directory
|
|
535
|
+
|
|
536
|
+
### `sheet-db generate <table-name>`
|
|
537
|
+
|
|
538
|
+
Generates a new table schema interactively.
|
|
539
|
+
|
|
540
|
+
**Example:**
|
|
541
|
+
|
|
542
|
+
```bash
|
|
543
|
+
pnpm sheet-db generate bookings
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### `sheet-db sync`
|
|
547
|
+
|
|
548
|
+
Syncs all schemas to Google Sheets.
|
|
549
|
+
|
|
550
|
+
**Actions:**
|
|
551
|
+
|
|
552
|
+
- Creates missing sheets
|
|
553
|
+
- Adds missing columns
|
|
554
|
+
- Never deletes existing data
|
|
555
|
+
|
|
556
|
+
### `sheet-db validate`
|
|
557
|
+
|
|
558
|
+
Validates all schemas.
|
|
559
|
+
|
|
560
|
+
**Checks:**
|
|
561
|
+
|
|
562
|
+
- Duplicate table names
|
|
563
|
+
- Invalid modifiers
|
|
564
|
+
- Unknown actors
|
|
565
|
+
- Missing required fields
|
|
566
|
+
|
|
567
|
+
## Type Definitions
|
|
568
|
+
|
|
569
|
+
### `TableSchema`
|
|
570
|
+
|
|
571
|
+
```typescript
|
|
572
|
+
interface TableSchema {
|
|
573
|
+
name: string;
|
|
574
|
+
actor: string;
|
|
575
|
+
timestamps?: boolean;
|
|
576
|
+
softDelete?: boolean;
|
|
577
|
+
columns: Record<string, ColumnDefinition>;
|
|
578
|
+
}
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### `ColumnDefinition`
|
|
582
|
+
|
|
583
|
+
```typescript
|
|
584
|
+
interface ColumnDefinition {
|
|
585
|
+
type: 'string' | 'number' | 'boolean' | 'date' | 'json';
|
|
586
|
+
required?: boolean;
|
|
587
|
+
unique?: boolean;
|
|
588
|
+
default?: any;
|
|
589
|
+
min?: number;
|
|
590
|
+
max?: number;
|
|
591
|
+
enum?: any[];
|
|
592
|
+
pattern?: RegExp;
|
|
593
|
+
readonly?: boolean;
|
|
594
|
+
primary?: boolean;
|
|
595
|
+
ref?: string;
|
|
596
|
+
index?: boolean;
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### `UserContext`
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
interface UserContext {
|
|
604
|
+
userId: string;
|
|
605
|
+
role: string;
|
|
606
|
+
actorSheetId?: string;
|
|
607
|
+
}
|
|
608
|
+
```
|
package/CHANGELOG.md
ADDED
|
File without changes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Longcelot
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|