chadstart 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/.dockerignore +10 -0
- package/.env.example +46 -0
- package/.github/workflows/browser-test.yml +34 -0
- package/.github/workflows/docker-publish.yml +54 -0
- package/.github/workflows/docs.yml +31 -0
- package/.github/workflows/npm-chadstart.yml +27 -0
- package/.github/workflows/npm-sdk.yml +38 -0
- package/.github/workflows/test.yml +85 -0
- package/.weblate +9 -0
- package/Dockerfile +23 -0
- package/README.md +348 -0
- package/admin/index.html +2802 -0
- package/admin/login.html +207 -0
- package/chadstart.example.yml +416 -0
- package/chadstart.schema.json +367 -0
- package/chadstart.yaml +53 -0
- package/cli/cli.js +295 -0
- package/core/api-generator.js +606 -0
- package/core/auth.js +298 -0
- package/core/db.js +384 -0
- package/core/entity-engine.js +166 -0
- package/core/error-reporter.js +132 -0
- package/core/file-storage.js +97 -0
- package/core/functions-engine.js +353 -0
- package/core/openapi.js +171 -0
- package/core/plugin-loader.js +92 -0
- package/core/realtime.js +93 -0
- package/core/schema-validator.js +50 -0
- package/core/seeder.js +231 -0
- package/core/telemetry.js +119 -0
- package/core/upload.js +372 -0
- package/core/workers/php_worker.php +19 -0
- package/core/workers/python_worker.py +33 -0
- package/core/workers/ruby_worker.rb +21 -0
- package/core/yaml-loader.js +64 -0
- package/demo/chadstart.yaml +178 -0
- package/demo/docker-compose.yml +31 -0
- package/demo/functions/greet.go +39 -0
- package/demo/functions/hello.cpp +18 -0
- package/demo/functions/hello.py +13 -0
- package/demo/functions/hello.rb +10 -0
- package/demo/functions/onTodoCreated.js +13 -0
- package/demo/functions/ping.sh +13 -0
- package/demo/functions/stats.js +22 -0
- package/demo/public/index.html +522 -0
- package/docker-compose.yml +17 -0
- package/docs/access-policies.md +155 -0
- package/docs/admin-ui.md +29 -0
- package/docs/angular.md +69 -0
- package/docs/astro.md +71 -0
- package/docs/auth.md +160 -0
- package/docs/cli.md +56 -0
- package/docs/config.md +127 -0
- package/docs/crud.md +627 -0
- package/docs/deploy.md +113 -0
- package/docs/docker.md +59 -0
- package/docs/entities.md +385 -0
- package/docs/functions.md +196 -0
- package/docs/getting-started.md +79 -0
- package/docs/groups.md +85 -0
- package/docs/index.md +5 -0
- package/docs/llm-rules.md +81 -0
- package/docs/middlewares.md +78 -0
- package/docs/overrides/home.html +350 -0
- package/docs/plugins.md +59 -0
- package/docs/react.md +75 -0
- package/docs/realtime.md +43 -0
- package/docs/s3-storage.md +40 -0
- package/docs/security.md +23 -0
- package/docs/stylesheets/extra.css +375 -0
- package/docs/svelte.md +71 -0
- package/docs/telemetry.md +97 -0
- package/docs/upload.md +168 -0
- package/docs/validation.md +115 -0
- package/docs/vue.md +86 -0
- package/docs/webhooks.md +87 -0
- package/index.js +11 -0
- package/locales/en/admin.json +169 -0
- package/mkdocs.yml +82 -0
- package/package.json +65 -0
- package/playwright.config.js +24 -0
- package/public/.gitkeep +0 -0
- package/sdk/README.md +284 -0
- package/sdk/package.json +39 -0
- package/sdk/scripts/build.js +58 -0
- package/sdk/src/index.js +368 -0
- package/sdk/test/sdk.test.cjs +340 -0
- package/sdk/types/index.d.ts +217 -0
- package/server/express-server.js +734 -0
- package/test/access-policies.test.js +96 -0
- package/test/ai.test.js +81 -0
- package/test/api-keys.test.js +361 -0
- package/test/auth.test.js +122 -0
- package/test/browser/admin-ui.spec.js +127 -0
- package/test/browser/global-setup.js +71 -0
- package/test/browser/global-teardown.js +11 -0
- package/test/db.test.js +227 -0
- package/test/entity-engine.test.js +193 -0
- package/test/error-reporter.test.js +140 -0
- package/test/functions-engine.test.js +240 -0
- package/test/groups.test.js +212 -0
- package/test/hot-reload.test.js +153 -0
- package/test/i18n.test.js +173 -0
- package/test/middleware.test.js +76 -0
- package/test/openapi.test.js +67 -0
- package/test/schema-validator.test.js +83 -0
- package/test/sdk.test.js +90 -0
- package/test/seeder.test.js +279 -0
- package/test/settings.test.js +109 -0
- package/test/telemetry.test.js +254 -0
- package/test/test.js +17 -0
- package/test/upload.test.js +265 -0
- package/test/validation.test.js +96 -0
- package/test/yaml-loader.test.js +93 -0
- package/utils/logger.js +24 -0
package/sdk/README.md
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# @chadstart/sdk
|
|
2
|
+
|
|
3
|
+
Official JavaScript/TypeScript SDK for [Chadstart](https://github.com/saulmmendoza/chadstart.com) — the YAML-first Backend as a Service.
|
|
4
|
+
|
|
5
|
+
Works in **any JS/TS project**: browsers, React, Vue, Svelte, Angular, Astro, Node.js, and more.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @chadstart/sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import Chadstart from '@chadstart/sdk'
|
|
21
|
+
|
|
22
|
+
// Initialize with your backend URL (defaults to http://localhost:3000)
|
|
23
|
+
const client = new Chadstart('https://your-chadstart-backend.com')
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Collections
|
|
29
|
+
|
|
30
|
+
### List items (paginated)
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
// Fetch all posts (returns paginated result)
|
|
34
|
+
const result = await client.from('posts').find()
|
|
35
|
+
// { data: [...], currentPage: 1, lastPage: 1, total: 10, perPage: 10, from: 1, to: 10 }
|
|
36
|
+
|
|
37
|
+
// With pagination
|
|
38
|
+
const result = await client.from('posts').find({ page: 2, perPage: 20 })
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Filtering
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
const posts = await client
|
|
45
|
+
.from('posts')
|
|
46
|
+
.where('published = true')
|
|
47
|
+
.andWhere('views > 100')
|
|
48
|
+
.find()
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Supported operators:**
|
|
52
|
+
|
|
53
|
+
| Operator | Description | Example |
|
|
54
|
+
| -------- | --------------------- | -------------------------------- |
|
|
55
|
+
| `=` | equals | `.where('isActive = true')` |
|
|
56
|
+
| `!=` | not equals | `.where('status != draft')` |
|
|
57
|
+
| `>` | greater than | `.where('age > 18')` |
|
|
58
|
+
| `>=` | greater than or equal | `.where('price >= 10')` |
|
|
59
|
+
| `<` | less than | `.where('stock < 5')` |
|
|
60
|
+
| `<=` | less than or equal | `.where('amount <= 400')` |
|
|
61
|
+
| `like` | pattern match | `.where('name like %jo%')` |
|
|
62
|
+
| `in` | included in | `.where('status in new,active')` |
|
|
63
|
+
|
|
64
|
+
### Ordering
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
const posts = await client
|
|
68
|
+
.from('posts')
|
|
69
|
+
.orderBy('createdAt', { desc: true })
|
|
70
|
+
.find()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Relations
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
const posts = await client
|
|
77
|
+
.from('posts')
|
|
78
|
+
.with(['author', 'tags'])
|
|
79
|
+
.find()
|
|
80
|
+
|
|
81
|
+
// Nested relations
|
|
82
|
+
const cities = await client
|
|
83
|
+
.from('cities')
|
|
84
|
+
.with(['region', 'region.country'])
|
|
85
|
+
.find()
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Get a single item by ID
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
const post = await client.from('posts').findOneById('2c4e6a8b-...')
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Create an item
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
const newPost = await client.from('posts').create({
|
|
98
|
+
title: 'Hello World',
|
|
99
|
+
published: true,
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Update an item (full replace — PUT)
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
const updated = await client.from('posts').update('2c4e6a8b-...', {
|
|
107
|
+
title: 'Updated Title',
|
|
108
|
+
published: false,
|
|
109
|
+
})
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Patch an item (partial update — PATCH)
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
const patched = await client.from('posts').patch('2c4e6a8b-...', {
|
|
116
|
+
published: true,
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Delete an item
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
const deleted = await client.from('posts').delete('2c4e6a8b-...')
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Singles
|
|
129
|
+
|
|
130
|
+
Singles are entities with only one record (e.g. homepage content, site settings).
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
// Get
|
|
134
|
+
const homepage = await client.single('homepage').get()
|
|
135
|
+
|
|
136
|
+
// Full replace (PUT)
|
|
137
|
+
const updated = await client.single('homepage').update({
|
|
138
|
+
title: 'Welcome!',
|
|
139
|
+
description: 'My awesome site',
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// Partial update (PATCH)
|
|
143
|
+
const patched = await client.single('homepage').patch({ title: 'New Title' })
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Authentication
|
|
149
|
+
|
|
150
|
+
Chadstart supports multiple authenticable entity types.
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
// Sign up
|
|
154
|
+
const { token, user } = await client.auth('customers').signup({
|
|
155
|
+
email: 'alice@example.com',
|
|
156
|
+
password: 'secret',
|
|
157
|
+
name: 'Alice',
|
|
158
|
+
})
|
|
159
|
+
// Token is stored automatically
|
|
160
|
+
|
|
161
|
+
// Log in
|
|
162
|
+
const { token, user } = await client.auth('customers').login({
|
|
163
|
+
email: 'alice@example.com',
|
|
164
|
+
password: 'secret',
|
|
165
|
+
})
|
|
166
|
+
// Token is stored automatically
|
|
167
|
+
|
|
168
|
+
// Get current user (requires a stored token)
|
|
169
|
+
const me = await client.auth('customers').me()
|
|
170
|
+
|
|
171
|
+
// Log out
|
|
172
|
+
client.auth('customers').logout()
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Manual token management
|
|
176
|
+
|
|
177
|
+
```js
|
|
178
|
+
// Store a token manually (e.g. from localStorage)
|
|
179
|
+
client.setToken(localStorage.getItem('token'))
|
|
180
|
+
|
|
181
|
+
// Clear the token
|
|
182
|
+
client.clearToken()
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Error Handling
|
|
188
|
+
|
|
189
|
+
All methods throw a `ChadstartError` on non-2xx responses.
|
|
190
|
+
|
|
191
|
+
```js
|
|
192
|
+
import Chadstart, { ChadstartError } from '@chadstart/sdk'
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
const post = await client.from('posts').findOneById('missing-id')
|
|
196
|
+
} catch (err) {
|
|
197
|
+
if (err instanceof ChadstartError) {
|
|
198
|
+
console.log(err.status) // e.g. 404
|
|
199
|
+
console.log(err.message) // e.g. "Not found"
|
|
200
|
+
console.log(err.data) // raw response body
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## TypeScript
|
|
208
|
+
|
|
209
|
+
Full TypeScript support is included out of the box.
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
import Chadstart from '@chadstart/sdk'
|
|
213
|
+
|
|
214
|
+
interface Post {
|
|
215
|
+
id: string
|
|
216
|
+
title: string
|
|
217
|
+
published: boolean
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const client = new Chadstart('https://api.example.com')
|
|
221
|
+
|
|
222
|
+
const { data } = await client.from<Post>('posts').find()
|
|
223
|
+
// ^? Post[]
|
|
224
|
+
|
|
225
|
+
const post = await client.from<Post>('posts').findOneById('abc')
|
|
226
|
+
// ^? Post
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## CommonJS usage
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
const Chadstart = require('@chadstart/sdk')
|
|
235
|
+
const client = new Chadstart('http://localhost:3000')
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## API Reference
|
|
241
|
+
|
|
242
|
+
### `new Chadstart(baseUrl?)`
|
|
243
|
+
|
|
244
|
+
| Parameter | Type | Default | Description |
|
|
245
|
+
| --------- | -------- | -------------------------- | ------------------------ |
|
|
246
|
+
| `baseUrl` | `string` | `'http://localhost:3000'` | Your Chadstart server URL |
|
|
247
|
+
|
|
248
|
+
### `client.from(slug)` → `CollectionQuery`
|
|
249
|
+
|
|
250
|
+
| Method | Description |
|
|
251
|
+
| --------------------------- | ------------------------------------ |
|
|
252
|
+
| `.where(condition)` | Add a filter |
|
|
253
|
+
| `.andWhere(condition)` | Add an additional filter |
|
|
254
|
+
| `.with(relations)` | Load relations |
|
|
255
|
+
| `.orderBy(field, options?)` | Order results |
|
|
256
|
+
| `.find(params?)` | Fetch paginated list |
|
|
257
|
+
| `.findOneById(id)` | Fetch one item by ID |
|
|
258
|
+
| `.create(data)` | Create a new item |
|
|
259
|
+
| `.update(id, data)` | Replace an item (PUT) |
|
|
260
|
+
| `.patch(id, data)` | Partially update an item (PATCH) |
|
|
261
|
+
| `.delete(id)` | Delete an item |
|
|
262
|
+
|
|
263
|
+
### `client.single(slug)` → `SingleQuery`
|
|
264
|
+
|
|
265
|
+
| Method | Description |
|
|
266
|
+
| --------------- | -------------------------------- |
|
|
267
|
+
| `.get()` | Fetch the single entity |
|
|
268
|
+
| `.update(data)` | Replace the single entity (PUT) |
|
|
269
|
+
| `.patch(data)` | Partially update it (PATCH) |
|
|
270
|
+
|
|
271
|
+
### `client.auth(slug)` → `AuthQuery`
|
|
272
|
+
|
|
273
|
+
| Method | Description |
|
|
274
|
+
| --------------- | ---------------------------------------------------- |
|
|
275
|
+
| `.signup(data)` | Register a user; auto-stores the returned token |
|
|
276
|
+
| `.login(data)` | Log in a user; auto-stores the returned token |
|
|
277
|
+
| `.me()` | Get the currently authenticated user |
|
|
278
|
+
| `.logout()` | Clear the stored token |
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## License
|
|
283
|
+
|
|
284
|
+
ISC
|
package/sdk/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "chadstart-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official JavaScript/TypeScript SDK for Chadstart BaaS",
|
|
5
|
+
"keywords": ["chadstart", "sdk", "baas", "backend", "rest", "crud"],
|
|
6
|
+
"author": "Chadstart",
|
|
7
|
+
"license": "ISC",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/saulmmendoza/chadstart.com.git",
|
|
11
|
+
"directory": "sdk"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/saulmmendoza/chadstart.com#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/saulmmendoza/chadstart.com/issues"
|
|
16
|
+
},
|
|
17
|
+
"type": "module",
|
|
18
|
+
"main": "./dist/index.cjs",
|
|
19
|
+
"module": "./dist/index.js",
|
|
20
|
+
"types": "./types/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"require": "./dist/index.cjs",
|
|
25
|
+
"types": "./types/index.d.ts"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"types",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "node scripts/build.js",
|
|
35
|
+
"test": "node test/sdk.test.cjs",
|
|
36
|
+
"prepublishOnly": "npm run build"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {}
|
|
39
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build script: converts sdk/src/index.js (ESM) into:
|
|
3
|
+
* dist/index.js (ESM, unchanged)
|
|
4
|
+
* dist/index.cjs (CommonJS, wrapped)
|
|
5
|
+
*
|
|
6
|
+
* No external dependencies required — uses only Node.js built-ins.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { dirname, join } from 'path';
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const root = join(__dirname, '..');
|
|
15
|
+
|
|
16
|
+
const src = readFileSync(join(root, 'src', 'index.js'), 'utf8');
|
|
17
|
+
|
|
18
|
+
// ── ESM build (verbatim copy) ─────────────────────────────────────────────────
|
|
19
|
+
mkdirSync(join(root, 'dist'), { recursive: true });
|
|
20
|
+
writeFileSync(join(root, 'dist', 'index.js'), src, 'utf8');
|
|
21
|
+
|
|
22
|
+
// ── CJS build ─────────────────────────────────────────────────────────────────
|
|
23
|
+
// Strip ESM export statements and wrap in a CJS module.
|
|
24
|
+
let cjs = src;
|
|
25
|
+
|
|
26
|
+
// Remove `export default Chadstart;`
|
|
27
|
+
cjs = cjs.replace(/^export default \w+;\n?/m, '');
|
|
28
|
+
|
|
29
|
+
// Remove named export line: `export { Chadstart, ... };`
|
|
30
|
+
cjs = cjs.replace(/^export \{[^}]+\};\n?/m, '');
|
|
31
|
+
|
|
32
|
+
// Remove `export ` keyword from class/function declarations
|
|
33
|
+
cjs = cjs.replace(/^export (class|function|const|let|var) /gm, '$1 ');
|
|
34
|
+
|
|
35
|
+
// Append CommonJS exports at the end
|
|
36
|
+
cjs += `
|
|
37
|
+
// CommonJS exports
|
|
38
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
39
|
+
exports.default = Chadstart;
|
|
40
|
+
exports.Chadstart = Chadstart;
|
|
41
|
+
exports.ChadstartError = ChadstartError;
|
|
42
|
+
exports.CollectionQuery = CollectionQuery;
|
|
43
|
+
exports.SingleQuery = SingleQuery;
|
|
44
|
+
exports.AuthQuery = AuthQuery;
|
|
45
|
+
module.exports = exports.default;
|
|
46
|
+
module.exports.default = exports.default;
|
|
47
|
+
module.exports.Chadstart = Chadstart;
|
|
48
|
+
module.exports.ChadstartError = ChadstartError;
|
|
49
|
+
module.exports.CollectionQuery = CollectionQuery;
|
|
50
|
+
module.exports.SingleQuery = SingleQuery;
|
|
51
|
+
module.exports.AuthQuery = AuthQuery;
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
// Replace the ESM import/export template with a CJS-safe header
|
|
55
|
+
writeFileSync(join(root, 'dist', 'index.cjs'), `'use strict';\n\n${cjs}`, 'utf8');
|
|
56
|
+
|
|
57
|
+
console.log('✓ dist/index.js (ESM)');
|
|
58
|
+
console.log('✓ dist/index.cjs (CJS)');
|