@warlock.js/cascade 5.24.0 → 5.25.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/CHANGELOG.md +18 -5
- package/README.md +101 -101
- package/bin/cascade.js +0 -0
- package/cjs/index.cjs +201 -71
- package/cjs/index.cjs.map +1 -1
- package/esm/contracts/database-driver.contract.d.mts +22 -1
- package/esm/contracts/database-driver.contract.d.mts.map +1 -1
- package/esm/contracts/index.d.mts +1 -1
- package/esm/data-source/data-source-registry.d.mts +8 -6
- package/esm/data-source/data-source-registry.d.mts.map +1 -1
- package/esm/data-source/data-source-registry.mjs +7 -1
- package/esm/data-source/data-source-registry.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-driver.d.mts +13 -0
- package/esm/drivers/mongodb/mongodb-driver.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-driver.mjs +71 -2
- package/esm/drivers/mongodb/mongodb-driver.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.mjs +2 -1
- package/esm/drivers/mongodb/mongodb-query-builder.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-driver.d.mts +9 -0
- package/esm/drivers/postgres/postgres-driver.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-driver.mjs +55 -7
- package/esm/drivers/postgres/postgres-driver.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.d.mts +1 -4
- package/esm/drivers/postgres/postgres-query-parser.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.mjs +4 -5
- package/esm/drivers/postgres/postgres-query-parser.mjs.map +1 -1
- package/esm/errors/unsafe-filter.error.mjs.map +1 -1
- package/esm/errors/unsafe-raw-expression.error.mjs.map +1 -1
- package/esm/errors/unsupported-lock-for-update.error.d.mts +11 -0
- package/esm/errors/unsupported-lock-for-update.error.d.mts.map +1 -0
- package/esm/errors/unsupported-lock-for-update.error.mjs +16 -0
- package/esm/errors/unsupported-lock-for-update.error.mjs.map +1 -0
- package/esm/events/model-events.mjs.map +1 -1
- package/esm/index.d.mts +3 -2
- package/esm/index.mjs +2 -1
- package/esm/migration/migration-runner.mjs.map +1 -1
- package/esm/migration/sql-grammar.mjs.map +1 -1
- package/esm/model/generate-model-id.mjs +23 -0
- package/esm/model/generate-model-id.mjs.map +1 -0
- package/esm/model/methods/delete-methods.mjs.map +1 -1
- package/esm/model/methods/meta-methods.mjs.map +1 -1
- package/esm/model/methods/query-methods.mjs +25 -2
- package/esm/model/methods/query-methods.mjs.map +1 -1
- package/esm/model/methods/write-methods.mjs.map +1 -1
- package/esm/query-builder/query-builder.mjs +1 -1
- package/esm/query-builder/query-builder.mjs.map +1 -1
- package/esm/utils/sanitize-filter.mjs.map +1 -1
- package/esm/validation/plugins/database-rules-plugin.mjs.map +1 -1
- package/esm/writer/database-writer.d.mts +0 -33
- package/esm/writer/database-writer.d.mts.map +1 -1
- package/esm/writer/database-writer.mjs +3 -52
- package/esm/writer/database-writer.mjs.map +1 -1
- package/llms-full.txt +2901 -2864
- package/package.json +5 -5
- package/skills/aggregate-data/SKILL.md +165 -165
- package/skills/alter-migration/SKILL.md +531 -531
- package/skills/configure-delete-strategy/SKILL.md +130 -130
- package/skills/define-model/SKILL.md +205 -205
- package/skills/define-relations/SKILL.md +171 -171
- package/skills/manage-data-sources/SKILL.md +177 -140
- package/skills/manage-transactions/SKILL.md +215 -205
- package/skills/paginate-results/SKILL.md +122 -122
- package/skills/perform-atomic-ops/SKILL.md +156 -156
- package/skills/query-data/SKILL.md +213 -213
- package/skills/run-cascade-cli/SKILL.md +125 -125
- package/skills/search-by-vector/SKILL.md +127 -127
- package/skills/subscribe-to-model-events/SKILL.md +148 -148
- package/skills/track-changes/SKILL.md +127 -127
- package/skills/write-migration/SKILL.md +206 -206
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to `@warlock.js/cascade` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.25.0 - 2026-09-28
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Drivers emit public `query` events for settled PostgreSQL SQL and MongoDB commands; `dataSourceRegistry` forwards them with the registered connection name for centralized inspection.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- PostgreSQL `groupByRaw()` now emits and parses its raw GROUP BY operation correctly, including bound parameters.
|
|
16
|
+
- MongoDB `lockForUpdate()` now throws the public `UnsupportedLockForUpdateError` with guidance to use a conditional atomic update instead of a nonexistent row lock.
|
|
17
|
+
- MongoDB atomic upserts now assign the model's auto-increment `id` on insert without changing an existing document's id.
|
|
18
|
+
|
|
7
19
|
## 5.24.0 - 2026-09-27
|
|
8
20
|
|
|
9
21
|
### Added
|
|
@@ -82,6 +94,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
82
94
|
### Changed
|
|
83
95
|
|
|
84
96
|
- Lockstep release maintenance and dependency refresh.
|
|
97
|
+
|
|
85
98
|
## 5.20.0 - 2026-09-24
|
|
86
99
|
|
|
87
100
|
### Added
|
|
@@ -212,12 +225,12 @@ changelogs.
|
|
|
212
225
|
|
|
213
226
|
### Security
|
|
214
227
|
|
|
215
|
-
- **NoSQL operator injection via equality filters is now rejected.** `where({ field: value })`, `where(field, value)` and the filter-accepting model statics (`first`, `findFirst`, `findAll`, `count`, `paginate`, `deleteMany`, `deleteOne`, …) treated the value verbatim, so a request-controlled payload such as `{ password: { $ne: null } }` compiled into a MongoDB
|
|
216
|
-
- **String-mode `whereRaw()` / `orWhereRaw()` no longer compiles to `$where` on the MongoDB driver.** Any string expression was wrapped as `{ $where: "<js>" }` — JavaScript executed
|
|
228
|
+
- **NoSQL operator injection via equality filters is now rejected.** `where({ field: value })`, `where(field, value)` and the filter-accepting model statics (`first`, `findFirst`, `findAll`, `count`, `paginate`, `deleteMany`, `deleteOne`, …) treated the value verbatim, so a request-controlled payload such as `{ password: { $ne: null } }` compiled into a MongoDB _operator_ query instead of an equality match — the textbook auth-bypass primitive (`User.first({ email, password })` matched any user). Equality-position values (and top-level object-form keys) containing `$`-prefixed keys now throw `UnsafeFilterError`. Explicit operator APIs are unaffected: `where(field, operator, value)`, `whereIn`/`whereNull`/`whereBetween`/…, and the object form of `whereRaw`. Dotted paths (`"profile.name"`) and plain sub-document equality values remain valid. A `sanitizeFilter` / `sanitizeFilterValue` helper pair is exported for callers who forward request objects to other driver-level APIs
|
|
229
|
+
- **String-mode `whereRaw()` / `orWhereRaw()` no longer compiles to `$where` on the MongoDB driver.** Any string expression was wrapped as `{ $where: "<js>" }` — JavaScript executed _inside_ `mongod` for every scanned document (an injection sink whenever any part of the string was request-influenced, and an unindexed full-scan DoS even when trusted), with `?`-bindings substituted by string concatenation rather than real parameterization. The MongoDB parser now throws `UnsafeRawExpressionError` for string expressions and directs callers to the object form (`whereRaw({ $expr: … })`), which keeps working. SQL drivers keep string mode with real bindings
|
|
217
230
|
- **`static hidden` — fields `toJSON()` can never emit.** With no `resource`/`toJsonColumns` configured (the quick-start model shape), `toJSON()` — invoked implicitly by `JSON.stringify(model)` / `res.json(model)` — returned the entire raw document, password hashes and tokens included. Models can now declare `static hidden = ["password", …]`; those top-level fields are ALWAYS stripped from `toJSON()` output — with the raw-document default, with `toJsonColumns` (hidden wins), and from the data handed to a `resource` class. Defaults to `[]`, so nothing changes until a model declares hidden fields — but because that default still fails open, cascade now logs a one-time `console.warn` per model whose schema declares a credential-shaped field (`password`/`passwordHash`/`secret`/`token`/`apiKey`/`api_key`, case-insensitive) that no `hidden`/`resource`/`toJsonColumns` covers
|
|
218
231
|
- **Atomic/find-and-modify statics now sanitize their filter.** `atomic()`, `findAndUpdate()`, `findOneAndUpdate()`, `findAndReplace()` and `findOneAndDelete()` forwarded their `filter` object straight to the driver — bypassing `where()` and therefore the operator-injection check above, so `{ role: { $ne: "admin" } }` from a request body was still a live operator query on these paths. The filter argument now runs through `sanitizeFilter` and throws `UnsafeFilterError` on `$`-prefixed keys. Update-operator semantics (`$set`/`$inc`/`$unset`/…) are untouched — only the FILTER is checked. Callers who legitimately need operator conditions must express them through the query API (`Model.query().where(…)`) instead of the raw filter argument
|
|
219
232
|
- **Residual injection paths closed.** The three-argument equality form `where(field, "=", value)` now sanitizes its value like the two-argument form (other operators are unaffected), and the object form of `whereRaw()`/`orWhereRaw()` rejects the server-side JavaScript operators `$where`, `$function` and `$accumulator` anywhere in the expression (throws `UnsafeRawExpressionError`); `$expr` and the other aggregation operators keep working
|
|
220
|
-
- **A `merge()`d primary key can no longer retarget a write at another document.** `performUpdate()` built its filter from `model.get(primaryKey)`
|
|
233
|
+
- **A `merge()`d primary key can no longer retarget a write at another document.** `performUpdate()` built its filter from `model.get(primaryKey)` _after_ `merge()` had run, so the canonical update-my-profile shape — `model.merge(req.body); await model.save()` — let a body carrying `{ id: "<victim-id>", role: "admin" }` redirect the UPDATE (and the mass-assigned fields with it) onto somebody else's row. Two independent controls now stand between a payload and the write target: (1) an instance captures its primary key at the moment it becomes persisted (`isNew` flipping to `false` — hydration, or the writer after an insert), and `update`/`replace`/`destroy` build their filter from that captured value, exposed as `model.trustedPrimaryKey`; (2) `merge()` on an already-persisted model drops the identity columns (`id`, `_id`, and the configured primary key) instead of applying them — which also covers `save({ merge })`. Identity columns are additionally excluded from the update's `$set`/`$unset`, so an explicit `set("id", …)` on a loaded record no longer rewrites the key of the row it is pinned to (`_id` was never writable in MongoDB anyway); changing a primary key is now a deliberate operation through the atomic/raw APIs. **Creating** a record with an explicit id is unchanged — a new model accepts identity columns — and the writer still merges driver-returned values (generated `_id`, `RETURNING *`) back onto the instance through a framework-internal path that request data never reaches
|
|
221
234
|
- **`whereLike` / `whereSearch` string arguments are matched literally instead of compiled as regexes.** `whereLike`, `whereNotLike`, `whereStartsWith`/`whereEndsWith` (and their `Not` variants) and the `$regex` form of `whereSearch` interpolated their argument straight into a MongoDB `$regex`. Wired to a search box — `User.query().whereSearch("name", req.query.q)`, the intended use — that handed the caller the regex engine running inside `mongod`: metacharacters rewrote the match semantics (`^.*$` matches everything, `^a`/`^b` probes read a value back character by character), and a nested-quantifier pattern such as `(a+)+$` backtracked catastrophically against every scanned document. String arguments are now escaped and treated as literals; the SQL `LIKE` wildcard `%` still expands (to `.*`, with runs of `%` collapsed) and matching stays unanchored/substring as this driver documents. An explicit `RegExp` argument — which cannot arrive as JSON — is still used as a pattern, so raw regex remains available to developer-authored queries; never build that `RegExp` from user input. `escapeRegex` / `likePatternToRegexSource` are exported for callers compiling their own patterns. The Postgres path was already parameterized (`ILIKE $1`) and is unchanged
|
|
222
235
|
- **`@mongez/*` dependencies bumped to the 2026-08-17 security release**: `@mongez/reinforcements` `^3.3.0` → `^4.0.1`, `@mongez/dotenv` `^1.3.1` → `^1.3.2`, `@mongez/events` `^2.2.6` → `^2.2.7`, `@mongez/supportive-is` `^2.1.3` → `^2.1.4`. Reinforcements 4 adds a prototype-pollution guard to `set`/`merge`/`pick`/`defaults` — the utilities behind `model.set()` / `model.merge()`, i.e. exactly where request-shaped data enters a model — and a ReDoS fix in `repeatsOf`. Its breaking change (`Random` is CSPRNG-backed and no longer honors `Random.seed()`) does not affect cascade: the package imports no `Random` API and seeds nothing. Requires Node 20+, which cascade already targets
|
|
223
236
|
|
|
@@ -229,7 +242,7 @@ changelogs.
|
|
|
229
242
|
|
|
230
243
|
Returns `PendingMigration { name, createdAt? }` rather than the migration classes: `MigrationClass` is module-local, so a public API returning it would hand consumers a type they cannot name. It deliberately omits `table`, which `status()` obtains by constructing each migration — instantiating user classes to decorate a listing lets a constructor throw inside the very call meant to report on a broken tree
|
|
231
244
|
|
|
232
|
-
`getPendingMigrations()` is now public alongside it. **Both document the trap in their own JSDoc:** only
|
|
245
|
+
`getPendingMigrations()` is now public alongside it. **Both document the trap in their own JSDoc:** only _registered_ migrations can be pending, so a caller that has not registered anything receives `[]` — indistinguishable from a database with nothing pending, and the reason `@warlock.js/core`'s CLI loads before it reports
|
|
233
246
|
|
|
234
247
|
### Changed
|
|
235
248
|
|
|
@@ -240,7 +253,7 @@ changelogs.
|
|
|
240
253
|
### Fixed
|
|
241
254
|
|
|
242
255
|
- `migrate:rollback` and `migrate:rollback --all` ran `down()` migrations in **apply order** instead of reverse. `getMigrationsToRollback` reversed the executed list and then re-sorted it ascending, which put it straight back into forward order and made the reverse dead code — so a rollback would drop a table before dropping the column added to it, failing with `relation "…" does not exist`. Any batch containing more than one migration was affected; single-migration batches hid it because one item has no order to get wrong
|
|
243
|
-
- migration ordering now lives in `migration-order.ts` with an explicit `sortMigrationsForRollback`. The descending sort is required, not cosmetic: the executed list is read back ordered by `batch, name`, so it is alphabetical rather than chronological and simply
|
|
256
|
+
- migration ordering now lives in `migration-order.ts` with an explicit `sortMigrationsForRollback`. The descending sort is required, not cosmetic: the executed list is read back ordered by `batch, name`, so it is alphabetical rather than chronological and simply _not_ re-sorting after the reverse would have produced reverse-alphabetical order — a different wrong answer
|
|
244
257
|
|
|
245
258
|
## 4.9.1
|
|
246
259
|
|
package/README.md
CHANGED
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
# cascade
|
|
2
|
-
|
|
3
|
-
A powerful, model-first TypeScript ORM for **MongoDB and PostgreSQL** on `Node.js`.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
Cascade is a unified ORM for MongoDB and PostgreSQL — one model-first API runs against both engines. Define a model once (its `@warlock.js/seal` schema doubles as the TypeScript type, the runtime validator, and the DB shape) and query straight off the class. It's fast, type-safe, and built for real-world apps.
|
|
8
|
-
|
|
9
|
-
Some but not all of the features:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- **Easy to use:** `Cascade` is very easy to use, it's just a wrapper around MongoDB driver.
|
|
13
|
-
- **Supports multiple connections:** You can perform multiple connections to different MongoDB connections and use each one of them separately.
|
|
14
|
-
- **Supports multiple databases:** `Cascade` supports multiple databases, you can connect to multiple databases at the same time.
|
|
15
|
-
- **Powerful Aggregate framework:** `Cascade` has a powerful aggregate framework that helps you to perform complex queries.
|
|
16
|
-
- **Basic CRUD operations:** `Cascade` supports basic CRUD operations, you can perform create, read, update and delete operations.
|
|
17
|
-
- **Events Driven:** `Cascade` is events driven, you can listen to events and perform actions, for example before creating, updating or deleting a document.
|
|
18
|
-
- **Powerful Models:** `Cascade` has a powerful models system, a Model is a collection manager document based, it manages a collection's document easily with many utilities.
|
|
19
|
-
- **Learning curve:** `Cascade` has a very small learning curve, you can learn it in few minutes.
|
|
20
|
-
- **Pagination support:** `Cascade` supports pagination, you can paginate your results easily.
|
|
21
|
-
- **Output formatting:** `Cascade` supports output formatting, you can format your output easily when model is sent as a response.
|
|
22
|
-
- **Auto incremented id:** `Cascade` supports auto incremented id, you can use it as a primary key for your documents.
|
|
23
|
-
- **Random or sequential id:** `Cascade` supports random or sequential id.
|
|
24
|
-
- **Recycle Bin:** Reduce collection documents by removing the document entirely from the collection, but move it to a separate collection trash.
|
|
25
|
-
- **Migration system:** `Cascade` has a migration system, you can create migrations and run them easily.
|
|
26
|
-
- **Data casting:** You can cast your data to a specific type or using custom casting.
|
|
27
|
-
- **Embedded documents:** `Cascade` supports single and multiple embedded documents, you can embed documents inside other documents.
|
|
28
|
-
- **Syncing Models**: Auto update documents when model's data is updated or deleted.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
## Server-only
|
|
32
|
-
|
|
33
|
-
`@warlock.js/cascade`'s entire runtime surface is server-only — its `package.json` declares `"warlock": { "environment": "server" }`. `@warlock.js/web`'s build treats this as a boundary: app client code cannot value-import this package (type-only imports are still allowed), while server loaders/controllers/modules can import it freely.
|
|
34
|
-
|
|
35
|
-
## Installation
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
npm i @warlock.js/cascade
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Using yarn:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
yarn add @warlock.js/cascade
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Using pnpm:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
pnpm add @warlock.js/cascade
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
## Peek inside cascade
|
|
55
|
-
|
|
56
|
-
Here is a simple example of defining a User model:
|
|
57
|
-
|
|
58
|
-
```ts title="src/models/user.ts"
|
|
59
|
-
import { Model, RegisterModel } from "@warlock.js/cascade";
|
|
60
|
-
|
|
61
|
-
@RegisterModel()
|
|
62
|
-
export class User extends Model {
|
|
63
|
-
/**
|
|
64
|
-
* The table / collection name.
|
|
65
|
-
* Must be defined explicitly.
|
|
66
|
-
*/
|
|
67
|
-
public static table = "users";
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
A quick example of creating a user:
|
|
72
|
-
|
|
73
|
-
```ts title="src/controllers/users.ts"
|
|
74
|
-
import { User } from "src/models/user";
|
|
75
|
-
|
|
76
|
-
export async function createUser() {
|
|
77
|
-
const user = await User.create({
|
|
78
|
-
name: "Hasan Zohdy",
|
|
79
|
-
email: "hassanzohdy@gmail.com",
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
console.log(user.data);
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Outputs something similar to:
|
|
87
|
-
|
|
88
|
-
```json
|
|
89
|
-
{
|
|
90
|
-
"id": 1231412,
|
|
91
|
-
"_id": "fagtrw43qwedasjoijwq",
|
|
92
|
-
"name": "Hasan Zohdy",
|
|
93
|
-
"email": "hassanzohdy@gmail.com",
|
|
94
|
-
"createdAt": "2023-06-01 00:00:00",
|
|
95
|
-
"updatedAt": "2023-06-01 00:00:00"
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
## Documentation
|
|
101
|
-
|
|
1
|
+
# cascade
|
|
2
|
+
|
|
3
|
+
A powerful, model-first TypeScript ORM for **MongoDB and PostgreSQL** on `Node.js`.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
Cascade is a unified ORM for MongoDB and PostgreSQL — one model-first API runs against both engines. Define a model once (its `@warlock.js/seal` schema doubles as the TypeScript type, the runtime validator, and the DB shape) and query straight off the class. It's fast, type-safe, and built for real-world apps.
|
|
8
|
+
|
|
9
|
+
Some but not all of the features:
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
- **Easy to use:** `Cascade` is very easy to use, it's just a wrapper around MongoDB driver.
|
|
13
|
+
- **Supports multiple connections:** You can perform multiple connections to different MongoDB connections and use each one of them separately.
|
|
14
|
+
- **Supports multiple databases:** `Cascade` supports multiple databases, you can connect to multiple databases at the same time.
|
|
15
|
+
- **Powerful Aggregate framework:** `Cascade` has a powerful aggregate framework that helps you to perform complex queries.
|
|
16
|
+
- **Basic CRUD operations:** `Cascade` supports basic CRUD operations, you can perform create, read, update and delete operations.
|
|
17
|
+
- **Events Driven:** `Cascade` is events driven, you can listen to events and perform actions, for example before creating, updating or deleting a document.
|
|
18
|
+
- **Powerful Models:** `Cascade` has a powerful models system, a Model is a collection manager document based, it manages a collection's document easily with many utilities.
|
|
19
|
+
- **Learning curve:** `Cascade` has a very small learning curve, you can learn it in few minutes.
|
|
20
|
+
- **Pagination support:** `Cascade` supports pagination, you can paginate your results easily.
|
|
21
|
+
- **Output formatting:** `Cascade` supports output formatting, you can format your output easily when model is sent as a response.
|
|
22
|
+
- **Auto incremented id:** `Cascade` supports auto incremented id, you can use it as a primary key for your documents.
|
|
23
|
+
- **Random or sequential id:** `Cascade` supports random or sequential id.
|
|
24
|
+
- **Recycle Bin:** Reduce collection documents by removing the document entirely from the collection, but move it to a separate collection trash.
|
|
25
|
+
- **Migration system:** `Cascade` has a migration system, you can create migrations and run them easily.
|
|
26
|
+
- **Data casting:** You can cast your data to a specific type or using custom casting.
|
|
27
|
+
- **Embedded documents:** `Cascade` supports single and multiple embedded documents, you can embed documents inside other documents.
|
|
28
|
+
- **Syncing Models**: Auto update documents when model's data is updated or deleted.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Server-only
|
|
32
|
+
|
|
33
|
+
`@warlock.js/cascade`'s entire runtime surface is server-only — its `package.json` declares `"warlock": { "environment": "server" }`. `@warlock.js/web`'s build treats this as a boundary: app client code cannot value-import this package (type-only imports are still allowed), while server loaders/controllers/modules can import it freely.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm i @warlock.js/cascade
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Using yarn:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
yarn add @warlock.js/cascade
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Using pnpm:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pnpm add @warlock.js/cascade
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Peek inside cascade
|
|
55
|
+
|
|
56
|
+
Here is a simple example of defining a User model:
|
|
57
|
+
|
|
58
|
+
```ts title="src/models/user.ts"
|
|
59
|
+
import { Model, RegisterModel } from "@warlock.js/cascade";
|
|
60
|
+
|
|
61
|
+
@RegisterModel()
|
|
62
|
+
export class User extends Model {
|
|
63
|
+
/**
|
|
64
|
+
* The table / collection name.
|
|
65
|
+
* Must be defined explicitly.
|
|
66
|
+
*/
|
|
67
|
+
public static table = "users";
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
A quick example of creating a user:
|
|
72
|
+
|
|
73
|
+
```ts title="src/controllers/users.ts"
|
|
74
|
+
import { User } from "src/models/user";
|
|
75
|
+
|
|
76
|
+
export async function createUser() {
|
|
77
|
+
const user = await User.create({
|
|
78
|
+
name: "Hasan Zohdy",
|
|
79
|
+
email: "hassanzohdy@gmail.com",
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
console.log(user.data);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Outputs something similar to:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"id": 1231412,
|
|
91
|
+
"_id": "fagtrw43qwedasjoijwq",
|
|
92
|
+
"name": "Hasan Zohdy",
|
|
93
|
+
"email": "hassanzohdy@gmail.com",
|
|
94
|
+
"createdAt": "2023-06-01 00:00:00",
|
|
95
|
+
"updatedAt": "2023-06-01 00:00:00"
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
## Documentation
|
|
101
|
+
|
|
102
102
|
To see the full documentation, please visit [Cascade Documentation](https://warlock.js.org/docs/cascade/getting-started/introduction)
|
package/bin/cascade.js
CHANGED
|
File without changes
|