@atmyapp/cli 0.0.7 → 0.0.9

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.
@@ -0,0 +1,334 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.uploadCommand = uploadCommand;
16
+ const commander_1 = require("commander");
17
+ const fast_glob_1 = __importDefault(require("fast-glob"));
18
+ const path_1 = __importDefault(require("path"));
19
+ const fs_1 = require("fs");
20
+ const logger_1 = require("../logger");
21
+ const http_1 = require("../utils/http");
22
+ const DEFAULT_BRANCH = "main";
23
+ const DEFAULT_IGNORE_PATTERNS = ["**/.git/**", "**/.ama/**"];
24
+ function uploadCommand() {
25
+ return new commander_1.Command("upload")
26
+ .description("Upload files to project storage")
27
+ .argument("[inputs...]")
28
+ .option("-t, --token <token>", "Authentication token override")
29
+ .option("-u, --url <url>", "Project base URL override")
30
+ .option("-p, --project-id <id>", "Project identifier override")
31
+ .option("-b, --base-path <path>", "Base remote path (relative to project root)")
32
+ .option("--branch <name>", "Branch to write to", DEFAULT_BRANCH)
33
+ .option("--environment-name <name>", "Environment name for scoped writes")
34
+ .option("--commit <message>", "Commit message recorded with the upload")
35
+ .option("--delete <path>", "Remote file path to delete (repeatable)", collectValues, [])
36
+ .option("--no-stream", "Disable streaming progress output (enabled by default)")
37
+ .option("--verbose", "Enable verbose logging")
38
+ .action((inputPatterns, options) => __awaiter(this, void 0, void 0, function* () {
39
+ var _a, _b;
40
+ const logger = new logger_1.Logger(Boolean(options.verbose));
41
+ try {
42
+ const session = (0, http_1.resolveSession)({
43
+ token: options.token,
44
+ projectId: options.projectId,
45
+ url: options.url,
46
+ });
47
+ const basePath = normalizeBasePath(options.basePath);
48
+ const streamEnabled = options.stream !== false;
49
+ const files = yield prepareFiles(inputPatterns, basePath, logger);
50
+ const filesToDelete = normalizeDeletionPaths((_a = options.delete) !== null && _a !== void 0 ? _a : [], basePath, logger);
51
+ if (files.length === 0 && filesToDelete.length === 0) {
52
+ throw new Error("Nothing to upload. Provide file inputs or --delete paths to process.");
53
+ }
54
+ const body = {
55
+ files,
56
+ };
57
+ if (filesToDelete.length > 0) {
58
+ body.filesToDelete = filesToDelete;
59
+ }
60
+ if (options.commit) {
61
+ body.commitMessage = options.commit;
62
+ }
63
+ const query = {
64
+ branch: (_b = options.branch) !== null && _b !== void 0 ? _b : DEFAULT_BRANCH,
65
+ };
66
+ if (options.environmentName) {
67
+ query.environment_name = options.environmentName;
68
+ }
69
+ if (streamEnabled) {
70
+ query.stream = true;
71
+ yield performStreamingUpload(session, basePath, body, query, logger);
72
+ }
73
+ else {
74
+ yield performStandardUpload(session, basePath, body, query, logger);
75
+ }
76
+ logger.success("Upload completed successfully.");
77
+ }
78
+ catch (error) {
79
+ const message = error instanceof Error ? error.message : String(error);
80
+ logger.error(`Upload failed: ${message}`);
81
+ process.exit(1);
82
+ }
83
+ }));
84
+ }
85
+ function collectValues(value, previous) {
86
+ previous.push(value);
87
+ return previous;
88
+ }
89
+ function normalizeBasePath(basePath) {
90
+ if (!basePath) {
91
+ return undefined;
92
+ }
93
+ const trimmed = basePath.trim();
94
+ if (!trimmed) {
95
+ return undefined;
96
+ }
97
+ const normalized = toPosix(trimmed)
98
+ .replace(/^\.\/?/, "")
99
+ .replace(/\/+$/, "");
100
+ return normalized || undefined;
101
+ }
102
+ function toPosix(value) {
103
+ return value.replace(/\\/g, "/");
104
+ }
105
+ function prepareFiles(patterns, basePath, logger) {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ if (!patterns || patterns.length === 0) {
108
+ return [];
109
+ }
110
+ const resolvedPaths = new Set();
111
+ for (const pattern of patterns) {
112
+ const expanded = yield expandInput(pattern);
113
+ if (expanded.length === 0) {
114
+ logger.warn(`No files matched pattern '${pattern}'.`);
115
+ }
116
+ for (const filePath of expanded) {
117
+ resolvedPaths.add(path_1.default.resolve(filePath));
118
+ }
119
+ }
120
+ const sortedPaths = Array.from(resolvedPaths).sort();
121
+ const files = [];
122
+ for (const absolutePath of sortedPaths) {
123
+ const buffer = yield fs_1.promises.readFile(absolutePath);
124
+ const relativePath = path_1.default.relative(process.cwd(), absolutePath) ||
125
+ path_1.default.basename(absolutePath);
126
+ const posixPath = toPosix(relativePath);
127
+ const remotePath = computeRemotePath(posixPath, basePath, logger);
128
+ logger.verbose_log(`Preparing file '${absolutePath}' as remote path '${remotePath}'.`);
129
+ files.push({
130
+ path: remotePath,
131
+ content: buffer.toString("base64"),
132
+ });
133
+ }
134
+ return files;
135
+ });
136
+ }
137
+ function expandInput(input) {
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ const cwd = process.cwd();
140
+ const absoluteCandidate = path_1.default.resolve(cwd, input);
141
+ try {
142
+ const stats = yield fs_1.promises.stat(absoluteCandidate);
143
+ if (stats.isDirectory()) {
144
+ const entries = yield (0, fast_glob_1.default)("**/*", {
145
+ cwd: absoluteCandidate,
146
+ dot: true,
147
+ onlyFiles: true,
148
+ followSymbolicLinks: false,
149
+ ignore: DEFAULT_IGNORE_PATTERNS,
150
+ });
151
+ return entries.map((entry) => path_1.default.resolve(absoluteCandidate, entry));
152
+ }
153
+ if (stats.isFile()) {
154
+ return [absoluteCandidate];
155
+ }
156
+ }
157
+ catch (error) {
158
+ // Treat as glob when path resolution fails
159
+ }
160
+ const normalizedPattern = toPosix(input);
161
+ const matches = yield (0, fast_glob_1.default)(normalizedPattern, {
162
+ cwd,
163
+ dot: true,
164
+ onlyFiles: true,
165
+ followSymbolicLinks: false,
166
+ ignore: DEFAULT_IGNORE_PATTERNS,
167
+ unique: true,
168
+ });
169
+ return matches.map((match) => path_1.default.resolve(cwd, match));
170
+ });
171
+ }
172
+ function computeRemotePath(posixPath, basePath, logger) {
173
+ const cleaned = posixPath.replace(/^\.\//, "");
174
+ if (!basePath) {
175
+ return cleaned;
176
+ }
177
+ const relativeToBase = path_1.default.posix.relative(basePath, cleaned);
178
+ if (relativeToBase.startsWith("..")) {
179
+ logger.warn(`File '${cleaned}' is outside the base path '${basePath}'. Using absolute path.`);
180
+ return cleaned;
181
+ }
182
+ const normalized = relativeToBase.replace(/^\.\//, "");
183
+ const finalSegment = normalized || path_1.default.posix.basename(cleaned);
184
+ return `./${finalSegment}`;
185
+ }
186
+ function normalizeDeletionPaths(values, basePath, logger) {
187
+ if (!values || values.length === 0) {
188
+ return [];
189
+ }
190
+ const result = [];
191
+ for (const original of values) {
192
+ const trimmed = original.trim();
193
+ if (!trimmed) {
194
+ continue;
195
+ }
196
+ const posix = toPosix(trimmed);
197
+ if (posix.startsWith("./")) {
198
+ result.push(`./${posix.replace(/^\.\/+/, "")}`);
199
+ continue;
200
+ }
201
+ if (posix.startsWith("/")) {
202
+ result.push(posix.replace(/^\/+/, ""));
203
+ continue;
204
+ }
205
+ result.push(computeRemotePath(posix, basePath, logger));
206
+ }
207
+ return result;
208
+ }
209
+ function buildUploadEndpoint(session, basePath) {
210
+ const projectSegment = `v0/projects/${encodeURIComponent(session.projectId)}/storage/f`;
211
+ if (!basePath) {
212
+ return projectSegment;
213
+ }
214
+ const encodedBase = (0, http_1.encodePathSegment)(basePath);
215
+ return `${projectSegment}/${encodedBase}`;
216
+ }
217
+ function performStreamingUpload(session, basePath, body, query, logger) {
218
+ return __awaiter(this, void 0, void 0, function* () {
219
+ const endpoint = buildUploadEndpoint(session, basePath);
220
+ const url = (0, http_1.projectUrl)(session, endpoint, {
221
+ branch: query.branch,
222
+ environment_name: query.environment_name,
223
+ stream: true,
224
+ });
225
+ const summary = {
226
+ updated: new Set(),
227
+ deleted: new Set(),
228
+ errors: new Map(),
229
+ hadErrorEvent: false,
230
+ };
231
+ yield (0, http_1.streamSse)({
232
+ url,
233
+ fetchInit: {
234
+ method: "PUT",
235
+ headers: {
236
+ "Content-Type": "application/json",
237
+ Authorization: `Bearer ${session.token}`,
238
+ },
239
+ body: JSON.stringify(body),
240
+ },
241
+ onEvent: (event) => __awaiter(this, void 0, void 0, function* () {
242
+ if (event.data === "[DONE]") {
243
+ return;
244
+ }
245
+ const payload = event.parsed;
246
+ if (!payload) {
247
+ logger.verbose_log(`SSE: ${event.data}`);
248
+ return;
249
+ }
250
+ if (payload.message) {
251
+ logger.info(payload.message);
252
+ }
253
+ if (payload.updated) {
254
+ payload.updated.forEach((item) => summary.updated.add(item));
255
+ }
256
+ if (payload.deleted) {
257
+ payload.deleted.forEach((item) => summary.deleted.add(item));
258
+ }
259
+ if (payload.errors) {
260
+ Object.entries(payload.errors).forEach(([key, value]) => {
261
+ summary.errors.set(key, value);
262
+ logger.error(`Error processing '${key}': ${value}`);
263
+ });
264
+ }
265
+ if (payload.type === "error" || payload.success === false) {
266
+ summary.hadErrorEvent = true;
267
+ }
268
+ if (payload.type === "complete") {
269
+ logger.info("Upload stream completed.");
270
+ }
271
+ }),
272
+ });
273
+ if (summary.updated.size > 0) {
274
+ logger.success(`Updated ${summary.updated.size} file(s): ${Array.from(summary.updated).join(", ")}`);
275
+ }
276
+ if (summary.deleted.size > 0) {
277
+ logger.warn(`Deleted ${summary.deleted.size} file(s): ${Array.from(summary.deleted).join(", ")}`);
278
+ }
279
+ if (summary.errors.size > 0 || summary.hadErrorEvent) {
280
+ throw new Error("Upload completed with errors. Check the log for details.");
281
+ }
282
+ });
283
+ }
284
+ function performStandardUpload(session, basePath, body, query, logger) {
285
+ return __awaiter(this, void 0, void 0, function* () {
286
+ var _a;
287
+ const endpoint = buildUploadEndpoint(session, basePath);
288
+ const url = (0, http_1.projectUrl)(session, endpoint, {
289
+ branch: query.branch,
290
+ environment_name: query.environment_name,
291
+ });
292
+ const fetcher = (0, http_1.createAmaFetch)(session);
293
+ const { data, error } = yield fetcher(url, {
294
+ method: "PUT",
295
+ headers: {
296
+ "Content-Type": "application/json",
297
+ },
298
+ body: JSON.stringify(body),
299
+ });
300
+ if (error) {
301
+ const errorMessage = typeof error === "string"
302
+ ? error
303
+ : error instanceof Error
304
+ ? error.message
305
+ : (_a = error.message) !== null && _a !== void 0 ? _a : (error.status
306
+ ? `HTTP ${error.status}`
307
+ : "Unknown error");
308
+ throw new Error(`Request failed: ${errorMessage}`);
309
+ }
310
+ if (!data) {
311
+ throw new Error("No response data received from the server.");
312
+ }
313
+ if (!data.success) {
314
+ throw new Error(data.error || "Upload failed without a server error message.");
315
+ }
316
+ const payload = data.data;
317
+ if (!payload) {
318
+ logger.success("Server reported success with no additional details.");
319
+ return;
320
+ }
321
+ if (payload.updated && payload.updated.length > 0) {
322
+ logger.success(`Updated files: ${payload.updated.join(", ")}`);
323
+ }
324
+ if (payload.deleted && payload.deleted.length > 0) {
325
+ logger.warn(`Deleted files: ${payload.deleted.join(", ")}`);
326
+ }
327
+ if (payload.errors && Object.keys(payload.errors).length > 0) {
328
+ for (const [pathKey, value] of Object.entries(payload.errors)) {
329
+ logger.error(`Error for '${pathKey}': ${value}`);
330
+ }
331
+ throw new Error("Upload completed with file-specific errors.");
332
+ }
333
+ });
334
+ }
@@ -41,13 +41,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
41
41
  step((generator = generator.apply(thisArg, _arguments || [])).next());
42
42
  });
43
43
  };
44
- var __importDefault = (this && this.__importDefault) || function (mod) {
45
- return (mod && mod.__esModule) ? mod : { "default": mod };
46
- };
47
44
  Object.defineProperty(exports, "__esModule", { value: true });
48
45
  exports.useCommand = useCommand;
49
46
  const commander_1 = require("commander");
50
- const chalk_1 = __importDefault(require("chalk"));
47
+ const logger_1 = require("../logger");
51
48
  const config_1 = require("../utils/config");
52
49
  const fs = __importStar(require("fs"));
53
50
  const path = __importStar(require("path"));
@@ -56,7 +53,10 @@ function useCommand() {
56
53
  .description("Set authentication token for AMA project")
57
54
  .option("-t, --token <token>", "Authentication token")
58
55
  .option("-u, --url <url>", "Project base URL")
56
+ .option("-p, --project-id <id>", "Project identifier override")
57
+ .option("--verbose", "Enable verbose logging")
59
58
  .action((options) => __awaiter(this, void 0, void 0, function* () {
59
+ const logger = new logger_1.Logger(Boolean(options.verbose));
60
60
  const rlQuestion = (query) => {
61
61
  return new Promise((resolve) => {
62
62
  const rl = require("readline").createInterface({
@@ -74,35 +74,47 @@ function useCommand() {
74
74
  const projectUrl = options.url || (yield rlQuestion("Enter the project URL: "));
75
75
  const authToken = options.token ||
76
76
  (yield rlQuestion("Enter the authentication token: "));
77
+ const detectProjectId = (url) => {
78
+ const match = url.match(/\/projects\/([^/?#]+)/i);
79
+ return match === null || match === void 0 ? void 0 : match[1];
80
+ };
81
+ const detectedProjectId = detectProjectId(projectUrl);
82
+ const projectId = options.projectId || detectedProjectId;
83
+ if (!projectId) {
84
+ logger.warn("Project ID could not be detected from the URL. Rerun with --project-id to set it explicitly.");
85
+ }
77
86
  // Create .ama directory if it doesn't exist
78
87
  const amaDir = path.join(process.cwd(), ".ama");
79
88
  if (!fs.existsSync(amaDir)) {
80
89
  fs.mkdirSync(amaDir, { recursive: true });
90
+ logger.verbose_log(`Created directory ${amaDir}.`);
81
91
  }
82
92
  // Add .gitignore if it doesn't exist or update it
83
93
  const gitignorePath = path.join(process.cwd(), ".gitignore");
84
94
  const gitignoreEntry = "\n# AMA configuration\n.ama/session.json\n";
85
95
  if (!fs.existsSync(gitignorePath)) {
86
96
  fs.writeFileSync(gitignorePath, gitignoreEntry);
97
+ logger.verbose_log(`Created ${gitignorePath} with AMA ignore rules.`);
87
98
  }
88
99
  else {
89
100
  const currentContent = fs.readFileSync(gitignorePath, "utf8");
90
101
  if (!currentContent.includes(".ama/session.json")) {
91
102
  fs.appendFileSync(gitignorePath, gitignoreEntry);
103
+ logger.verbose_log(`Updated ${gitignorePath} with AMA ignore rules.`);
92
104
  }
93
105
  }
94
- const projectId = "proj_" + Math.random().toString(36).slice(2, 9);
95
106
  const configData = { token: authToken, projectId, url: projectUrl };
96
107
  (0, config_1.setConfig)(configData);
97
108
  // Save session data to .ama/session.json
98
109
  fs.writeFileSync(path.join(amaDir, "session.json"), JSON.stringify(configData, null, 2));
99
- console.log(chalk_1.default.green("🔐 Successfully authenticated and joined project"));
100
- console.log(chalk_1.default.yellow("⚠️ Warning: Keep your .ama/session.json file private and do not commit it to version control"));
101
- console.log(chalk_1.default.blue("ℹ️ Note: Session file has been automatically added to .gitignore"));
110
+ logger.success("Authentication details saved for the project.");
111
+ logger.info(`Session file stored at ${path.join(amaDir, "session.json")}.`);
112
+ logger.warn("Keep your .ama/session.json file private and exclude it from version control.");
113
+ logger.info("Session file has been added to the project .gitignore file.");
102
114
  }
103
115
  catch (error) {
104
116
  const message = error instanceof Error ? error.message : "Unknown error";
105
- console.error(chalk_1.default.red(`❌ Error: ${message}`));
117
+ logger.error(`Configuration update failed: ${message}`, error);
106
118
  process.exit(1);
107
119
  }
108
120
  }));
package/dist/cli/index.js CHANGED
@@ -4,12 +4,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const commander_1 = require("commander");
5
5
  const migrate_1 = require("./commands/migrate");
6
6
  const use_1 = require("./commands/use");
7
+ const upload_1 = require("./commands/upload");
8
+ const generate_1 = require("./commands/generate");
9
+ const snapshot_1 = require("./commands/snapshot");
7
10
  const program = new commander_1.Command()
8
11
  .name("ama")
9
12
  .description("AtMyApp CLI Tool")
10
13
  .version("1.0.0");
11
14
  program.addCommand((0, use_1.useCommand)());
12
15
  program.addCommand((0, migrate_1.migrateCommand)());
16
+ program.addCommand((0, upload_1.uploadCommand)());
17
+ program.addCommand((0, generate_1.generateCommand)());
18
+ program.addCommand((0, snapshot_1.snapshotCommand)());
13
19
  program.parseAsync(process.argv).catch((err) => {
14
20
  console.error("Error:", err.message);
15
21
  process.exit(1);
@@ -1,12 +1,14 @@
1
1
  /**
2
- * Logger utility to handle verbose logging
2
+ * Logger utility to handle verbose logging with consistent formatting.
3
3
  */
4
4
  export declare class Logger {
5
- private verbose;
5
+ private readonly verbose;
6
6
  constructor(verbose: boolean);
7
7
  info(message: string): void;
8
8
  success(message: string): void;
9
+ warn(message: string): void;
9
10
  error(message: string, error?: unknown): void;
10
11
  verbose_log(message: string): void;
11
- warn(message: string): void;
12
+ private write;
13
+ private formatErrorDetail;
12
14
  }
@@ -5,30 +5,76 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Logger = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
+ const LEVEL_CONFIG = {
9
+ info: { label: "INFO", style: (text) => chalk_1.default.blueBright.bold(text), method: "log" },
10
+ success: { label: "SUCCESS", style: (text) => chalk_1.default.greenBright.bold(text), method: "log" },
11
+ warn: { label: "WARN", style: (text) => chalk_1.default.yellowBright.bold(text), method: "warn" },
12
+ error: { label: "ERROR", style: (text) => chalk_1.default.redBright.bold(text), method: "error" },
13
+ verbose: { label: "VERBOSE", style: (text) => chalk_1.default.gray.bold(text), method: "log" },
14
+ };
8
15
  /**
9
- * Logger utility to handle verbose logging
16
+ * Logger utility to handle verbose logging with consistent formatting.
10
17
  */
11
18
  class Logger {
12
19
  constructor(verbose) {
13
20
  this.verbose = verbose;
14
21
  }
15
22
  info(message) {
16
- console.log(chalk_1.default.blue(message));
23
+ this.write("info", message);
17
24
  }
18
25
  success(message) {
19
- console.log(chalk_1.default.green(message));
26
+ this.write("success", message);
27
+ }
28
+ warn(message) {
29
+ this.write("warn", message);
20
30
  }
21
31
  error(message, error) {
22
- const errorMessage = error instanceof Error ? error.message : String(error);
23
- console.error(chalk_1.default.red(message), error ? chalk_1.default.red(errorMessage) : "");
32
+ const detail = this.formatErrorDetail(error);
33
+ const formatted = detail ? `${message}\n${chalk_1.default.gray(detail)}` : message;
34
+ this.write("error", formatted);
24
35
  }
25
36
  verbose_log(message) {
26
- if (this.verbose) {
27
- console.log(chalk_1.default.cyan(`[VERBOSE] ${message}`));
37
+ if (!this.verbose) {
38
+ return;
28
39
  }
40
+ this.write("verbose", message);
29
41
  }
30
- warn(message) {
31
- console.warn(chalk_1.default.yellow(message));
42
+ write(level, message) {
43
+ const { label, style, method } = LEVEL_CONFIG[level];
44
+ const rawLabel = `[${label}]`;
45
+ const styledLabel = style(rawLabel);
46
+ const lines = message.split(/\r?\n/);
47
+ const continuationPrefix = " ".repeat(rawLabel.length + 1);
48
+ for (const [index, line] of lines.entries()) {
49
+ const output = index === 0 ? `${styledLabel} ${line}` : `${continuationPrefix}${line}`;
50
+ if (method === "warn") {
51
+ console.warn(output);
52
+ }
53
+ else if (method === "error") {
54
+ console.error(output);
55
+ }
56
+ else {
57
+ console.log(output);
58
+ }
59
+ }
60
+ }
61
+ formatErrorDetail(error) {
62
+ var _a;
63
+ if (!error) {
64
+ return undefined;
65
+ }
66
+ if (error instanceof Error) {
67
+ return (_a = error.stack) !== null && _a !== void 0 ? _a : error.message;
68
+ }
69
+ if (typeof error === "string") {
70
+ return error;
71
+ }
72
+ try {
73
+ return JSON.stringify(error, null, 2);
74
+ }
75
+ catch (_b) {
76
+ return String(error);
77
+ }
32
78
  }
33
79
  }
34
80
  exports.Logger = Logger;
@@ -15,6 +15,11 @@ export interface OutputDefinition {
15
15
  events: Record<string, EventConfig>;
16
16
  args: any[];
17
17
  metadata?: any;
18
+ mdx?: Record<string, {
19
+ components: Record<string, {
20
+ props?: Record<string, string>;
21
+ }>;
22
+ }>;
18
23
  }
19
24
  export interface MigrateOptions {
20
25
  dryRun: boolean;
@@ -29,6 +29,22 @@ function detectAmaAssetField(schema) {
29
29
  }
30
30
  return Object.assign({ format: assetMapping.format, semanticType: assetMapping.semanticType }, (imageOptions ? { imageOptions } : {}));
31
31
  }
32
+ function detectAmaMdxField(schema) {
33
+ var _a, _b, _c, _d, _e, _f;
34
+ const amaType = (_b = (_a = schema === null || schema === void 0 ? void 0 : schema.properties) === null || _a === void 0 ? void 0 : _a.__amatype) === null || _b === void 0 ? void 0 : _b.const;
35
+ if (amaType !== "AmaMdxDef") {
36
+ return null;
37
+ }
38
+ const mdxConfigConst = (_d = (_c = schema === null || schema === void 0 ? void 0 : schema.properties) === null || _c === void 0 ? void 0 : _c.mdxConfig) === null || _d === void 0 ? void 0 : _d.const;
39
+ if (typeof mdxConfigConst === "string") {
40
+ return { mdxConfig: mdxConfigConst };
41
+ }
42
+ const mdxConfigEnum = (_f = (_e = schema === null || schema === void 0 ? void 0 : schema.properties) === null || _e === void 0 ? void 0 : _e.mdxConfig) === null || _f === void 0 ? void 0 : _f.enum;
43
+ if (Array.isArray(mdxConfigEnum) && typeof mdxConfigEnum[0] === "string") {
44
+ return { mdxConfig: mdxConfigEnum[0] };
45
+ }
46
+ return null;
47
+ }
32
48
  function ensureDescription(description, fallback) {
33
49
  if (typeof description === "string" && description.trim().length > 0) {
34
50
  return description.trim();
@@ -136,6 +152,18 @@ function convertField(schema, fieldName, logger, breadcrumb) {
136
152
  }
137
153
  return base;
138
154
  }
155
+ const mdxField = detectAmaMdxField(schema);
156
+ if (mdxField) {
157
+ const description = ensureDescription(schema.description, `Generated description for ${breadcrumb}`);
158
+ return {
159
+ type: "string",
160
+ description,
161
+ format: "mdx",
162
+ storeInBlob: true,
163
+ __amatype: "AmaMdxDef",
164
+ mdxConfig: mdxField.mdxConfig,
165
+ };
166
+ }
139
167
  let type = inferType(schema);
140
168
  if (!type) {
141
169
  logger.error(`Collection conversion failed for field "${breadcrumb}": could not determine field type.`);
@@ -1,10 +1,10 @@
1
- type Config = {
1
+ export interface AmaConfig {
2
2
  token?: string;
3
3
  projectId?: string;
4
+ url?: string;
4
5
  include?: string[];
5
6
  description?: string;
6
7
  args?: Record<string, string>;
7
- };
8
- export declare function setConfig(config: Config): void;
9
- export declare function getConfig(): Config;
10
- export {};
8
+ }
9
+ export declare function setConfig(config: AmaConfig): void;
10
+ export declare function getConfig(): AmaConfig;
@@ -19,7 +19,6 @@ function ensureConfigDir() {
19
19
  }
20
20
  function setConfig(config) {
21
21
  ensureConfigDir();
22
- (0, fs_1.writeFileSync)(CONFIG_PATH, JSON.stringify(config, null, 2));
23
22
  try {
24
23
  (0, fs_1.writeFileSync)(CONFIG_PATH, JSON.stringify(config, null, 2));
25
24
  }
@@ -105,17 +105,26 @@ function generateOutput(contents, config, logger) {
105
105
  // Separate events from regular definitions
106
106
  const events = {};
107
107
  const definitions = {};
108
+ const mdx = {};
108
109
  transformedContents.forEach((content) => {
109
- var _a, _b, _c, _d;
110
+ var _a, _b, _c, _d, _e, _f;
111
+ if (content.type === "mdxConfig") {
112
+ const name = (_a = content.structure) === null || _a === void 0 ? void 0 : _a.name;
113
+ const components = (_b = content.structure) === null || _b === void 0 ? void 0 : _b.components;
114
+ if (typeof name === "string" && components && typeof components === "object") {
115
+ mdx[name] = { components };
116
+ }
117
+ return;
118
+ }
110
119
  const contentType = determineContentType(content);
111
120
  if (contentType === "event") {
112
121
  logger.verbose_log(`Processing event: ${content.path}`);
113
122
  // Extract event ID from path or structure
114
123
  let eventId = content.path;
115
- if ((_c = (_b = (_a = content.structure) === null || _a === void 0 ? void 0 : _a.properties) === null || _b === void 0 ? void 0 : _b.id) === null || _c === void 0 ? void 0 : _c.const) {
124
+ if ((_e = (_d = (_c = content.structure) === null || _c === void 0 ? void 0 : _c.properties) === null || _d === void 0 ? void 0 : _d.id) === null || _e === void 0 ? void 0 : _e.const) {
116
125
  eventId = content.structure.properties.id.const;
117
126
  }
118
- else if ((_d = content.structure) === null || _d === void 0 ? void 0 : _d.id) {
127
+ else if ((_f = content.structure) === null || _f === void 0 ? void 0 : _f.id) {
119
128
  eventId = content.structure.id;
120
129
  }
121
130
  const eventConfig = extractEventConfig(content);
@@ -136,12 +145,8 @@ function generateOutput(contents, config, logger) {
136
145
  }
137
146
  });
138
147
  logger.verbose_log("Generating base output definition");
139
- const baseOutput = {
140
- description: config.description || "AMA Definitions",
141
- definitions,
142
- events,
143
- args: config.args || {},
144
- };
148
+ const baseOutput = Object.assign({ description: config.description || "AMA Definitions", definitions,
149
+ events, args: config.args || {} }, (Object.keys(mdx).length > 0 ? { mdx } : {}));
145
150
  // Transform the final output through the pipeline
146
151
  logger.verbose_log("Applying output transformations");
147
152
  const finalOutput = definition_processor_1.definitionPipeline.transformOutput(baseOutput, config, logger);