@noego/stitch 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/README-schema.md +139 -0
- package/bin/stitch.js +156 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/cli/StitchCLI.d.ts +12 -0
- package/dist/cli/StitchCLI.d.ts.map +1 -0
- package/dist/client.cjs +2 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.mjs +83 -0
- package/dist/client.mjs.map +1 -0
- package/dist/core/ConfigParser.d.ts +16 -0
- package/dist/core/ConfigParser.d.ts.map +1 -0
- package/dist/core/StitchEngine.d.ts +31 -0
- package/dist/core/StitchEngine.d.ts.map +1 -0
- package/dist/core/Validator.d.ts +18 -0
- package/dist/core/Validator.d.ts.map +1 -0
- package/dist/core/ViteHelper.d.ts +33 -0
- package/dist/core/ViteHelper.d.ts.map +1 -0
- package/dist/core/YamlMerger.d.ts +29 -0
- package/dist/core/YamlMerger.d.ts.map +1 -0
- package/dist/core/YamlMergerBrowser.d.ts +18 -0
- package/dist/core/YamlMergerBrowser.d.ts.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/types/StitchTypes.d.ts +38 -0
- package/dist/types/StitchTypes.d.ts.map +1 -0
- package/dist-ssr/browser/index.d.ts +4 -0
- package/dist-ssr/browser/index.d.ts.map +1 -0
- package/dist-ssr/cli/StitchCLI.d.ts +12 -0
- package/dist-ssr/cli/StitchCLI.d.ts.map +1 -0
- package/dist-ssr/core/ConfigParser.d.ts +16 -0
- package/dist-ssr/core/ConfigParser.d.ts.map +1 -0
- package/dist-ssr/core/StitchEngine.d.ts +31 -0
- package/dist-ssr/core/StitchEngine.d.ts.map +1 -0
- package/dist-ssr/core/Validator.d.ts +18 -0
- package/dist-ssr/core/Validator.d.ts.map +1 -0
- package/dist-ssr/core/ViteHelper.d.ts +33 -0
- package/dist-ssr/core/ViteHelper.d.ts.map +1 -0
- package/dist-ssr/core/YamlMerger.d.ts +29 -0
- package/dist-ssr/core/YamlMerger.d.ts.map +1 -0
- package/dist-ssr/core/YamlMergerBrowser.d.ts +18 -0
- package/dist-ssr/core/YamlMergerBrowser.d.ts.map +1 -0
- package/dist-ssr/index.d.ts +15 -0
- package/dist-ssr/index.d.ts.map +1 -0
- package/dist-ssr/server.cjs +574 -0
- package/dist-ssr/server.cjs.map +1 -0
- package/dist-ssr/server.d.ts +2 -0
- package/dist-ssr/server.js +554 -0
- package/dist-ssr/server.js.map +1 -0
- package/dist-ssr/types/StitchTypes.d.ts +38 -0
- package/dist-ssr/types/StitchTypes.d.ts.map +1 -0
- package/docs/advanced_validation.md +188 -0
- package/docs/middleware.md +507 -0
- package/docs/modules.md +175 -0
- package/docs/project.md +856 -0
- package/docs/validation.md +77 -0
- package/package.json +67 -0
- package/readme.md +159 -0
- package/schemas/schema.json +360 -0
- package/schemas/stitch-schema.json +38 -0
package/docs/project.md
ADDED
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
# Stitch Project Plan: YAML Modularization for Groom Application
|
|
2
|
+
|
|
3
|
+
## Problem Statement
|
|
4
|
+
|
|
5
|
+
The Groom barber shop application has grown to use large OpenAPI YAML files that are becoming difficult to maintain:
|
|
6
|
+
|
|
7
|
+
- **Backend OpenAPI**: `/Users/shavauhngabay/dev/groom/backend/openapi.yaml` (1,511 lines)
|
|
8
|
+
- **Frontend OpenAPI**: `/Users/shavauhngabay/dev/groom/frontend/openapi.yaml` (466 lines)
|
|
9
|
+
|
|
10
|
+
These monolithic files contain:
|
|
11
|
+
- **Backend**: API endpoint definitions with controllers, middleware, and schemas
|
|
12
|
+
- **Frontend**: Route definitions with Svelte views and layouts for the Forge framework
|
|
13
|
+
|
|
14
|
+
As the application grows, these files will become increasingly unwieldy and difficult to collaborate on.
|
|
15
|
+
|
|
16
|
+
## Current Architecture Analysis
|
|
17
|
+
|
|
18
|
+
### Backend (`/groom/backend/`)
|
|
19
|
+
- Uses `@noego/dinner` framework for API routing
|
|
20
|
+
- OpenAPI file defines REST endpoints with custom extensions:
|
|
21
|
+
- `x-controller`: Points to controller classes
|
|
22
|
+
- `x-action`: Specifies controller methods
|
|
23
|
+
- `x-middleware`: Defines middleware chains
|
|
24
|
+
- File structure includes paths, components/schemas, and security definitions
|
|
25
|
+
- Consumed by dinner framework for automatic route generation
|
|
26
|
+
|
|
27
|
+
### Frontend (`/groom/frontend/`)
|
|
28
|
+
- Uses `@noego/forge` framework for SSR/client-side routing
|
|
29
|
+
- OpenAPI file defines page routes with custom extensions:
|
|
30
|
+
- `x-view`: Specifies Svelte component to render
|
|
31
|
+
- `x-layout`: Defines layout component hierarchy
|
|
32
|
+
- Consumed by forge framework for automatic route generation and component loading
|
|
33
|
+
- Client configured in `client.ts` to load `frontend/openapi.yaml`
|
|
34
|
+
- Server configured in `app.ts` to load same OpenAPI file
|
|
35
|
+
|
|
36
|
+
## Solution: Stitch YAML Modularization Tool
|
|
37
|
+
|
|
38
|
+
### Core Concept
|
|
39
|
+
Stitch will allow breaking down large OpenAPI YAML files into smaller, manageable modules that can be combined at build time or runtime.
|
|
40
|
+
|
|
41
|
+
### Proposed File Structure
|
|
42
|
+
|
|
43
|
+
#### Backend Modularization
|
|
44
|
+
```
|
|
45
|
+
/groom/backend/
|
|
46
|
+
├── stitch.yaml # Main stitch configuration
|
|
47
|
+
├── openapi/
|
|
48
|
+
│ ├── base.yaml # OpenAPI header, info, servers
|
|
49
|
+
│ ├── security.yaml # Security schemes and definitions
|
|
50
|
+
│ ├── components/
|
|
51
|
+
│ │ ├── schemas/
|
|
52
|
+
│ │ │ ├── user.yaml
|
|
53
|
+
│ │ │ ├── business.yaml
|
|
54
|
+
│ │ │ └── booking.yaml
|
|
55
|
+
│ │ └── responses.yaml
|
|
56
|
+
│ └── paths/
|
|
57
|
+
│ ├── users.yaml # All user-related endpoints
|
|
58
|
+
│ ├── businesses.yaml # All business-related endpoints
|
|
59
|
+
│ ├── bookings.yaml # All booking-related endpoints
|
|
60
|
+
│ └── auth.yaml # Authentication endpoints
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Frontend Modularization
|
|
64
|
+
```
|
|
65
|
+
/groom/frontend/
|
|
66
|
+
├── stitch.yaml # Main stitch configuration
|
|
67
|
+
├── openapi/
|
|
68
|
+
│ ├── base.yaml # OpenAPI header and info
|
|
69
|
+
│ ├── layouts.yaml # Global layout definitions
|
|
70
|
+
│ └── routes/
|
|
71
|
+
│ ├── home.yaml # Home page routes
|
|
72
|
+
│ ├── users.yaml # User-related pages
|
|
73
|
+
│ ├── businesses.yaml # Business-related pages
|
|
74
|
+
│ ├── bookings.yaml # Booking-related pages
|
|
75
|
+
│ └── auth.yaml # Authentication pages
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Stitch Configuration Format
|
|
79
|
+
|
|
80
|
+
**Simple and Clean**: Stitch uses a minimal configuration format that just lists files to merge.
|
|
81
|
+
|
|
82
|
+
#### Backend `stitch.yaml`
|
|
83
|
+
```yaml
|
|
84
|
+
stitch:
|
|
85
|
+
- openapi/base.yaml
|
|
86
|
+
- openapi/security.yaml
|
|
87
|
+
- openapi/paths/*.yaml
|
|
88
|
+
- openapi/components/responses.yaml
|
|
89
|
+
- openapi/components/schemas/*.yaml
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Frontend `stitch.yaml`
|
|
93
|
+
```yaml
|
|
94
|
+
stitch:
|
|
95
|
+
- openapi/base.yaml
|
|
96
|
+
- openapi/layouts.yaml
|
|
97
|
+
- openapi/routes/*.yaml
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**How it works:**
|
|
101
|
+
- Files are merged in order using deep merge
|
|
102
|
+
- Supports glob patterns (e.g., `*.yaml`, `**/*.yaml`)
|
|
103
|
+
- Globs are expanded and sorted alphabetically
|
|
104
|
+
- Later files override earlier files for conflicting keys
|
|
105
|
+
- Arrays and objects are merged intelligently
|
|
106
|
+
- All paths are relative to the stitch.yaml file location
|
|
107
|
+
|
|
108
|
+
### Implementation Strategy
|
|
109
|
+
|
|
110
|
+
The approach is to build Stitch as a standalone tool first, then update forge and dinner to use Stitch for YAML loading. This ensures Stitch works independently before integration.
|
|
111
|
+
|
|
112
|
+
#### Phase 1: Standalone Stitch Tool (Current Focus)
|
|
113
|
+
|
|
114
|
+
**Goal**: Create a working YAML modularization tool that can be used independently via CLI or programmatic API.
|
|
115
|
+
|
|
116
|
+
##### Step 1: Core Dependencies & Setup
|
|
117
|
+
```bash
|
|
118
|
+
# Add required dependencies
|
|
119
|
+
npm install js-yaml @types/js-yaml chokidar @types/chokidar ajv ajv-formats glob @types/glob
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Dependencies needed:
|
|
123
|
+
- `js-yaml` - YAML parsing and serialization (same as forge uses)
|
|
124
|
+
- `chokidar` - File watching for watch mode
|
|
125
|
+
- `ajv` + `ajv-formats` - JSON Schema validation for OpenAPI validation
|
|
126
|
+
- `glob` - Glob pattern matching for file expansion
|
|
127
|
+
|
|
128
|
+
##### Step 2: Core Engine Implementation
|
|
129
|
+
|
|
130
|
+
**File Structure:**
|
|
131
|
+
```
|
|
132
|
+
src/
|
|
133
|
+
├── index.ts # Main API exports
|
|
134
|
+
├── cli/
|
|
135
|
+
│ └── StitchCLI.ts # CLI argument parser (already exists)
|
|
136
|
+
├── core/
|
|
137
|
+
│ ├── StitchEngine.ts # Main processing engine
|
|
138
|
+
│ ├── ConfigParser.ts # Parse stitch.yaml configuration
|
|
139
|
+
│ ├── YamlMerger.ts # YAML merging logic
|
|
140
|
+
│ └── Validator.ts # OpenAPI validation
|
|
141
|
+
├── types/
|
|
142
|
+
│ └── StitchTypes.ts # TypeScript interfaces
|
|
143
|
+
└── utils/
|
|
144
|
+
└── FileUtils.ts # File system utilities
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Core Components:**
|
|
148
|
+
|
|
149
|
+
1. **StitchEngine.ts** - Main orchestrator
|
|
150
|
+
```typescript
|
|
151
|
+
export class StitchEngine {
|
|
152
|
+
async build(configPath: string, options: BuildOptions): Promise<StitchResult>
|
|
153
|
+
buildSync(configPath: string, options: BuildOptions): StitchResult
|
|
154
|
+
async watch(configPath: string, options: WatchOptions): Promise<void>
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Processing flow:
|
|
158
|
+
// 1. Parse stitch.yaml config
|
|
159
|
+
// 2. Expand any glob patterns to actual file paths
|
|
160
|
+
// 3. Load and parse each YAML file in order
|
|
161
|
+
// 4. Deep merge files in order (later files override earlier)
|
|
162
|
+
// 5. Validate merged result if requested
|
|
163
|
+
// 6. Output as YAML/JSON to stdout or file
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
2. **ConfigParser.ts** - Parse stitch.yaml files
|
|
167
|
+
```typescript
|
|
168
|
+
export interface StitchConfig {
|
|
169
|
+
stitch: string[]; // Array of file paths/globs to merge in order
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export class ConfigParser {
|
|
173
|
+
parseConfig(configPath: string): StitchConfig
|
|
174
|
+
resolveFilePaths(patterns: string[], baseDir: string): string[]
|
|
175
|
+
expandGlobs(patterns: string[], baseDir: string): string[]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
3. **YamlMerger.ts** - Deep YAML merging
|
|
180
|
+
```typescript
|
|
181
|
+
export class YamlMerger {
|
|
182
|
+
mergeFiles(files: string[]): any
|
|
183
|
+
deepMerge(target: any, source: any): any
|
|
184
|
+
|
|
185
|
+
// Deep merge rules:
|
|
186
|
+
// - Objects: merge properties, source overrides target
|
|
187
|
+
// - Arrays: source replaces target completely
|
|
188
|
+
// - Primitives: source overrides target
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
4. **Validator.ts** - OpenAPI schema validation
|
|
193
|
+
```typescript
|
|
194
|
+
export class Validator {
|
|
195
|
+
validateOpenAPI(yamlContent: any): ValidationResult
|
|
196
|
+
validateYamlSyntax(yamlString: string): ValidationResult
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
##### Step 3: CLI Implementation
|
|
201
|
+
|
|
202
|
+
Update `cli.ts` to implement actual functionality:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
// cli.ts updates needed
|
|
206
|
+
switch(command.toLowerCase()){
|
|
207
|
+
case "build":
|
|
208
|
+
const inputFile = commands[1] || 'stitch.yaml';
|
|
209
|
+
const engine = new StitchEngine();
|
|
210
|
+
const result = await engine.build(inputFile, {
|
|
211
|
+
output: args.flags.output,
|
|
212
|
+
format: args.flags.format || 'yaml',
|
|
213
|
+
validate: args.flags.validate,
|
|
214
|
+
quiet: args.flags.quiet
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
if (result.success) {
|
|
218
|
+
if (!args.flags.quiet) {
|
|
219
|
+
if (args.flags.output) {
|
|
220
|
+
console.log(`Built successfully to ${args.flags.output}`);
|
|
221
|
+
} else {
|
|
222
|
+
console.log(result.data); // Output to stdout
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
console.error(result.error);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
break;
|
|
230
|
+
|
|
231
|
+
case "watch":
|
|
232
|
+
const watchFile = commands[1] || 'stitch.yaml';
|
|
233
|
+
const engine = new StitchEngine();
|
|
234
|
+
await engine.watch(watchFile, {
|
|
235
|
+
output: args.flags.output,
|
|
236
|
+
format: args.flags.format || 'yaml',
|
|
237
|
+
validate: args.flags.validate,
|
|
238
|
+
quiet: args.flags.quiet
|
|
239
|
+
});
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
##### Step 4: Programmatic API
|
|
245
|
+
|
|
246
|
+
Export clean API in `src/index.ts`:
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
export { StitchEngine } from './core/StitchEngine';
|
|
250
|
+
export * from './types/StitchTypes';
|
|
251
|
+
|
|
252
|
+
// Convenience functions
|
|
253
|
+
export const stitch = {
|
|
254
|
+
build: async (options: BuildOptions) => new StitchEngine().build(options.input || 'stitch.yaml', options),
|
|
255
|
+
buildSync: (options: BuildOptions) => new StitchEngine().buildSync(options.input || 'stitch.yaml', options),
|
|
256
|
+
watch: async (options: WatchOptions) => new StitchEngine().watch(options.input || 'stitch.yaml', options),
|
|
257
|
+
};
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
##### Step 5: Testing Strategy
|
|
261
|
+
|
|
262
|
+
Create test files to validate functionality:
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
test/
|
|
266
|
+
├── fixtures/
|
|
267
|
+
│ ├── simple/
|
|
268
|
+
│ │ ├── stitch.yaml # stitch: [base.yaml, paths.yaml]
|
|
269
|
+
│ │ ├── base.yaml # OpenAPI header, info
|
|
270
|
+
│ │ └── paths.yaml # paths section
|
|
271
|
+
│ └── complex/
|
|
272
|
+
│ ├── stitch.yaml # stitch: [base.yaml, paths/users.yaml, ...]
|
|
273
|
+
│ ├── base.yaml # OpenAPI header, info, servers
|
|
274
|
+
│ ├── paths/
|
|
275
|
+
│ │ ├── users.yaml # paths: { /users: {...} }
|
|
276
|
+
│ │ └── businesses.yaml # paths: { /businesses: {...} }
|
|
277
|
+
│ └── components/
|
|
278
|
+
│ └── schemas.yaml # components: { schemas: {...} }
|
|
279
|
+
└── StitchEngine.test.ts
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Example simple test case:**
|
|
283
|
+
|
|
284
|
+
`test/fixtures/simple/stitch.yaml`:
|
|
285
|
+
```yaml
|
|
286
|
+
stitch:
|
|
287
|
+
- base.yaml
|
|
288
|
+
- paths.yaml
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Example with globs:**
|
|
292
|
+
|
|
293
|
+
`test/fixtures/complex/stitch.yaml`:
|
|
294
|
+
```yaml
|
|
295
|
+
stitch:
|
|
296
|
+
- base.yaml
|
|
297
|
+
- paths/*.yaml
|
|
298
|
+
- components/**/*.yaml
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
`test/fixtures/simple/base.yaml`:
|
|
302
|
+
```yaml
|
|
303
|
+
openapi: '3.0.3'
|
|
304
|
+
info:
|
|
305
|
+
title: Test API
|
|
306
|
+
version: '1.0.0'
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
`test/fixtures/simple/paths.yaml`:
|
|
310
|
+
```yaml
|
|
311
|
+
paths:
|
|
312
|
+
/test:
|
|
313
|
+
get:
|
|
314
|
+
summary: Test endpoint
|
|
315
|
+
responses:
|
|
316
|
+
'200':
|
|
317
|
+
description: OK
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**Expected merged result:**
|
|
321
|
+
```yaml
|
|
322
|
+
openapi: '3.0.3'
|
|
323
|
+
info:
|
|
324
|
+
title: Test API
|
|
325
|
+
version: '1.0.0'
|
|
326
|
+
paths:
|
|
327
|
+
/test:
|
|
328
|
+
get:
|
|
329
|
+
summary: Test endpoint
|
|
330
|
+
responses:
|
|
331
|
+
'200':
|
|
332
|
+
description: OK
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
#### Phase 2: Integration with Forge/Dinner (Future)
|
|
336
|
+
|
|
337
|
+
Once Stitch is working standalone:
|
|
338
|
+
|
|
339
|
+
1. **Update forge** to use Stitch for YAML loading
|
|
340
|
+
- Modify `src/parser/openapi.ts` to optionally use Stitch
|
|
341
|
+
- Add fallback to current behavior for backward compatibility
|
|
342
|
+
|
|
343
|
+
2. **Update dinner** to use Stitch for YAML loading
|
|
344
|
+
- Similar integration approach
|
|
345
|
+
|
|
346
|
+
3. **Groom Migration**
|
|
347
|
+
- Split existing YAML files using working Stitch tool
|
|
348
|
+
- Update build processes to use Stitch
|
|
349
|
+
|
|
350
|
+
#### Success Criteria for Phase 1
|
|
351
|
+
|
|
352
|
+
1. ✅ CLI commands work: `stitch build`, `stitch watch`
|
|
353
|
+
2. ✅ Options work: `--output`, `--format`, `--validate`, `--quiet`
|
|
354
|
+
3. ✅ Programmatic API works: `stitch.build()`, `stitch.buildSync()`
|
|
355
|
+
4. ✅ YAML merging preserves OpenAPI structure correctly
|
|
356
|
+
5. ✅ Watch mode detects file changes and rebuilds
|
|
357
|
+
6. ✅ Validation catches invalid YAML and OpenAPI issues
|
|
358
|
+
7. ✅ Error messages are clear and helpful
|
|
359
|
+
8. ✅ Performance is acceptable (< 1 second for typical builds)
|
|
360
|
+
|
|
361
|
+
## Phase 1.5: Binary Distribution Setup (Current Task)
|
|
362
|
+
|
|
363
|
+
**Goal**: Package Stitch as a distributable npm package with a global CLI binary.
|
|
364
|
+
|
|
365
|
+
### Tasks to Complete
|
|
366
|
+
|
|
367
|
+
1. **Build System Setup**
|
|
368
|
+
- Configure TypeScript compilation for distribution
|
|
369
|
+
- Set up proper build pipeline for binary distribution
|
|
370
|
+
- Ensure all dependencies are properly bundled/referenced
|
|
371
|
+
|
|
372
|
+
2. **Binary Configuration**
|
|
373
|
+
- Add `bin` field to package.json pointing to compiled CLI
|
|
374
|
+
- Create executable CLI entry point
|
|
375
|
+
- Set proper file permissions and shebang
|
|
376
|
+
|
|
377
|
+
3. **Package.json Updates**
|
|
378
|
+
- Configure proper exports for both programmatic and CLI usage
|
|
379
|
+
- Set up build scripts for distribution
|
|
380
|
+
- Ensure proper entry points for different use cases
|
|
381
|
+
|
|
382
|
+
4. **Distribution Testing**
|
|
383
|
+
- Test global installation: `npm install -g .`
|
|
384
|
+
- Verify `stitch` command works globally
|
|
385
|
+
- Test both local and global package usage
|
|
386
|
+
- Ensure programmatic API still works after build
|
|
387
|
+
|
|
388
|
+
### Implementation Plan
|
|
389
|
+
|
|
390
|
+
#### Step 1: TypeScript Build Configuration
|
|
391
|
+
|
|
392
|
+
**Current Issue**: We're using `tsx` for development, but need compiled JavaScript for distribution.
|
|
393
|
+
|
|
394
|
+
**Solution**:
|
|
395
|
+
- Configure TypeScript to compile to a `bin/` directory
|
|
396
|
+
- Create a standalone CLI entry point that doesn't require tsx
|
|
397
|
+
- Update build scripts to generate distribution-ready files
|
|
398
|
+
|
|
399
|
+
**Updated File Structure:**
|
|
400
|
+
```
|
|
401
|
+
dist/ # Compiled JavaScript output
|
|
402
|
+
├── core/
|
|
403
|
+
│ ├── StitchEngine.js
|
|
404
|
+
│ ├── ConfigParser.js
|
|
405
|
+
│ ├── YamlMerger.js
|
|
406
|
+
│ └── Validator.js
|
|
407
|
+
├── types/
|
|
408
|
+
│ └── StitchTypes.js
|
|
409
|
+
├── cli/
|
|
410
|
+
│ └── StitchCLI.js
|
|
411
|
+
└── index.js # Main API export
|
|
412
|
+
|
|
413
|
+
bin/
|
|
414
|
+
└── stitch.js # CLI entry point (executable)
|
|
415
|
+
|
|
416
|
+
src/ # Source TypeScript (unchanged)
|
|
417
|
+
cli.ts # Development CLI (stays for dev)
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
#### Step 2: CLI Entry Point Creation
|
|
421
|
+
|
|
422
|
+
Create `bin/stitch.js` as the executable entry point:
|
|
423
|
+
|
|
424
|
+
```javascript
|
|
425
|
+
#!/usr/bin/env node
|
|
426
|
+
|
|
427
|
+
// Production CLI entry point - uses compiled JavaScript
|
|
428
|
+
const { StitchEngine } = require('../dist/core/StitchEngine');
|
|
429
|
+
const { StitchCLIFactory } = require('../dist/cli/StitchCLI');
|
|
430
|
+
|
|
431
|
+
// Similar logic to cli.ts but using compiled modules
|
|
432
|
+
// Handle all CLI commands and flags
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
#### Step 3: Package.json Configuration
|
|
436
|
+
|
|
437
|
+
**Add Binary Configuration:**
|
|
438
|
+
```json
|
|
439
|
+
{
|
|
440
|
+
"bin": {
|
|
441
|
+
"stitch": "./bin/stitch.js"
|
|
442
|
+
},
|
|
443
|
+
"main": "./dist/index.js",
|
|
444
|
+
"types": "./dist/index.d.ts",
|
|
445
|
+
"files": [
|
|
446
|
+
"dist/**/*",
|
|
447
|
+
"bin/**/*",
|
|
448
|
+
"README.md"
|
|
449
|
+
]
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**Updated Scripts:**
|
|
454
|
+
```json
|
|
455
|
+
{
|
|
456
|
+
"scripts": {
|
|
457
|
+
"build": "tsc && npm run build:bin",
|
|
458
|
+
"build:bin": "node scripts/create-bin.js",
|
|
459
|
+
"build:client": "vite build --config vite.config.js",
|
|
460
|
+
"build:ssr": "SSR=true vite build --ssr",
|
|
461
|
+
"dev": "tsx cli.ts",
|
|
462
|
+
"test": "jest",
|
|
463
|
+
"prepublishOnly": "npm run build",
|
|
464
|
+
"postinstall": "chmod +x bin/stitch.js"
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
#### Step 4: TypeScript Configuration Updates
|
|
470
|
+
|
|
471
|
+
**Update tsconfig.json:**
|
|
472
|
+
```json
|
|
473
|
+
{
|
|
474
|
+
"compilerOptions": {
|
|
475
|
+
"outDir": "dist",
|
|
476
|
+
"declaration": true,
|
|
477
|
+
"declarationMap": true,
|
|
478
|
+
"target": "ES2020",
|
|
479
|
+
"module": "CommonJS",
|
|
480
|
+
"moduleResolution": "node"
|
|
481
|
+
},
|
|
482
|
+
"include": ["src/**/*"],
|
|
483
|
+
"exclude": ["node_modules", "dist", "test", "bin"]
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
#### Step 5: Distribution Workflow
|
|
488
|
+
|
|
489
|
+
1. **Development**: Use `npm run dev` (tsx cli.ts)
|
|
490
|
+
2. **Testing**: Use `npm test` (jest on source files)
|
|
491
|
+
3. **Building**: Use `npm run build` (compile + create bin)
|
|
492
|
+
4. **Local Install**: Use `npm install -g .` (test global CLI)
|
|
493
|
+
5. **Publishing**: Use `npm publish` (with prepublishOnly hook)
|
|
494
|
+
|
|
495
|
+
### Testing Plan
|
|
496
|
+
|
|
497
|
+
1. **Build Test**: `npm run build` should create dist/ and bin/
|
|
498
|
+
2. **Local Install Test**: `npm install -g .` should make `stitch` available
|
|
499
|
+
3. **CLI Test**: `stitch build test/fixtures/simple/stitch.yaml` should work
|
|
500
|
+
4. **API Test**: `import { stitch } from 'stitch'` should work
|
|
501
|
+
5. **Uninstall Test**: `npm uninstall -g stitch` should clean up
|
|
502
|
+
|
|
503
|
+
### Success Criteria for Phase 1.5
|
|
504
|
+
|
|
505
|
+
1. ✅ `npm run build` generates distribution files
|
|
506
|
+
2. ✅ `npm install -g .` installs CLI globally
|
|
507
|
+
3. ✅ `stitch build [file]` works from any directory
|
|
508
|
+
4. ✅ Programmatic API works: `require('stitch')` or `import { stitch }`
|
|
509
|
+
5. ✅ Package is ready for npm publish
|
|
510
|
+
6. ✅ All original functionality preserved
|
|
511
|
+
7. ✅ Binary has proper permissions and works cross-platform
|
|
512
|
+
8. ✅ Clean uninstall with `npm uninstall -g stitch`
|
|
513
|
+
|
|
514
|
+
## Phase 2: Client-Side / Vite Integration
|
|
515
|
+
|
|
516
|
+
**Goal**: Enable Stitch to work in browser environments with Vite's `?raw` import system.
|
|
517
|
+
|
|
518
|
+
### Background
|
|
519
|
+
|
|
520
|
+
Currently Stitch reads YAML files from the filesystem using Node.js `fs` module. This works great for:
|
|
521
|
+
- CLI usage (server-side)
|
|
522
|
+
- Node.js programmatic API
|
|
523
|
+
|
|
524
|
+
However, for client-side usage (like in forge framework), we need to support Vite's import system where YAML content is imported at build time using the `?raw` suffix.
|
|
525
|
+
|
|
526
|
+
**Current forge pattern:**
|
|
527
|
+
```typescript
|
|
528
|
+
// Dynamic YAML import with Vite's raw import
|
|
529
|
+
let open_api_config = (await import(/* @vite-ignore */ config+'?raw')).default;
|
|
530
|
+
open_api_config = yaml.load(open_api_config);
|
|
531
|
+
routes = transform_openapi_config(open_api_config);
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Proposed Enhancement
|
|
535
|
+
|
|
536
|
+
#### New API: Content-Based Merging
|
|
537
|
+
|
|
538
|
+
Add support for merging YAML content directly (not just file paths):
|
|
539
|
+
|
|
540
|
+
```typescript
|
|
541
|
+
// New interface for content-based merging
|
|
542
|
+
export interface StitchContentConfig {
|
|
543
|
+
stitch: Array<string | { content: string; name?: string }>;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// New methods on YamlMerger
|
|
547
|
+
export class YamlMerger {
|
|
548
|
+
// Existing file-based method
|
|
549
|
+
mergeFiles(filePaths: string[]): any
|
|
550
|
+
|
|
551
|
+
// New content-based method
|
|
552
|
+
mergeContent(contents: Array<{ content: string; name?: string }>): any
|
|
553
|
+
|
|
554
|
+
// Mixed method (files + content)
|
|
555
|
+
merge(items: Array<string | { content: string; name?: string }>): any
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
#### Usage Examples
|
|
560
|
+
|
|
561
|
+
**Pure content merging (client-side):**
|
|
562
|
+
```typescript
|
|
563
|
+
import baseYaml from './openapi/base.yaml?raw';
|
|
564
|
+
import pathsYaml from './openapi/paths.yaml?raw';
|
|
565
|
+
import { YamlMerger } from 'stitch';
|
|
566
|
+
|
|
567
|
+
const merger = new YamlMerger();
|
|
568
|
+
const result = merger.mergeContent([
|
|
569
|
+
{ content: baseYaml, name: 'base.yaml' },
|
|
570
|
+
{ content: pathsYaml, name: 'paths.yaml' }
|
|
571
|
+
]);
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
**Mixed file and content merging:**
|
|
575
|
+
```typescript
|
|
576
|
+
const merger = new YamlMerger();
|
|
577
|
+
const result = merger.merge([
|
|
578
|
+
'base.yaml', // File path (Node.js)
|
|
579
|
+
{ content: importedYaml, name: 'imported.yaml' } // Raw content
|
|
580
|
+
]);
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
**Vite integration helper:**
|
|
584
|
+
```typescript
|
|
585
|
+
// Helper function for Vite environments
|
|
586
|
+
export async function stitchFromViteImports(imports: Record<string, () => Promise<{ default: string }>>) {
|
|
587
|
+
const contents = await Promise.all(
|
|
588
|
+
Object.entries(imports).map(async ([path, importFn]) => ({
|
|
589
|
+
content: (await importFn()).default,
|
|
590
|
+
name: path
|
|
591
|
+
}))
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
const merger = new YamlMerger();
|
|
595
|
+
return merger.mergeContent(contents);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Usage:
|
|
599
|
+
const imports = import.meta.glob('./openapi/*.yaml', { as: 'raw' });
|
|
600
|
+
const merged = await stitchFromViteImports(imports);
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
#### Implementation Plan
|
|
604
|
+
|
|
605
|
+
1. **Extend YamlMerger class**
|
|
606
|
+
- Add `mergeContent()` method for content-based merging
|
|
607
|
+
- Add `merge()` method for mixed file/content merging
|
|
608
|
+
- Maintain existing `mergeFiles()` for backward compatibility
|
|
609
|
+
|
|
610
|
+
2. **Update StitchEngine**
|
|
611
|
+
- Add content-based build methods
|
|
612
|
+
- Support mixed configurations
|
|
613
|
+
- Maintain file-based CLI functionality
|
|
614
|
+
|
|
615
|
+
3. **Add Vite helpers**
|
|
616
|
+
- Helper functions for common Vite patterns
|
|
617
|
+
- Integration utilities for `import.meta.glob()`
|
|
618
|
+
- Documentation and examples
|
|
619
|
+
|
|
620
|
+
4. **Browser compatibility**
|
|
621
|
+
- Ensure YamlMerger works in browser environments
|
|
622
|
+
- Remove Node.js-specific dependencies from core merge logic
|
|
623
|
+
- Provide separate builds for Node.js vs browser
|
|
624
|
+
|
|
625
|
+
#### File Structure Changes
|
|
626
|
+
|
|
627
|
+
```
|
|
628
|
+
src/
|
|
629
|
+
├── core/
|
|
630
|
+
│ ├── StitchEngine.ts # Node.js + content support
|
|
631
|
+
│ ├── YamlMerger.ts # Universal (Node.js + browser)
|
|
632
|
+
│ └── ViteHelper.ts # NEW: Vite-specific utilities
|
|
633
|
+
├── browser/
|
|
634
|
+
│ └── index.ts # NEW: Browser-specific exports
|
|
635
|
+
└── node/
|
|
636
|
+
└── index.ts # NEW: Node.js-specific exports
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
#### Package.json Exports
|
|
640
|
+
|
|
641
|
+
```json
|
|
642
|
+
{
|
|
643
|
+
"exports": {
|
|
644
|
+
".": {
|
|
645
|
+
"browser": "./dist/browser/index.js",
|
|
646
|
+
"node": "./dist/node/index.js",
|
|
647
|
+
"default": "./dist/index.js"
|
|
648
|
+
},
|
|
649
|
+
"./vite": "./dist/core/ViteHelper.js"
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
### Benefits
|
|
655
|
+
|
|
656
|
+
1. **Universal Usage**: Same merging logic works in Node.js and browser
|
|
657
|
+
2. **Vite Integration**: Native support for Vite's import system
|
|
658
|
+
3. **Performance**: No runtime file system access in browser builds
|
|
659
|
+
4. **Flexibility**: Mix file-based and content-based merging
|
|
660
|
+
5. **Backward Compatibility**: Existing CLI and Node.js API unchanged
|
|
661
|
+
|
|
662
|
+
### Success Criteria for Phase 2
|
|
663
|
+
|
|
664
|
+
1. ✅ `YamlMerger.mergeContent()` works with raw YAML strings
|
|
665
|
+
2. ✅ Vite helper functions simplify `import.meta.glob()` usage
|
|
666
|
+
3. ✅ Browser build works without Node.js dependencies
|
|
667
|
+
4. ✅ Mixed file + content merging works in Node.js
|
|
668
|
+
5. ✅ Existing CLI and Node.js functionality preserved
|
|
669
|
+
6. ✅ forge framework can use Stitch instead of custom merge logic
|
|
670
|
+
7. ✅ Documentation covers both server and client usage patterns
|
|
671
|
+
|
|
672
|
+
## Phase 2: Complete ✅
|
|
673
|
+
|
|
674
|
+
**Goal**: Enable Stitch to work in browser environments with Vite's `?raw` import system.
|
|
675
|
+
|
|
676
|
+
### Implemented Features
|
|
677
|
+
|
|
678
|
+
#### Content-Based Merging API
|
|
679
|
+
- `YamlMerger.mergeContent()` - Merge raw YAML content strings
|
|
680
|
+
- `YamlMerger.merge()` - Mixed file paths and content merging
|
|
681
|
+
- `StitchEngine.buildFromContent()` - Build from content without filesystem
|
|
682
|
+
|
|
683
|
+
#### Vite Integration Helpers
|
|
684
|
+
- `stitchFromViteImports()` - Work with `import.meta.glob()`
|
|
685
|
+
- `stitchFromOrderedViteImports()` - Specific merge order
|
|
686
|
+
- `stitchFromSortedViteImports()` - Alphabetical ordering
|
|
687
|
+
- `stitchFromContent()` - Direct content merging
|
|
688
|
+
- `stitchFromRawContent()` - Simple string array merging
|
|
689
|
+
|
|
690
|
+
#### Browser/Server Separation
|
|
691
|
+
- Browser entry point: `src/browser/index.ts` (no Node.js deps)
|
|
692
|
+
- Server entry point: `src/index.ts` (full functionality)
|
|
693
|
+
- Separate builds via Vite configuration
|
|
694
|
+
- Package.json exports for environment-specific imports
|
|
695
|
+
|
|
696
|
+
#### Usage Examples
|
|
697
|
+
|
|
698
|
+
**Client-side with Vite:**
|
|
699
|
+
```typescript
|
|
700
|
+
import { stitchFromViteImports } from 'stitch/browser';
|
|
701
|
+
|
|
702
|
+
const imports = import.meta.glob('./openapi/*.yaml', { as: 'raw' });
|
|
703
|
+
const merged = await stitchFromViteImports(imports);
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
**Direct content merging:**
|
|
707
|
+
```typescript
|
|
708
|
+
import { stitchFromContent } from 'stitch/browser';
|
|
709
|
+
|
|
710
|
+
const contents = [
|
|
711
|
+
{ content: baseYaml, name: 'base.yaml' },
|
|
712
|
+
{ content: pathsYaml, name: 'paths.yaml' }
|
|
713
|
+
];
|
|
714
|
+
const result = stitchFromContent(contents);
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
**Mixed file + content (Node.js):**
|
|
718
|
+
```typescript
|
|
719
|
+
import { YamlMerger } from 'stitch';
|
|
720
|
+
|
|
721
|
+
const merger = new YamlMerger();
|
|
722
|
+
const result = merger.merge([
|
|
723
|
+
'base.yaml', // File path
|
|
724
|
+
{ content: importedYaml, name: 'imported.yaml' } // Raw content
|
|
725
|
+
]);
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
#### Implementation Order
|
|
729
|
+
|
|
730
|
+
1. **Dependencies** - Add js-yaml, chokidar, ajv, glob packages
|
|
731
|
+
2. **Types** - Define TypeScript interfaces (simplified)
|
|
732
|
+
3. **ConfigParser** - Parse simple stitch.yaml format
|
|
733
|
+
4. **YamlMerger** - Deep merge implementation
|
|
734
|
+
5. **Validator** - OpenAPI validation (optional)
|
|
735
|
+
6. **StitchEngine** - Simple orchestration: parse config → load files → merge → output
|
|
736
|
+
7. **CLI** - Wire up build/watch commands to engine
|
|
737
|
+
8. **API** - Export programmatic interface
|
|
738
|
+
9. **Tests** - Validate with simple merge examples
|
|
739
|
+
|
|
740
|
+
**Core logic is much simpler now:**
|
|
741
|
+
- Parse `stitch.yaml` → get array of files/globs
|
|
742
|
+
- Expand globs to actual file paths (sorted alphabetically)
|
|
743
|
+
- Load each YAML file in order
|
|
744
|
+
- Deep merge them sequentially
|
|
745
|
+
- Output result as YAML or JSON
|
|
746
|
+
|
|
747
|
+
**Glob Examples:**
|
|
748
|
+
- `*.yaml` - All YAML files in current directory
|
|
749
|
+
- `**/*.yaml` - All YAML files recursively
|
|
750
|
+
- `paths/*.yaml` - All YAML files in paths directory
|
|
751
|
+
- `components/**/*.yaml` - All YAML files in components and subdirectories
|
|
752
|
+
|
|
753
|
+
### Migration Plan
|
|
754
|
+
|
|
755
|
+
#### Step 1: Extract Backend API
|
|
756
|
+
1. Create backend stitch configuration
|
|
757
|
+
2. Split `backend/openapi.yaml` into modules:
|
|
758
|
+
- Extract user endpoints to `paths/users.yaml`
|
|
759
|
+
- Extract business endpoints to `paths/businesses.yaml`
|
|
760
|
+
- Extract schemas to component files
|
|
761
|
+
3. Update build process to generate `openapi.yaml`
|
|
762
|
+
4. Verify dinner framework still works correctly
|
|
763
|
+
|
|
764
|
+
#### Step 2: Extract Frontend Routes
|
|
765
|
+
1. Create frontend stitch configuration
|
|
766
|
+
2. Split `frontend/openapi.yaml` into route modules
|
|
767
|
+
3. Update build process to generate `openapi.yaml`
|
|
768
|
+
4. Verify forge framework still works correctly
|
|
769
|
+
|
|
770
|
+
#### Step 3: Team Workflow
|
|
771
|
+
1. Establish conventions for module organization
|
|
772
|
+
2. Create documentation for adding new routes/endpoints
|
|
773
|
+
3. Setup CI validation to ensure merged output is valid
|
|
774
|
+
|
|
775
|
+
### Benefits
|
|
776
|
+
|
|
777
|
+
1. **Maintainability**: Smaller, focused files are easier to understand and modify
|
|
778
|
+
2. **Collaboration**: Reduces merge conflicts when multiple developers work on different features
|
|
779
|
+
3. **Organization**: Logical grouping of related functionality
|
|
780
|
+
4. **Reusability**: Common components can be shared across modules
|
|
781
|
+
5. **Validation**: Individual modules can be validated independently
|
|
782
|
+
6. **Scalability**: New features can be added as new modules without touching existing files
|
|
783
|
+
|
|
784
|
+
### Technical Requirements
|
|
785
|
+
|
|
786
|
+
1. **YAML Processing**: Robust YAML parsing and merging capabilities
|
|
787
|
+
2. **OpenAPI Validation**: Ensure merged output conforms to OpenAPI 3.0.3 spec
|
|
788
|
+
3. **File Watching**: Efficient file system monitoring for development
|
|
789
|
+
4. **Path Resolution**: Proper handling of relative paths and includes
|
|
790
|
+
5. **Error Handling**: Clear error messages for validation and merge conflicts
|
|
791
|
+
6. **Performance**: Fast builds for development workflow
|
|
792
|
+
|
|
793
|
+
### Success Criteria
|
|
794
|
+
|
|
795
|
+
1. Backend and frontend OpenAPI files successfully split into manageable modules
|
|
796
|
+
2. Generated combined files are identical to original monolithic files
|
|
797
|
+
3. Both dinner (backend) and forge (frontend) frameworks work without modification
|
|
798
|
+
4. Development workflow remains smooth with watch mode
|
|
799
|
+
5. Build times are acceptable (< 1 second for typical changes)
|
|
800
|
+
6. Clear error messages help developers fix issues quickly
|
|
801
|
+
|
|
802
|
+
## Phase 3: VSCode Schema Integration ✅
|
|
803
|
+
|
|
804
|
+
**Goal**: Enable automatic schema validation in VSCode for YAML files.
|
|
805
|
+
|
|
806
|
+
### Implemented Features
|
|
807
|
+
|
|
808
|
+
#### Install Command
|
|
809
|
+
- `stitch install <schema-file> --target <patterns>` - Install JSON schema for VSCode
|
|
810
|
+
- Automatically creates/updates `.vscode/settings.json`
|
|
811
|
+
- Supports comma-separated file patterns and globs
|
|
812
|
+
- Preserves existing VSCode settings
|
|
813
|
+
|
|
814
|
+
#### CLI Usage
|
|
815
|
+
```bash
|
|
816
|
+
# Install schema for all YAML files
|
|
817
|
+
stitch install schemas/schema.json --target "*.yaml"
|
|
818
|
+
|
|
819
|
+
# Install schema for specific patterns
|
|
820
|
+
stitch install openapi-schema.json --target "stitch.yaml,openapi/*.yaml"
|
|
821
|
+
|
|
822
|
+
# Custom VSCode settings path
|
|
823
|
+
stitch install schemas/schema.json --target "*.yaml" --vscode custom/.vscode/settings.json
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
#### Generated VSCode Configuration
|
|
827
|
+
```json
|
|
828
|
+
{
|
|
829
|
+
"yaml.schemas": {
|
|
830
|
+
"test/fixtures/simple/schema.json": [
|
|
831
|
+
"*.yaml",
|
|
832
|
+
"openapi/*.yaml"
|
|
833
|
+
]
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
#### Programmatic API
|
|
839
|
+
```typescript
|
|
840
|
+
import { StitchEngine } from 'stitch';
|
|
841
|
+
|
|
842
|
+
const engine = new StitchEngine();
|
|
843
|
+
const result = engine.install({
|
|
844
|
+
schemaPath: 'schemas/schema.json',
|
|
845
|
+
targets: ['*.yaml', 'openapi/*.yaml'],
|
|
846
|
+
vscodeSettingsPath: '.vscode/settings.json' // optional
|
|
847
|
+
});
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
#### Benefits
|
|
851
|
+
- **IDE Integration**: Real-time YAML validation in VSCode
|
|
852
|
+
- **Development Experience**: Catch schema errors as you type
|
|
853
|
+
- **Team Consistency**: Share schema validation across team members
|
|
854
|
+
- **Automated Setup**: No manual VSCode configuration required
|
|
855
|
+
|
|
856
|
+
This modularization will significantly improve the maintainability and scalability of the Groom application's API and route definitions while preserving the existing framework integrations. Stitch is now a complete YAML modularization tool that works seamlessly across CLI, Node.js server environments, browser/Vite environments, and provides IDE integration for enhanced development experience.
|