@atmyapp/cli 0.0.1
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 +633 -0
- package/dist/cli/commands/migrate.d.ts +5 -0
- package/dist/cli/commands/migrate.js +76 -0
- package/dist/cli/commands/use.d.ts +2 -0
- package/dist/cli/commands/use.js +109 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +16 -0
- package/dist/cli/logger/index.d.ts +12 -0
- package/dist/cli/logger/index.js +34 -0
- package/dist/cli/test-migrate.d.ts +2 -0
- package/dist/cli/test-migrate.js +10 -0
- package/dist/cli/types/migrate.d.ts +34 -0
- package/dist/cli/types/migrate.js +2 -0
- package/dist/cli/utils/config.d.ts +10 -0
- package/dist/cli/utils/config.js +38 -0
- package/dist/cli/utils/content-processor.d.ts +6 -0
- package/dist/cli/utils/content-processor.js +141 -0
- package/dist/cli/utils/definition-processor.d.ts +61 -0
- package/dist/cli/utils/definition-processor.js +248 -0
- package/dist/cli/utils/file-operations.d.ts +4 -0
- package/dist/cli/utils/file-operations.js +24 -0
- package/dist/cli/utils/index.d.ts +9 -0
- package/dist/cli/utils/index.js +27 -0
- package/dist/cli/utils/schema-processor.d.ts +7 -0
- package/dist/cli/utils/schema-processor.js +247 -0
- package/dist/cli/utils/type-transformers.d.ts +8 -0
- package/dist/cli/utils/type-transformers.js +94 -0
- package/dist/cli/utils/upload.d.ts +3 -0
- package/dist/cli/utils/upload.js +62 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
# ๐ AtMyApp CLI
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/%40atmyapp%2Fcli)
|
|
4
|
+
[](https://opensource.org/licenses/ISC)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
> ๐ง **Migrate your TypeScript definitions seamlessly.** The official CLI tool for AtMyApp - AI-powered content management that migrates your type definitions to the AtMyApp platform with zero configuration.
|
|
8
|
+
|
|
9
|
+
## ๐ Table of Contents
|
|
10
|
+
|
|
11
|
+
- [๐ Features](#-features)
|
|
12
|
+
- [๐ฆ Installation](#-installation)
|
|
13
|
+
- [๐ Quick Start](#-quick-start)
|
|
14
|
+
- [๐ Commands](#-commands)
|
|
15
|
+
- [use Command](#use-command)
|
|
16
|
+
- [migrate Command](#migrate-command)
|
|
17
|
+
- [๐ฏ Type Definitions](#-type-definitions)
|
|
18
|
+
- [Content Definitions](#content-definitions)
|
|
19
|
+
- [Event Definitions](#event-definitions)
|
|
20
|
+
- [Image & File Definitions](#image--file-definitions)
|
|
21
|
+
- [๐ก Examples](#-examples)
|
|
22
|
+
- [๐ง Configuration](#-configuration)
|
|
23
|
+
- [๐๏ธ Architecture](#-architecture)
|
|
24
|
+
- [๐งช Testing](#-testing)
|
|
25
|
+
- [๐ค Contributing](#-contributing)
|
|
26
|
+
- [๐ License](#-license)
|
|
27
|
+
|
|
28
|
+
## ๐ Features
|
|
29
|
+
|
|
30
|
+
โจ **Automated Type Migration** - Extracts TypeScript definitions and migrates them automatically
|
|
31
|
+
๐ **Event Analytics Support** - Built-in support for event tracking definitions
|
|
32
|
+
๐ผ๏ธ **Media Type Support** - Handles image and file definitions with optimization configs
|
|
33
|
+
๐ **Real-time Processing** - Process multiple definition files simultaneously
|
|
34
|
+
๐ฏ **Type-Safe** - Full TypeScript support with comprehensive validation
|
|
35
|
+
โก **Zero Configuration** - Works out of the box with smart defaults
|
|
36
|
+
๐ **Secure** - API key authentication with session management
|
|
37
|
+
๐ **Pipeline Architecture** - Extensible processing pipeline for custom transformations
|
|
38
|
+
|
|
39
|
+
## ๐ฆ Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# npm
|
|
43
|
+
npm install -g @atmyapp/cli
|
|
44
|
+
|
|
45
|
+
# yarn
|
|
46
|
+
yarn global add @atmyapp/cli
|
|
47
|
+
|
|
48
|
+
# pnpm
|
|
49
|
+
pnpm add -g @atmyapp/cli
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## ๐ Quick Start
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# 1. Authenticate with your AtMyApp project
|
|
56
|
+
ama use --token your-api-token --url https://your-project.atmyapp.com
|
|
57
|
+
|
|
58
|
+
# 2. Migrate your definitions
|
|
59
|
+
ama migrate
|
|
60
|
+
|
|
61
|
+
# 3. Or run in dry-run mode to preview changes
|
|
62
|
+
ama migrate --dry-run --verbose
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## ๐ Commands
|
|
66
|
+
|
|
67
|
+
### use Command
|
|
68
|
+
|
|
69
|
+
Authenticate and configure your AtMyApp project connection.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
ama use [options]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Options:**
|
|
76
|
+
|
|
77
|
+
- `-t, --token <token>` - Authentication token
|
|
78
|
+
- `-u, --url <url>` - Project base URL
|
|
79
|
+
|
|
80
|
+
**Interactive Mode:**
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
ama use
|
|
84
|
+
# Will prompt for token and URL if not provided
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Example:**
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
ama use --token "ama_pk_..." --url "https://edge.atmyapp.com/projects/your-project-id"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### migrate Command
|
|
94
|
+
|
|
95
|
+
Migrate TypeScript definitions to the AtMyApp platform.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
ama migrate [options]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Options:**
|
|
102
|
+
|
|
103
|
+
- `--dry-run` - Generate definitions without uploading (default: false)
|
|
104
|
+
- `--verbose` - Enable verbose logging (default: false)
|
|
105
|
+
- `--tsconfig <path>` - Path to tsconfig.json (default: "tsconfig.json")
|
|
106
|
+
- `--continue-on-error` - Continue processing even if some files fail (default: false)
|
|
107
|
+
|
|
108
|
+
**Examples:**
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Basic migration
|
|
112
|
+
ama migrate
|
|
113
|
+
|
|
114
|
+
# Dry run with verbose output
|
|
115
|
+
ama migrate --dry-run --verbose
|
|
116
|
+
|
|
117
|
+
# Use custom tsconfig and continue on errors
|
|
118
|
+
ama migrate --tsconfig ./custom-tsconfig.json --continue-on-error
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## ๐ฏ Type Definitions
|
|
122
|
+
|
|
123
|
+
### Content Definitions
|
|
124
|
+
|
|
125
|
+
Define structured content using `AmaContentDef`:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { AmaContentDef } from "@atmyapp/core";
|
|
129
|
+
|
|
130
|
+
// Define your content structure
|
|
131
|
+
interface BlogPost {
|
|
132
|
+
title: string;
|
|
133
|
+
content: string;
|
|
134
|
+
publishedAt: string;
|
|
135
|
+
author: {
|
|
136
|
+
name: string;
|
|
137
|
+
avatar: string;
|
|
138
|
+
};
|
|
139
|
+
tags: string[];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Create a typed content definition
|
|
143
|
+
export type BlogPostContent = AmaContentDef<"/blog/featured", BlogPost>;
|
|
144
|
+
|
|
145
|
+
// Export for migration
|
|
146
|
+
export type ATMYAPP = [BlogPostContent];
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Event Definitions
|
|
150
|
+
|
|
151
|
+
Define analytics events using `AmaEventDef` with ordered columns:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { AmaEventDef } from "@atmyapp/core";
|
|
155
|
+
|
|
156
|
+
// Define event types for analytics tracking
|
|
157
|
+
export type PageViewEvent = AmaEventDef<
|
|
158
|
+
"page_view",
|
|
159
|
+
["page", "referrer", "timestamp", "user_id"]
|
|
160
|
+
>;
|
|
161
|
+
|
|
162
|
+
export type PurchaseEvent = AmaEventDef<
|
|
163
|
+
"purchase",
|
|
164
|
+
["product_id", "amount", "currency", "user_id", "timestamp"]
|
|
165
|
+
>;
|
|
166
|
+
|
|
167
|
+
export type ClickEvent = AmaEventDef<
|
|
168
|
+
"button_click",
|
|
169
|
+
["element", "position", "timestamp"]
|
|
170
|
+
>;
|
|
171
|
+
|
|
172
|
+
// Export all events
|
|
173
|
+
export type ATMYAPP = [PageViewEvent, PurchaseEvent, ClickEvent];
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Generated Output:**
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"events": {
|
|
181
|
+
"page_view": {
|
|
182
|
+
"columns": ["page", "referrer", "timestamp", "user_id"]
|
|
183
|
+
},
|
|
184
|
+
"purchase": {
|
|
185
|
+
"columns": ["product_id", "amount", "currency", "user_id", "timestamp"]
|
|
186
|
+
},
|
|
187
|
+
"button_click": {
|
|
188
|
+
"columns": ["element", "position", "timestamp"]
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Image & File Definitions
|
|
195
|
+
|
|
196
|
+
Define optimized media with `AmaImageDef` and `AmaFileDef`:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
import { AmaImageDef, AmaFileDef, AmaImageConfig } from "@atmyapp/core";
|
|
200
|
+
|
|
201
|
+
// Image with optimization config
|
|
202
|
+
interface HeroImageConfig extends AmaImageConfig {
|
|
203
|
+
optimizeFormat: "webp";
|
|
204
|
+
maxSize: { width: 1920; height: 1080 };
|
|
205
|
+
quality: 85;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export type HeroImage = AmaImageDef<"/images/hero", HeroImageConfig>;
|
|
209
|
+
|
|
210
|
+
// File definition
|
|
211
|
+
export type UserManual = AmaFileDef<"/docs/manual.pdf">;
|
|
212
|
+
|
|
213
|
+
export type ATMYAPP = [HeroImage, UserManual];
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## ๐ก Examples
|
|
217
|
+
|
|
218
|
+
### ๐ช E-commerce Setup
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
// types/ecommerce.ts
|
|
222
|
+
import { AmaContentDef, AmaEventDef, AmaImageDef } from "@atmyapp/core";
|
|
223
|
+
|
|
224
|
+
// Product catalog
|
|
225
|
+
interface Product {
|
|
226
|
+
id: string;
|
|
227
|
+
name: string;
|
|
228
|
+
price: number;
|
|
229
|
+
description: string;
|
|
230
|
+
inStock: boolean;
|
|
231
|
+
category: string;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export type ProductCatalog = AmaContentDef<"/products/catalog", Product[]>;
|
|
235
|
+
export type FeaturedProduct = AmaContentDef<"/products/featured", Product>;
|
|
236
|
+
|
|
237
|
+
// Product images
|
|
238
|
+
export type ProductImage = AmaImageDef<
|
|
239
|
+
"/images/products",
|
|
240
|
+
{
|
|
241
|
+
optimizeFormat: "webp";
|
|
242
|
+
maxSize: { width: 800; height: 800 };
|
|
243
|
+
}
|
|
244
|
+
>;
|
|
245
|
+
|
|
246
|
+
// E-commerce events
|
|
247
|
+
export type ProductViewEvent = AmaEventDef<
|
|
248
|
+
"product_view",
|
|
249
|
+
["product_id", "category", "price", "user_id", "timestamp"]
|
|
250
|
+
>;
|
|
251
|
+
|
|
252
|
+
export type AddToCartEvent = AmaEventDef<
|
|
253
|
+
"add_to_cart",
|
|
254
|
+
["product_id", "quantity", "price", "user_id", "timestamp"]
|
|
255
|
+
>;
|
|
256
|
+
|
|
257
|
+
export type PurchaseEvent = AmaEventDef<
|
|
258
|
+
"purchase",
|
|
259
|
+
["order_id", "total_amount", "currency", "user_id", "timestamp"]
|
|
260
|
+
>;
|
|
261
|
+
|
|
262
|
+
// Export all definitions
|
|
263
|
+
export type ATMYAPP = [
|
|
264
|
+
ProductCatalog,
|
|
265
|
+
FeaturedProduct,
|
|
266
|
+
ProductImage,
|
|
267
|
+
ProductViewEvent,
|
|
268
|
+
AddToCartEvent,
|
|
269
|
+
PurchaseEvent,
|
|
270
|
+
];
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### ๐ฐ Blog & Content Management
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
// types/blog.ts
|
|
277
|
+
import { AmaContentDef, AmaEventDef, AmaImageDef } from "@atmyapp/core";
|
|
278
|
+
|
|
279
|
+
// Blog content types
|
|
280
|
+
interface BlogPost {
|
|
281
|
+
title: string;
|
|
282
|
+
slug: string;
|
|
283
|
+
content: string;
|
|
284
|
+
excerpt: string;
|
|
285
|
+
publishedAt: string;
|
|
286
|
+
author: {
|
|
287
|
+
name: string;
|
|
288
|
+
email: string;
|
|
289
|
+
avatar: string;
|
|
290
|
+
};
|
|
291
|
+
tags: string[];
|
|
292
|
+
featured: boolean;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
interface Category {
|
|
296
|
+
name: string;
|
|
297
|
+
slug: string;
|
|
298
|
+
description: string;
|
|
299
|
+
color: string;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Content definitions
|
|
303
|
+
export type BlogPosts = AmaContentDef<"/blog/posts", BlogPost[]>;
|
|
304
|
+
export type FeaturedPost = AmaContentDef<"/blog/featured", BlogPost>;
|
|
305
|
+
export type Categories = AmaContentDef<"/blog/categories", Category[]>;
|
|
306
|
+
|
|
307
|
+
// Featured images
|
|
308
|
+
export type BlogHeroImage = AmaImageDef<
|
|
309
|
+
"/images/blog/hero",
|
|
310
|
+
{
|
|
311
|
+
optimizeFormat: "webp";
|
|
312
|
+
maxSize: { width: 1200; height: 630 };
|
|
313
|
+
}
|
|
314
|
+
>;
|
|
315
|
+
|
|
316
|
+
// Blog analytics events
|
|
317
|
+
export type ArticleReadEvent = AmaEventDef<
|
|
318
|
+
"article_read",
|
|
319
|
+
["article_id", "reading_time", "completion_rate", "referrer", "timestamp"]
|
|
320
|
+
>;
|
|
321
|
+
|
|
322
|
+
export type CommentEvent = AmaEventDef<
|
|
323
|
+
"comment_posted",
|
|
324
|
+
["article_id", "comment_id", "user_id", "timestamp"]
|
|
325
|
+
>;
|
|
326
|
+
|
|
327
|
+
export type ShareEvent = AmaEventDef<
|
|
328
|
+
"article_shared",
|
|
329
|
+
["article_id", "platform", "user_id", "timestamp"]
|
|
330
|
+
>;
|
|
331
|
+
|
|
332
|
+
export type ATMYAPP = [
|
|
333
|
+
BlogPosts,
|
|
334
|
+
FeaturedPost,
|
|
335
|
+
Categories,
|
|
336
|
+
BlogHeroImage,
|
|
337
|
+
ArticleReadEvent,
|
|
338
|
+
CommentEvent,
|
|
339
|
+
ShareEvent,
|
|
340
|
+
];
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### ๐ฎ User Analytics Dashboard
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
// types/analytics.ts
|
|
347
|
+
import { AmaEventDef } from "@atmyapp/core";
|
|
348
|
+
|
|
349
|
+
// User interaction events
|
|
350
|
+
export type PageViewEvent = AmaEventDef<
|
|
351
|
+
"page_view",
|
|
352
|
+
["page", "referrer", "user_agent", "session_id", "timestamp"]
|
|
353
|
+
>;
|
|
354
|
+
|
|
355
|
+
export type ClickEvent = AmaEventDef<
|
|
356
|
+
"click",
|
|
357
|
+
["element", "element_text", "page", "position_x", "position_y", "timestamp"]
|
|
358
|
+
>;
|
|
359
|
+
|
|
360
|
+
export type FormSubmissionEvent = AmaEventDef<
|
|
361
|
+
"form_submit",
|
|
362
|
+
["form_id", "form_name", "success", "validation_errors", "timestamp"]
|
|
363
|
+
>;
|
|
364
|
+
|
|
365
|
+
export type ScrollEvent = AmaEventDef<
|
|
366
|
+
"scroll",
|
|
367
|
+
["page", "scroll_depth", "session_id", "timestamp"]
|
|
368
|
+
>;
|
|
369
|
+
|
|
370
|
+
export type ErrorEvent = AmaEventDef<
|
|
371
|
+
"error",
|
|
372
|
+
["error_message", "error_stack", "page", "user_agent", "timestamp"]
|
|
373
|
+
>;
|
|
374
|
+
|
|
375
|
+
// Performance events
|
|
376
|
+
export type PerformanceEvent = AmaEventDef<
|
|
377
|
+
"performance",
|
|
378
|
+
["page", "load_time", "dom_ready", "first_paint", "timestamp"]
|
|
379
|
+
>;
|
|
380
|
+
|
|
381
|
+
export type ATMYAPP = [
|
|
382
|
+
PageViewEvent,
|
|
383
|
+
ClickEvent,
|
|
384
|
+
FormSubmissionEvent,
|
|
385
|
+
ScrollEvent,
|
|
386
|
+
ErrorEvent,
|
|
387
|
+
PerformanceEvent,
|
|
388
|
+
];
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## ๐ง Configuration
|
|
392
|
+
|
|
393
|
+
### Project Structure
|
|
394
|
+
|
|
395
|
+
```
|
|
396
|
+
your-project/
|
|
397
|
+
โโโ .ama/
|
|
398
|
+
โ โโโ session.json # Auth credentials (auto-generated)
|
|
399
|
+
โ โโโ definitions.json # Generated definitions (auto-generated)
|
|
400
|
+
โโโ types/
|
|
401
|
+
โ โโโ content.ts # Content definitions
|
|
402
|
+
โ โโโ events.ts # Event definitions
|
|
403
|
+
โ โโโ media.ts # Image/file definitions
|
|
404
|
+
โโโ .gitignore # Updated automatically
|
|
405
|
+
โโโ tsconfig.json # TypeScript config
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Environment Setup
|
|
409
|
+
|
|
410
|
+
The CLI automatically manages configuration through the `.ama` directory:
|
|
411
|
+
|
|
412
|
+
- **`session.json`** - Stores authentication token and project URL
|
|
413
|
+
- **`definitions.json`** - Generated output (for preview and debugging)
|
|
414
|
+
- **`.gitignore`** - Automatically updated to exclude sensitive files
|
|
415
|
+
|
|
416
|
+
### Custom Configuration
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
// ama.config.ts (optional)
|
|
420
|
+
export default {
|
|
421
|
+
include: ["src/**/*.ts", "types/**/*.ts"],
|
|
422
|
+
exclude: ["**/*.test.ts"],
|
|
423
|
+
description: "My Project Definitions",
|
|
424
|
+
metadata: {
|
|
425
|
+
version: "1.0.0",
|
|
426
|
+
author: "Your Name",
|
|
427
|
+
environment: process.env.NODE_ENV,
|
|
428
|
+
},
|
|
429
|
+
};
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
## ๐๏ธ Architecture
|
|
433
|
+
|
|
434
|
+
### Processing Pipeline
|
|
435
|
+
|
|
436
|
+
The CLI uses a modular pipeline architecture:
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
// 1. File Scanning
|
|
440
|
+
scanFiles(patterns)
|
|
441
|
+
โ
|
|
442
|
+
// 2. TypeScript Processing
|
|
443
|
+
createProject(files)
|
|
444
|
+
โ
|
|
445
|
+
// 3. Definition Extraction
|
|
446
|
+
processFiles(sourceFiles)
|
|
447
|
+
โ
|
|
448
|
+
// 4. Content Processing Pipeline
|
|
449
|
+
definitionPipeline.processDefinitions()
|
|
450
|
+
โ
|
|
451
|
+
// 5. Output Generation
|
|
452
|
+
generateOutput(contents)
|
|
453
|
+
โ
|
|
454
|
+
// 6. Upload (unless --dry-run)
|
|
455
|
+
uploadDefinitions(output)
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### Built-in Processors
|
|
459
|
+
|
|
460
|
+
- **pathNormalizer** - Normalizes file paths across platforms
|
|
461
|
+
- **typeDetector** - Detects content, event, image, and file types
|
|
462
|
+
- **duplicateValidator** - Prevents duplicate path definitions
|
|
463
|
+
- **metadataEnricher** - Adds processing metadata to output
|
|
464
|
+
|
|
465
|
+
### Extensibility
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
import {
|
|
469
|
+
definitionPipeline,
|
|
470
|
+
DefinitionProcessor,
|
|
471
|
+
ValidationRule,
|
|
472
|
+
OutputTransformer,
|
|
473
|
+
} from "@atmyapp/cli";
|
|
474
|
+
|
|
475
|
+
// Custom processor
|
|
476
|
+
const customProcessor: DefinitionProcessor = {
|
|
477
|
+
name: "custom-processor",
|
|
478
|
+
process: (content, context) => {
|
|
479
|
+
// Your custom logic
|
|
480
|
+
return modifiedContent;
|
|
481
|
+
},
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
// Register custom components
|
|
485
|
+
definitionPipeline.addProcessor(customProcessor);
|
|
486
|
+
definitionPipeline.addValidator(customValidator);
|
|
487
|
+
definitionPipeline.addOutputTransformer(customTransformer);
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
## ๐งช Testing
|
|
491
|
+
|
|
492
|
+
### Running Tests
|
|
493
|
+
|
|
494
|
+
```bash
|
|
495
|
+
# Run all tests
|
|
496
|
+
npm test
|
|
497
|
+
|
|
498
|
+
# Run with coverage
|
|
499
|
+
npm run test:coverage
|
|
500
|
+
|
|
501
|
+
# Run specific test suite
|
|
502
|
+
npm test -- --testNamePattern="Content Processor"
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Test Structure
|
|
506
|
+
|
|
507
|
+
```
|
|
508
|
+
tests/
|
|
509
|
+
โโโ __tests__/
|
|
510
|
+
โ โโโ content-processor.test.ts # Content processing tests
|
|
511
|
+
โ โโโ definition-processor.test.ts # Pipeline tests
|
|
512
|
+
โ โโโ schema-processor.test.ts # TypeScript processing tests
|
|
513
|
+
โ โโโ integration.test.ts # End-to-end tests
|
|
514
|
+
โโโ definitions/
|
|
515
|
+
โ โโโ someFile.ts # Basic test definitions
|
|
516
|
+
โ โโโ multipleDefinitions.ts # Multi-definition tests
|
|
517
|
+
โ โโโ eventDefinitions.ts # Event definition tests
|
|
518
|
+
โโโ setup.ts # Test configuration
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Example Test
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
describe("Event Processing", () => {
|
|
525
|
+
it("should separate events from regular definitions", () => {
|
|
526
|
+
const contents: Content[] = [
|
|
527
|
+
{
|
|
528
|
+
path: "hero.json",
|
|
529
|
+
structure: { title: "Hero" },
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
path: "page_view_event",
|
|
533
|
+
structure: {
|
|
534
|
+
type: "event",
|
|
535
|
+
properties: {
|
|
536
|
+
id: { const: "page_view" },
|
|
537
|
+
columns: { const: ["page", "user_id", "timestamp"] },
|
|
538
|
+
type: { const: "event" },
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
];
|
|
543
|
+
|
|
544
|
+
const output = generateOutput(contents, {}, mockLogger);
|
|
545
|
+
|
|
546
|
+
expect(output.definitions["hero.json"]).toBeDefined();
|
|
547
|
+
expect(output.events["page_view"]).toBeDefined();
|
|
548
|
+
expect(output.events["page_view"]).toHaveProperty("columns", [
|
|
549
|
+
"page",
|
|
550
|
+
"user_id",
|
|
551
|
+
"timestamp",
|
|
552
|
+
]);
|
|
553
|
+
});
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## ๐จ Best Practices
|
|
558
|
+
|
|
559
|
+
### Definition Organization
|
|
560
|
+
|
|
561
|
+
โ
**Do:**
|
|
562
|
+
|
|
563
|
+
- Group related definitions in separate files
|
|
564
|
+
- Use descriptive type names
|
|
565
|
+
- Keep event column order consistent
|
|
566
|
+
- Include comprehensive type documentation
|
|
567
|
+
|
|
568
|
+
โ **Don't:**
|
|
569
|
+
|
|
570
|
+
- Mix content and event definitions unnecessarily
|
|
571
|
+
- Use dynamic or computed type names
|
|
572
|
+
- Ignore TypeScript compiler errors
|
|
573
|
+
|
|
574
|
+
### Performance Tips
|
|
575
|
+
|
|
576
|
+
- โ
Use specific include patterns to reduce scanning
|
|
577
|
+
- โ
Enable `--continue-on-error` for large codebases
|
|
578
|
+
- โ
Run `--dry-run` first to preview changes
|
|
579
|
+
- โ
Use `--verbose` for debugging issues
|
|
580
|
+
|
|
581
|
+
### Security
|
|
582
|
+
|
|
583
|
+
- โ
Keep `.ama/session.json` private
|
|
584
|
+
- โ
Use environment variables for CI/CD
|
|
585
|
+
- โ
Regularly rotate API tokens
|
|
586
|
+
- โ
Review generated definitions before upload
|
|
587
|
+
|
|
588
|
+
## ๐ค Contributing
|
|
589
|
+
|
|
590
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
591
|
+
|
|
592
|
+
1. Fork the repository
|
|
593
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
594
|
+
3. Write tests for your changes
|
|
595
|
+
4. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
596
|
+
5. Push to the branch (`git push origin feature/amazing-feature`)
|
|
597
|
+
6. Open a Pull Request
|
|
598
|
+
|
|
599
|
+
### Development Setup
|
|
600
|
+
|
|
601
|
+
```bash
|
|
602
|
+
# Clone the repository
|
|
603
|
+
git clone https://github.com/atmyapp/cli.git
|
|
604
|
+
cd cli
|
|
605
|
+
|
|
606
|
+
# Install dependencies
|
|
607
|
+
npm install
|
|
608
|
+
|
|
609
|
+
# Build the project
|
|
610
|
+
npm run build
|
|
611
|
+
|
|
612
|
+
# Run tests
|
|
613
|
+
npm test
|
|
614
|
+
|
|
615
|
+
# Link for local development
|
|
616
|
+
npm link
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
## ๐ License
|
|
620
|
+
|
|
621
|
+
This project is licensed under the ISC License - see the [LICENSE](LICENSE) file for details.
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
<div align="center">
|
|
626
|
+
|
|
627
|
+
**[๐ AtMyApp Website](https://atmyapp.com)** โข **[๐ Documentation](https://docs.atmyapp.com)** โข **[๐ฌ Support](https://atmyapp.com/support)**
|
|
628
|
+
|
|
629
|
+
Made with โค๏ธ by the AtMyApp team
|
|
630
|
+
|
|
631
|
+
_Migrate your definitions with confidence._
|
|
632
|
+
|
|
633
|
+
</div>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { registerTypeTransformer, definitionPipeline, DefinitionProcessor, ValidationRule, OutputTransformer } from "../utils";
|
|
3
|
+
export { registerTypeTransformer };
|
|
4
|
+
export { definitionPipeline, DefinitionProcessor, ValidationRule, OutputTransformer, };
|
|
5
|
+
export declare function migrateCommand(): Command;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.definitionPipeline = exports.registerTypeTransformer = void 0;
|
|
13
|
+
exports.migrateCommand = migrateCommand;
|
|
14
|
+
const commander_1 = require("commander");
|
|
15
|
+
const utils_1 = require("../utils");
|
|
16
|
+
Object.defineProperty(exports, "registerTypeTransformer", { enumerable: true, get: function () { return utils_1.registerTypeTransformer; } });
|
|
17
|
+
Object.defineProperty(exports, "definitionPipeline", { enumerable: true, get: function () { return utils_1.definitionPipeline; } });
|
|
18
|
+
// Main migrate command function
|
|
19
|
+
function migrateCommand() {
|
|
20
|
+
return new commander_1.Command("migrate")
|
|
21
|
+
.description("Migrate definitions to AtMyApp platform")
|
|
22
|
+
.option("--dry-run", "Generate definitions without uploading to server", false)
|
|
23
|
+
.option("--verbose", "Enable verbose logging", false)
|
|
24
|
+
.option("--tsconfig <path>", "Path to tsconfig.json", "tsconfig.json")
|
|
25
|
+
.option("--continue-on-error", "Continue processing even if some files fail", false)
|
|
26
|
+
.action((options) => __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
const logger = new utils_1.Logger(options.verbose);
|
|
28
|
+
try {
|
|
29
|
+
logger.info("๐ Starting migration process");
|
|
30
|
+
logger.verbose_log(`Options: ${JSON.stringify(options)}`);
|
|
31
|
+
const config = (0, utils_1.getConfig)();
|
|
32
|
+
const patterns = config.include || ["**/*.ts", "**/*.tsx"];
|
|
33
|
+
// Create .ama directory if it doesn't exist
|
|
34
|
+
(0, utils_1.ensureAmaDirectory)(logger);
|
|
35
|
+
// Execute migration steps
|
|
36
|
+
const files = yield (0, utils_1.scanFiles)(patterns, logger);
|
|
37
|
+
logger.info(`๐ Found ${files.length} files to process`);
|
|
38
|
+
const project = (0, utils_1.createProject)(files, options.tsconfig, logger);
|
|
39
|
+
const { contents, errors, successCount, failureCount } = (0, utils_1.processFiles)(project.getSourceFiles(), options.tsconfig, options.continueOnError, logger);
|
|
40
|
+
// Report processing results
|
|
41
|
+
logger.success(`โ
Successfully processed ${successCount} AMA contents`);
|
|
42
|
+
if (failureCount > 0) {
|
|
43
|
+
logger.warn(`โ ๏ธ Failed to process ${failureCount} items`);
|
|
44
|
+
if (options.verbose && errors.length > 0) {
|
|
45
|
+
logger.info("Errors encountered:");
|
|
46
|
+
errors.forEach((err) => logger.error(` ${err}`));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (contents.length === 0) {
|
|
50
|
+
logger.error("No valid AMA contents found. Exiting.");
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
// Generate and save output
|
|
54
|
+
const output = (0, utils_1.generateOutput)(contents, config, logger);
|
|
55
|
+
(0, utils_1.saveOutputToFile)(output, logger);
|
|
56
|
+
// Upload definitions unless dry-run is enabled
|
|
57
|
+
if (!options.dryRun) {
|
|
58
|
+
logger.info("Uploading definitions to AtMyApp platform");
|
|
59
|
+
const uploadSuccess = yield (0, utils_1.uploadDefinitions)(output, config, logger);
|
|
60
|
+
if (!uploadSuccess) {
|
|
61
|
+
logger.warn("Upload failed, but definitions were generated successfully");
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
logger.info("Dry run mode enabled. Skipping upload to server.");
|
|
67
|
+
}
|
|
68
|
+
logger.success("Migration completed successfully");
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
72
|
+
logger.error(`Fatal error: ${message}`, error);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
}));
|
|
76
|
+
}
|