baasix 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/README.md +355 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +2521 -0
- package/package.json +56 -0
- package/src/commands/extension.ts +447 -0
- package/src/commands/generate.ts +485 -0
- package/src/commands/init.ts +1409 -0
- package/src/commands/migrate.ts +573 -0
- package/src/index.ts +39 -0
- package/src/utils/api-client.ts +121 -0
- package/src/utils/get-config.ts +69 -0
- package/src/utils/get-package-info.ts +12 -0
- package/src/utils/package-manager.ts +62 -0
- package/tsconfig.json +19 -0
- package/tsup.config.ts +16 -0
package/README.md
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# @tspvivek/baasix-cli
|
|
2
|
+
|
|
3
|
+
Command-line interface for [Baasix](https://baasix.com) Backend-as-a-Service.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Global installation
|
|
9
|
+
npm install -g @tspvivek/baasix-cli
|
|
10
|
+
|
|
11
|
+
# Or use npx
|
|
12
|
+
npx @tspvivek/baasix-cli <command>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
### `baasix init`
|
|
18
|
+
|
|
19
|
+
Initialize a new Baasix project with scaffolding.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
baasix init [project-name]
|
|
23
|
+
|
|
24
|
+
# Skip prompts with defaults
|
|
25
|
+
baasix init --name my-app --template api -y
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Options:**
|
|
29
|
+
|
|
30
|
+
| Option | Description |
|
|
31
|
+
|--------|-------------|
|
|
32
|
+
| `-n, --name <name>` | Project name |
|
|
33
|
+
| `-t, --template <template>` | Project template: `api`, `nextjs`, `nextjs-app` |
|
|
34
|
+
| `-y, --yes` | Skip prompts and use sensible defaults |
|
|
35
|
+
| `-c, --cwd <path>` | Working directory (default: current) |
|
|
36
|
+
|
|
37
|
+
**Templates:**
|
|
38
|
+
|
|
39
|
+
| Template | Description |
|
|
40
|
+
|----------|-------------|
|
|
41
|
+
| `api` | Standalone Baasix API server |
|
|
42
|
+
| `nextjs-app` | Next.js 14+ frontend (App Router) with Baasix SDK |
|
|
43
|
+
| `nextjs` | Next.js frontend (Pages Router) with Baasix SDK |
|
|
44
|
+
|
|
45
|
+
> **Note:** Next.js templates create **frontend-only** projects. You need a separate Baasix API server running.
|
|
46
|
+
|
|
47
|
+
**Example:**
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Create API server
|
|
51
|
+
npx @tspvivek/baasix-cli init --template api my-api
|
|
52
|
+
|
|
53
|
+
# Create Next.js frontend (separate from API)
|
|
54
|
+
npx @tspvivek/baasix-cli init --template nextjs-app my-frontend
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### `baasix generate`
|
|
58
|
+
|
|
59
|
+
Generate TypeScript types from your Baasix schemas with full support for:
|
|
60
|
+
- ✅ **Relations** — Properly typed as target collection types
|
|
61
|
+
- ✅ **Enums** — Generated as union types (`'active' | 'inactive'`)
|
|
62
|
+
- ✅ **System collections** — `BaasixUser`, `BaasixRole`, `BaasixFile`, etc.
|
|
63
|
+
- ✅ **Validations** — JSDoc comments with `@min`, `@max`, `@length`, `@format`
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
baasix generate
|
|
67
|
+
baasix gen
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Options:**
|
|
71
|
+
|
|
72
|
+
| Option | Description | Default |
|
|
73
|
+
|--------|-------------|---------|
|
|
74
|
+
| `-o, --output <path>` | Output file path | `baasix.d.ts` |
|
|
75
|
+
| `-t, --target <target>` | Generation target (see below) | Interactive |
|
|
76
|
+
| `--url <url>` | Baasix server URL | `http://localhost:8056` |
|
|
77
|
+
| `-y, --yes` | Skip confirmation prompts | - |
|
|
78
|
+
|
|
79
|
+
**Generation Targets:**
|
|
80
|
+
|
|
81
|
+
| Target | Description |
|
|
82
|
+
|--------|-------------|
|
|
83
|
+
| `types` | TypeScript interfaces for all collections |
|
|
84
|
+
| `sdk-types` | Typed SDK helpers with collection methods |
|
|
85
|
+
| `schema-json` | Export schemas as JSON |
|
|
86
|
+
|
|
87
|
+
**Example Output:**
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// System collections (referenced by relations)
|
|
91
|
+
export interface BaasixUser {
|
|
92
|
+
id: string;
|
|
93
|
+
firstName: string;
|
|
94
|
+
lastName?: string | null;
|
|
95
|
+
email?: string | null;
|
|
96
|
+
// ...
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Your collections with proper relation types
|
|
100
|
+
export interface Product {
|
|
101
|
+
id: string;
|
|
102
|
+
name: string;
|
|
103
|
+
price: number;
|
|
104
|
+
status: 'published' | 'draft' | 'archived'; // Enum as union type
|
|
105
|
+
category_Id?: string | null;
|
|
106
|
+
category?: Category | null; // Relation typed correctly
|
|
107
|
+
userCreated?: BaasixUser | null; // System relation
|
|
108
|
+
createdAt?: string;
|
|
109
|
+
updatedAt?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface Category {
|
|
113
|
+
id: string;
|
|
114
|
+
name: string;
|
|
115
|
+
products?: Product[] | null; // HasMany relation as array
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Collection type map
|
|
119
|
+
export type CollectionName = "products" | "categories";
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Usage:**
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Generate types from running Baasix instance
|
|
126
|
+
baasix generate --url http://localhost:8056 --output ./src/types/baasix.d.ts
|
|
127
|
+
|
|
128
|
+
# Use in your code
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import type { Product, Category, BaasixUser } from "./types/baasix";
|
|
133
|
+
import { createBaasix } from "@tspvivek/baasix-sdk";
|
|
134
|
+
|
|
135
|
+
const baasix = createBaasix({ url: "http://localhost:8056" });
|
|
136
|
+
|
|
137
|
+
// Type-safe queries with properly typed relations
|
|
138
|
+
const products = await baasix.items<Product>("products").list({
|
|
139
|
+
fields: ["*", "category.*", "userCreated.*"]
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// products[0].category is typed as Category | null
|
|
143
|
+
// products[0].status is typed as 'published' | 'draft' | 'archived'
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### `baasix extension`
|
|
147
|
+
|
|
148
|
+
Scaffold a new Baasix extension.
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
baasix extension
|
|
152
|
+
baasix ext
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Options:**
|
|
156
|
+
|
|
157
|
+
| Option | Description |
|
|
158
|
+
|--------|-------------|
|
|
159
|
+
| `-t, --type <type>` | Extension type: `hook` or `endpoint` |
|
|
160
|
+
| `-n, --name <name>` | Extension name |
|
|
161
|
+
| `--collection <name>` | Collection name (for hooks) |
|
|
162
|
+
| `--typescript` | Use TypeScript (default) |
|
|
163
|
+
| `--no-typescript` | Use JavaScript |
|
|
164
|
+
|
|
165
|
+
**Extension Types:**
|
|
166
|
+
|
|
167
|
+
#### Hook Extension
|
|
168
|
+
|
|
169
|
+
Lifecycle hooks triggered on CRUD operations:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
baasix extension --type hook --name audit-log --collection orders
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
// extensions/baasix-hook-audit-log/index.js
|
|
177
|
+
export default (hooksService, context) => {
|
|
178
|
+
const { ItemsService } = context;
|
|
179
|
+
|
|
180
|
+
hooksService.registerHook("orders", "items.create", async ({ data, accountability }) => {
|
|
181
|
+
console.log(`Creating order:`, data);
|
|
182
|
+
data.created_by = accountability.user.id;
|
|
183
|
+
return { data };
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
hooksService.registerHook("orders", "items.update", async ({ id, data, accountability }) => {
|
|
187
|
+
console.log(`Updating order ${id}:`, data);
|
|
188
|
+
data.updated_by = accountability.user.id;
|
|
189
|
+
return { id, data };
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### Endpoint Extension
|
|
195
|
+
|
|
196
|
+
Custom REST API endpoints:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
baasix extension --type endpoint --name analytics
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
// extensions/baasix-endpoint-analytics/index.js
|
|
204
|
+
import { APIError } from "@tspvivek/baasix";
|
|
205
|
+
|
|
206
|
+
export default {
|
|
207
|
+
id: "analytics",
|
|
208
|
+
handler: (app, context) => {
|
|
209
|
+
const { ItemsService } = context;
|
|
210
|
+
|
|
211
|
+
app.get("/analytics/dashboard", async (req, res) => {
|
|
212
|
+
if (!req.accountability?.user) {
|
|
213
|
+
throw new APIError("Unauthorized", 401);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Your custom logic
|
|
217
|
+
res.json({ message: "Hello from analytics!" });
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### `baasix migrate`
|
|
224
|
+
|
|
225
|
+
Database migration management.
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
baasix migrate [action]
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Actions:**
|
|
232
|
+
|
|
233
|
+
| Action | Description |
|
|
234
|
+
|--------|-------------|
|
|
235
|
+
| `status` | Show migration status (pending/executed) |
|
|
236
|
+
| `list` | List all local migrations |
|
|
237
|
+
| `run` | Run pending migrations |
|
|
238
|
+
| `create` | Create a new migration file |
|
|
239
|
+
| `rollback` | Rollback the last batch |
|
|
240
|
+
| `reset` | Rollback all migrations (dangerous!) |
|
|
241
|
+
|
|
242
|
+
**Options:**
|
|
243
|
+
|
|
244
|
+
| Option | Description |
|
|
245
|
+
|--------|-------------|
|
|
246
|
+
| `--url <url>` | Baasix server URL |
|
|
247
|
+
| `-n, --name <name>` | Migration name (for create) |
|
|
248
|
+
| `-s, --steps <number>` | Number of batches to rollback |
|
|
249
|
+
| `-y, --yes` | Skip confirmation prompts |
|
|
250
|
+
|
|
251
|
+
**Example:**
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
# Create a new migration
|
|
255
|
+
baasix migrate create --name add-products-table
|
|
256
|
+
|
|
257
|
+
# Check status
|
|
258
|
+
baasix migrate status --url http://localhost:8056
|
|
259
|
+
|
|
260
|
+
# Run pending migrations
|
|
261
|
+
baasix migrate run --url http://localhost:8056
|
|
262
|
+
|
|
263
|
+
# Rollback last batch
|
|
264
|
+
baasix migrate rollback --url http://localhost:8056 --steps 1
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Migration File Example:**
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
// migrations/20240115120000_add-products-table.js
|
|
271
|
+
export async function up(baasix) {
|
|
272
|
+
await baasix.schema.create("products", {
|
|
273
|
+
name: "Products",
|
|
274
|
+
timestamps: true,
|
|
275
|
+
fields: {
|
|
276
|
+
id: { type: "UUID", primaryKey: true, defaultValue: { type: "UUIDV4" } },
|
|
277
|
+
name: { type: "String", allowNull: false, values: { length: 255 } },
|
|
278
|
+
price: { type: "Decimal", values: { precision: 10, scale: 2 } },
|
|
279
|
+
status: { type: "Enum", values: ["published", "draft", "archived"], defaultValue: "draft" },
|
|
280
|
+
description: { type: "Text" },
|
|
281
|
+
},
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export async function down(baasix) {
|
|
286
|
+
await baasix.schema.delete("products");
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Configuration
|
|
291
|
+
|
|
292
|
+
The CLI reads configuration from environment variables or a `.env` file:
|
|
293
|
+
|
|
294
|
+
```env
|
|
295
|
+
# Required for most commands
|
|
296
|
+
BAASIX_URL=http://localhost:8056
|
|
297
|
+
|
|
298
|
+
# Authentication (optional, for protected operations)
|
|
299
|
+
BAASIX_EMAIL=admin@example.com
|
|
300
|
+
BAASIX_PASSWORD=your-password
|
|
301
|
+
|
|
302
|
+
# Or use token auth
|
|
303
|
+
BAASIX_TOKEN=your-jwt-token
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Project Structure
|
|
307
|
+
|
|
308
|
+
### API Template
|
|
309
|
+
|
|
310
|
+
```
|
|
311
|
+
my-api/
|
|
312
|
+
├── server.js # Entry point
|
|
313
|
+
├── package.json # Dependencies
|
|
314
|
+
├── .env # Configuration
|
|
315
|
+
├── .env.example # Example configuration
|
|
316
|
+
├── extensions/ # Custom hooks & endpoints
|
|
317
|
+
├── migrations/ # Database migrations
|
|
318
|
+
└── uploads/ # File uploads
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Next.js Template (Frontend Only)
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
my-frontend/
|
|
325
|
+
├── src/
|
|
326
|
+
│ ├── app/ # Next.js App Router pages
|
|
327
|
+
│ │ ├── layout.tsx
|
|
328
|
+
│ │ ├── page.tsx
|
|
329
|
+
│ │ └── globals.css
|
|
330
|
+
│ └── lib/
|
|
331
|
+
│ └── baasix.ts # Pre-configured SDK client
|
|
332
|
+
├── package.json
|
|
333
|
+
├── .env.local # Just NEXT_PUBLIC_BAASIX_URL
|
|
334
|
+
└── README.md
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
> **Architecture:** Next.js templates are frontend-only. Create a separate API project with `--template api`.
|
|
338
|
+
|
|
339
|
+
## CI/CD Integration
|
|
340
|
+
|
|
341
|
+
```yaml
|
|
342
|
+
# .github/workflows/deploy.yml
|
|
343
|
+
- name: Generate Types
|
|
344
|
+
run: npx @tspvivek/baasix-cli generate --url ${{ secrets.BAASIX_URL }} -o ./src/types/baasix.d.ts -y
|
|
345
|
+
|
|
346
|
+
- name: Run Migrations
|
|
347
|
+
run: npx @tspvivek/baasix-cli migrate run --url ${{ secrets.BAASIX_URL }} -y
|
|
348
|
+
|
|
349
|
+
- name: Build
|
|
350
|
+
run: npm run build
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## License
|
|
354
|
+
|
|
355
|
+
MIT
|
package/dist/index.d.ts
ADDED