tina4-nodejs 3.10.66 → 3.10.67
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/CLAUDE.md +28 -2
- package/package.json +1 -1
- package/packages/orm/src/baseModel.ts +14 -3
package/CLAUDE.md
CHANGED
|
@@ -153,13 +153,39 @@ Database layer with auto-CRUD generation, seeding, fake data, and SQL translatio
|
|
|
153
153
|
- `fakeData.ts` — ORM-aware fake data extending core (adds `forField()` with column-name heuristics)
|
|
154
154
|
- `seeder.ts` — Database seeding (`seedTable` for raw SQL, `seedOrm` for model-based)
|
|
155
155
|
- `sqlTranslation.ts` — Cross-engine SQL translator (`SQLTranslator`) and TTL query cache (`QueryCache`)
|
|
156
|
-
- `
|
|
157
|
-
- `
|
|
156
|
+
- **Instance methods:** `save()`, `delete()`, `forceDelete()`, `restore()`, `load(sql, params?, include?): boolean` (selectOne into self), `validate(): string[]`, `toDict(include?): Record`, `toObject(): Record`, `toArray(): unknown[]`, `toList(): unknown[]`, `toJson(): string`, `hasOne()`, `hasMany()`, `belongsTo()`
|
|
157
|
+
- **Static methods:** `find(id, include?)`, `findById(id, include?)`, `findAll(where?, params?, include?)`, `findOrFail(id)`, `create(data)`, `select(sql, params?)`, `selectOne(sql, params?, include?)`, `count(conditions?, params?)`, `withTrashed(conditions?, params?)`, `scope(name, filterSql, params?)`, `createTable()`, `query(): QueryBuilder`
|
|
158
158
|
- QueryBuilder supports `toMongo()` for generating MongoDB query documents from the same fluent API
|
|
159
159
|
- `getNextId(table: string, pkColumn?: string, generatorName?: string): Promise<number>` — Race-safe ID generation using atomic sequence table (`tina4_sequences`). SQLite/MySQL/MSSQL use `tina4_sequences` with atomic UPDATE+SELECT. PostgreSQL auto-creates sequences if missing. Firebird uses existing generators (unchanged).
|
|
160
160
|
|
|
161
161
|
**`tina4_sequences` table** — Auto-created by `getNextId()` on first use for SQLite, MySQL, and MSSQL. Stores the current sequence value per table. Do not modify this table manually.
|
|
162
162
|
|
|
163
|
+
### File Uploads
|
|
164
|
+
|
|
165
|
+
Multipart file uploads are available via `req.files` (array of UploadedFile objects):
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// req.files[0] =>
|
|
169
|
+
{
|
|
170
|
+
fieldName: "avatar",
|
|
171
|
+
filename: "photo.png",
|
|
172
|
+
type: "image/png",
|
|
173
|
+
content: Buffer, // raw bytes — NOT base64
|
|
174
|
+
size: 102400
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
post("/api/upload", (req, res) => {
|
|
180
|
+
const file = req.files?.find(f => f.fieldName === "avatar");
|
|
181
|
+
if (!file) return res.json({ error: "No file" }, 400);
|
|
182
|
+
fs.writeFileSync(`src/public/uploads/${file.filename}`, file.content);
|
|
183
|
+
return res.json({ ok: true });
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Max upload size: `TINA4_MAX_UPLOAD_SIZE` env var (default 10MB).
|
|
188
|
+
|
|
163
189
|
### @tina4/swagger (`packages/swagger/`)
|
|
164
190
|
Auto-generates OpenAPI 3.0 docs.
|
|
165
191
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tina4-nodejs",
|
|
3
|
-
"version": "3.10.
|
|
3
|
+
"version": "3.10.67",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Tina4 for Node.js/TypeScript — 54 built-in features, zero dependencies",
|
|
6
6
|
"keywords": ["tina4", "framework", "web", "api", "orm", "graphql", "websocket", "typescript"],
|
|
@@ -240,9 +240,20 @@ export class BaseModel {
|
|
|
240
240
|
return (this as unknown as typeof BaseModel).findById.call(this, id, include) as T | null;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
/**
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
/**
|
|
244
|
+
* Load a record into this instance via selectOne.
|
|
245
|
+
* Returns true if found and loaded, false otherwise.
|
|
246
|
+
*/
|
|
247
|
+
load(sql: string, params?: unknown[], include?: string[]): boolean {
|
|
248
|
+
const ModelClass = this.constructor as typeof BaseModel & (new (data?: Record<string, unknown>) => BaseModel);
|
|
249
|
+
const result = ModelClass.selectOne(sql, params, include);
|
|
250
|
+
if (!result) return false;
|
|
251
|
+
const data = (result as any).toJSON ? (result as any).toJSON() : result;
|
|
252
|
+
for (const [key, value] of Object.entries(data)) {
|
|
253
|
+
(this as any)[key] = value;
|
|
254
|
+
}
|
|
255
|
+
(this as any)._exists = true;
|
|
256
|
+
return true;
|
|
246
257
|
}
|
|
247
258
|
|
|
248
259
|
/**
|