@constela/start 1.2.23 → 1.2.25

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.
Files changed (2) hide show
  1. package/README.md +168 -317
  2. package/package.json +6 -6
package/README.md CHANGED
@@ -8,118 +8,87 @@ Meta-framework for Constela applications with dev server, build tools, and SSG.
8
8
  npm install @constela/start
9
9
  ```
10
10
 
11
- ## Overview
11
+ ## Quick Start
12
12
 
13
- This package provides a full-stack framework for building Constela applications:
14
-
15
- - **Dev Server** - Vite-powered development server with HMR
16
- - **Build** - Production builds with SSG support
17
- - **File Router** - File-based routing conventions
18
- - **Data Loading** - Glob, file, and API data sources
19
- - **MDX** - Markdown with JSX component support
20
- - **Layouts** - Nested layout composition
21
- - **API Routes** - Server-side API endpoints
22
- - **Middleware** - Request middleware chain
23
- - **Edge Adapters** - Deploy to Cloudflare, Vercel, Deno
24
-
25
- ## CLI Usage
13
+ 1. Create a project:
26
14
 
27
15
  ```bash
28
- # Development server
29
- npx constela-start dev --port 3000
30
-
31
- # Production build
32
- npx constela-start build --outDir dist
33
-
34
- # Start production server
35
- npx constela-start start --port 3000
16
+ mkdir my-app && cd my-app
17
+ npm init -y
18
+ npm install @constela/start
19
+ mkdir -p src/routes
36
20
  ```
37
21
 
38
- ## API Reference
39
-
40
- ### createDevServer
22
+ 2. Create a page (`src/routes/index.json`):
41
23
 
42
- Creates a development server with hot reload.
43
-
44
- ```typescript
45
- import { createDevServer } from '@constela/start';
46
-
47
- const server = await createDevServer({
48
- port: 3000,
49
- host: 'localhost',
50
- routesDir: 'src/routes',
51
- publicDir: 'public',
52
- layoutsDir: 'src/layouts',
53
- css: {
54
- links: ['/styles/main.css'],
24
+ ```json
25
+ {
26
+ "version": "1.0",
27
+ "state": {
28
+ "count": { "type": "number", "initial": 0 }
55
29
  },
56
- });
30
+ "actions": [
31
+ {
32
+ "name": "increment",
33
+ "steps": [{ "do": "update", "target": "count", "operation": "increment" }]
34
+ }
35
+ ],
36
+ "view": {
37
+ "kind": "element",
38
+ "tag": "button",
39
+ "props": { "onClick": { "event": "click", "action": "increment" } },
40
+ "children": [{ "kind": "text", "value": { "expr": "state", "name": "count" } }]
41
+ }
42
+ }
57
43
  ```
58
44
 
59
- **DevServerOptions:**
60
- - `port?: number` - Server port (default: 3000)
61
- - `host?: string` - Server host (default: localhost)
62
- - `routesDir?: string` - Routes directory (default: src/routes)
63
- - `publicDir?: string` - Static files directory (default: public)
64
- - `layoutsDir?: string` - Layouts directory
65
- - `css?: { links?: string[] }` - CSS configuration
66
-
67
- ### build
68
-
69
- Builds the application for production.
70
-
71
- ```typescript
72
- import { build } from '@constela/start';
73
-
74
- const result = await build({
75
- outDir: 'dist',
76
- routesDir: 'src/routes',
77
- publicDir: 'public',
78
- layoutsDir: 'src/layouts',
79
- css: { links: ['/styles/main.css'] },
80
- target: 'node', // or 'edge'
81
- });
45
+ 3. Start development:
82
46
 
83
- console.log('Routes:', result.routes);
84
- console.log('Files:', result.files);
47
+ ```bash
48
+ npx constela dev
85
49
  ```
86
50
 
87
- **BuildOptions:**
88
- - `outDir?: string` - Output directory (default: dist)
89
- - `routesDir?: string` - Pages directory
90
- - `publicDir?: string` - Static files directory
91
- - `layoutsDir?: string` - Layouts directory
92
- - `css?: { links?: string[] }` - CSS configuration
93
- - `target?: 'node' | 'edge'` - Build target
51
+ Open http://localhost:3000 to see your app.
94
52
 
95
- ### generateStaticPages
53
+ ## CLI Usage
96
54
 
97
- Generates static HTML pages for SSG.
55
+ ```bash
56
+ # Development server
57
+ npx constela dev --port 3000
98
58
 
99
- ```typescript
100
- import { generateStaticPages } from '@constela/start';
59
+ # Production build
60
+ npx constela build --outDir dist
101
61
 
102
- const files = await generateStaticPages({
103
- routesDir: 'src/routes',
104
- outDir: 'dist',
105
- layoutsDir: 'src/layouts',
106
- });
62
+ # Start production server
63
+ npx constela start --port 3000
107
64
  ```
108
65
 
109
- ## File-Based Routing
110
-
111
- ### scanRoutes
112
-
113
- Discovers routes from the file system.
114
-
115
- ```typescript
116
- import { scanRoutes } from '@constela/start';
66
+ ## Project Structure
117
67
 
118
- const routes = await scanRoutes('src/routes');
119
- // [{ path: '/', file: 'index.json', type: 'page' }, ...]
68
+ ```
69
+ project/
70
+ src/
71
+ routes/ # Page files (.json)
72
+ index.json # / route
73
+ about.json # /about route
74
+ users/
75
+ [id].json # /users/:id route
76
+ layouts/ # Layout files
77
+ main.json
78
+ docs.json
79
+ components/ # Component files
80
+ header.json
81
+ footer.json
82
+ data/ # Data files
83
+ config.json
84
+ navigation.json
85
+ content/ # Content files (MDX)
86
+ blog/
87
+ *.mdx
88
+ public/ # Static assets
120
89
  ```
121
90
 
122
- **Routing Conventions:**
91
+ ## File-Based Routing
123
92
 
124
93
  | File | Route |
125
94
  |------|-------|
@@ -127,44 +96,13 @@ const routes = await scanRoutes('src/routes');
127
96
  | `about.json` | `/about` |
128
97
  | `users/[id].json` | `/users/:id` |
129
98
  | `docs/[...slug].json` | `/docs/*` |
130
- | `api/users.ts` | `/api/users` (API route) |
131
- | `_middleware.ts` | Middleware |
132
-
133
- ### filePathToPattern
134
99
 
135
- Converts file paths to route patterns.
100
+ ## Data Sources
136
101
 
137
- ```typescript
138
- import { filePathToPattern } from '@constela/start';
139
-
140
- filePathToPattern('users/[id].json'); // '/users/:id'
141
- filePathToPattern('docs/[...slug].json'); // '/docs/*'
142
- ```
102
+ Load data at build time:
143
103
 
144
- ## Data Loading
104
+ ### Glob Pattern
145
105
 
146
- ### DataLoader
147
-
148
- Loads data from various sources.
149
-
150
- ```typescript
151
- import { DataLoader } from '@constela/start';
152
-
153
- const loader = new DataLoader('src/routes');
154
-
155
- // Glob pattern
156
- const posts = await loader.loadGlob('content/blog/*.mdx', 'mdx');
157
-
158
- // Single file
159
- const config = await loader.loadFile('data/config.json');
160
-
161
- // API endpoint
162
- const users = await loader.loadApi('https://api.example.com/users');
163
- ```
164
-
165
- ### Data Source Types
166
-
167
- **Glob Pattern:**
168
106
  ```json
169
107
  {
170
108
  "data": {
@@ -177,7 +115,8 @@ const users = await loader.loadApi('https://api.example.com/users');
177
115
  }
178
116
  ```
179
117
 
180
- **File:**
118
+ ### File
119
+
181
120
  ```json
182
121
  {
183
122
  "data": {
@@ -189,7 +128,8 @@ const users = await loader.loadApi('https://api.example.com/users');
189
128
  }
190
129
  ```
191
130
 
192
- **API:**
131
+ ### API
132
+
193
133
  ```json
194
134
  {
195
135
  "data": {
@@ -201,44 +141,54 @@ const users = await loader.loadApi('https://api.example.com/users');
201
141
  }
202
142
  ```
203
143
 
204
- ### Transforms
144
+ **Transforms:** `mdx`, `yaml`, `csv`
205
145
 
206
- - `mdx` - Markdown with JSX to Constela nodes
207
- - `yaml` - YAML to JSON
208
- - `csv` - CSV to array of objects
146
+ ## Layouts
209
147
 
210
- ## MDX Support
148
+ Define reusable layouts:
211
149
 
212
- ### mdxToConstela
150
+ ```json
151
+ {
152
+ "version": "1.0",
153
+ "type": "layout",
154
+ "state": {
155
+ "theme": { "type": "string", "initial": "light" }
156
+ },
157
+ "view": {
158
+ "kind": "element",
159
+ "tag": "div",
160
+ "children": [
161
+ { "kind": "component", "name": "Header" },
162
+ { "kind": "element", "tag": "main", "children": [{ "kind": "slot" }] },
163
+ { "kind": "component", "name": "Footer" }
164
+ ]
165
+ }
166
+ }
167
+ ```
213
168
 
214
- Transforms MDX content to Constela view nodes.
169
+ Use layout in pages:
215
170
 
216
- ```typescript
217
- import { mdxToConstela } from '@constela/start';
218
-
219
- const result = await mdxToConstela(mdxContent, {
220
- components: {
221
- Callout: {
222
- params: { type: { type: 'string' } },
223
- view: { kind: 'element', tag: 'div', ... },
224
- },
225
- },
226
- });
171
+ ```json
172
+ {
173
+ "route": {
174
+ "path": "/docs/:slug",
175
+ "layout": "docs",
176
+ "layoutParams": {
177
+ "title": { "expr": "data", "name": "doc", "path": "title" }
178
+ }
179
+ }
180
+ }
227
181
  ```
228
182
 
229
- **Supported Markdown:**
230
- - Headings, paragraphs, emphasis, strong
231
- - Links, images, lists (ordered/unordered)
232
- - Blockquotes, tables (GFM)
233
- - Code blocks with language
234
- - Horizontal rules, line breaks
183
+ **Named Slots:**
184
+
185
+ ```json
186
+ { "kind": "slot", "name": "sidebar" }
187
+ ```
235
188
 
236
- **MDX Extensions:**
237
- - JSX elements
238
- - Custom components (PascalCase)
239
- - Expression interpolation
189
+ ## Static Paths
240
190
 
241
- ### Static Paths with MDX
191
+ Generate static pages for dynamic routes:
242
192
 
243
193
  ```json
244
194
  {
@@ -261,215 +211,116 @@ const result = await mdxToConstela(mdxContent, {
261
211
  }
262
212
  ```
263
213
 
264
- ## Layout System
214
+ ## MDX Support
265
215
 
266
- ### LayoutResolver
216
+ Markdown files with JSX components:
267
217
 
268
- Manages layout discovery and composition.
218
+ ```mdx
219
+ ---
220
+ title: Getting Started
221
+ ---
269
222
 
270
- ```typescript
271
- import { LayoutResolver } from '@constela/start';
223
+ # Welcome
272
224
 
273
- const resolver = new LayoutResolver('src/layouts');
274
- await resolver.scan();
275
-
276
- if (resolver.has('docs')) {
277
- const layout = await resolver.load('docs');
278
- }
225
+ <Callout type="info">
226
+ This is an info callout.
227
+ </Callout>
279
228
  ```
280
229
 
281
- ### Layout Definition
282
-
283
- ```json
284
- {
285
- "version": "1.0",
286
- "type": "layout",
287
- "view": {
288
- "kind": "element",
289
- "tag": "div",
290
- "children": [
291
- { "kind": "component", "name": "Header" },
292
- { "kind": "slot" },
293
- { "kind": "component", "name": "Footer" }
294
- ]
295
- }
296
- }
297
- ```
298
-
299
- **Named Slots:**
300
- ```json
301
- { "kind": "slot", "name": "sidebar" }
302
- ```
230
+ ## Configuration
303
231
 
304
- ### Page with Layout
232
+ Create `constela.config.json`:
305
233
 
306
234
  ```json
307
235
  {
308
- "route": {
309
- "path": "/docs/:slug",
310
- "layout": "docs",
311
- "layoutParams": {
312
- "title": { "expr": "data", "name": "doc", "path": "title" }
313
- }
314
- }
236
+ "adapter": "node",
237
+ "css": "src/styles/globals.css",
238
+ "layoutsDir": "src/layouts"
315
239
  }
316
240
  ```
317
241
 
318
- ## API Routes
242
+ **Adapters:** `cloudflare`, `vercel`, `deno`, `node`
319
243
 
320
- ### createAPIHandler
244
+ ## Internal API
321
245
 
322
- Creates an API route handler.
246
+ > For framework developers only. End users should use the CLI.
247
+
248
+ ### createDevServer
323
249
 
324
250
  ```typescript
325
- import { createAPIHandler } from '@constela/start';
251
+ import { createDevServer } from '@constela/start';
326
252
 
327
- const handler = createAPIHandler({
328
- GET: async (ctx) => {
329
- return new Response(JSON.stringify({ users: [] }), {
330
- headers: { 'Content-Type': 'application/json' },
331
- });
332
- },
333
- POST: async (ctx) => {
334
- const body = await ctx.request.json();
335
- // ...
336
- },
253
+ const server = await createDevServer({
254
+ port: 3000,
255
+ routesDir: 'src/routes',
256
+ layoutsDir: 'src/layouts',
337
257
  });
338
258
  ```
339
259
 
340
- **APIContext:**
341
- ```typescript
342
- interface APIContext {
343
- params: Record<string, string>;
344
- query: URLSearchParams;
345
- request: Request;
346
- }
347
- ```
348
-
349
- **Supported Methods:** GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
350
-
351
- ## Middleware
352
-
353
- ### createMiddlewareChain
354
-
355
- Creates a middleware chain for request processing.
260
+ ### build
356
261
 
357
262
  ```typescript
358
- import { createMiddlewareChain } from '@constela/start';
359
-
360
- const chain = createMiddlewareChain([
361
- async (ctx, next) => {
362
- console.log('Request:', ctx.url);
363
- const response = await next();
364
- console.log('Response:', response.status);
365
- return response;
366
- },
367
- async (ctx, next) => {
368
- ctx.locals.user = await getUser(ctx.request);
369
- return next();
370
- },
371
- ]);
372
- ```
263
+ import { build } from '@constela/start';
373
264
 
374
- **MiddlewareContext:**
375
- ```typescript
376
- interface MiddlewareContext {
377
- request: Request;
378
- params: Record<string, string>;
379
- url: URL;
380
- locals: Record<string, unknown>;
381
- }
265
+ const result = await build({
266
+ outDir: 'dist',
267
+ routesDir: 'src/routes',
268
+ target: 'node',
269
+ });
382
270
  ```
383
271
 
384
- ## Edge Adapters
385
-
386
- ### createAdapter
387
-
388
- Creates an adapter for edge deployment.
272
+ ### DataLoader
389
273
 
390
274
  ```typescript
391
- import { createAdapter } from '@constela/start';
392
-
393
- const adapter = createAdapter({
394
- platform: 'cloudflare', // or 'vercel', 'deno', 'node'
395
- routes: scannedRoutes,
396
- fallback: notFoundProgram,
397
- });
275
+ import { DataLoader } from '@constela/start';
398
276
 
399
- // Cloudflare Workers
400
- export default {
401
- fetch: adapter.fetch,
402
- };
277
+ const loader = new DataLoader('src/routes');
278
+ const posts = await loader.loadGlob('content/blog/*.mdx', 'mdx');
279
+ const config = await loader.loadFile('data/config.json');
403
280
  ```
404
281
 
405
- **Platforms:**
406
- - `cloudflare` - Cloudflare Workers
407
- - `vercel` - Vercel Edge Functions
408
- - `deno` - Deno Deploy
409
- - `node` - Node.js
410
-
411
- ## Page Types
412
-
413
- ### Static Page
282
+ ### LayoutResolver
414
283
 
415
284
  ```typescript
416
- // pages/about.ts
417
- import type { CompiledProgram } from '@constela/compiler';
418
-
419
- const page: CompiledProgram = {
420
- version: '1.0',
421
- state: {},
422
- actions: {},
423
- view: { kind: 'element', tag: 'div', ... },
424
- };
285
+ import { LayoutResolver } from '@constela/start';
425
286
 
426
- export default page;
287
+ const resolver = new LayoutResolver('src/layouts');
288
+ await resolver.scan();
289
+ const layout = await resolver.load('docs');
427
290
  ```
428
291
 
429
- ### Dynamic Page
292
+ ### API Routes
430
293
 
431
294
  ```typescript
432
- // pages/users/[id].ts
433
- import type { PageExportFunction, StaticPathsResult } from '@constela/start';
434
-
435
- export const getStaticPaths = async (): Promise<StaticPathsResult> => ({
436
- paths: [
437
- { params: { id: '1' } },
438
- { params: { id: '2' } },
439
- ],
440
- });
441
-
442
- const page: PageExportFunction = async (params) => {
443
- const user = await fetchUser(params.id);
444
- return compileUserPage(user);
295
+ // src/routes/api/users.ts
296
+ export const GET = async (ctx) => {
297
+ return new Response(JSON.stringify({ users: [] }), {
298
+ headers: { 'Content-Type': 'application/json' },
299
+ });
445
300
  };
446
-
447
- export default page;
448
301
  ```
449
302
 
450
- ## Configuration
451
-
452
- ### ConstelaConfig
303
+ ### Middleware
453
304
 
454
305
  ```typescript
455
- interface ConstelaConfig {
456
- adapter?: 'cloudflare' | 'vercel' | 'deno' | 'node';
457
- ssg?: {
458
- routes?: string[];
459
- };
460
- }
306
+ // src/routes/_middleware.ts
307
+ export default async (ctx, next) => {
308
+ console.log('Request:', ctx.url);
309
+ return next();
310
+ };
461
311
  ```
462
312
 
463
- ## Exports
464
-
465
- ### Runtime Entry Points
313
+ ### Edge Adapters
466
314
 
467
315
  ```typescript
468
- // Client-side hydration
469
- import '@constela/start/client';
316
+ import { createAdapter } from '@constela/start';
317
+
318
+ const adapter = createAdapter({
319
+ platform: 'cloudflare',
320
+ routes: scannedRoutes,
321
+ });
470
322
 
471
- // Server-side rendering
472
- import { render } from '@constela/start/server';
323
+ export default { fetch: adapter.fetch };
473
324
  ```
474
325
 
475
326
  ## License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/start",
3
- "version": "1.2.23",
3
+ "version": "1.2.25",
4
4
  "description": "Meta-framework for Constela applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -43,11 +43,11 @@
43
43
  "postcss": "^8.5.0",
44
44
  "@tailwindcss/postcss": "^4.0.0",
45
45
  "tailwindcss": "^4.0.0",
46
- "@constela/compiler": "0.7.1",
47
- "@constela/core": "0.7.0",
48
- "@constela/runtime": "0.10.3",
49
- "@constela/server": "3.0.1",
50
- "@constela/router": "8.0.0"
46
+ "@constela/compiler": "0.8.0",
47
+ "@constela/core": "0.8.0",
48
+ "@constela/server": "4.1.0",
49
+ "@constela/router": "9.0.0",
50
+ "@constela/runtime": "0.11.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/mdast": "^4.0.4",