atmx-cli 0.62.0 → 0.63.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.
@@ -0,0 +1,665 @@
1
+ Project Root: /Users/yashmakan/AxiomCore/AxiomCore/release/atmx-cli
2
+ Project Structure:
3
+ ```
4
+ .
5
+ |-- package-lock.json
6
+ |-- package.json
7
+ |-- src
8
+ |-- generators
9
+ |-- model-generator.ts
10
+ |-- sdk-generator.ts
11
+ |-- utils.ts
12
+ |-- index.ts
13
+ |-- templates
14
+ |-- types.ts
15
+ |-- tsconfig.json
16
+
17
+ ```
18
+
19
+ ---
20
+ ## File: package.json
21
+
22
+ ```json
23
+ {
24
+ "name": "atmx-cli",
25
+ "version": "0.62.0",
26
+ "description": "",
27
+ "main": "dist/index.js",
28
+ "scripts": {
29
+ "build": "tsc"
30
+ },
31
+ "bin": {
32
+ "atmx": "./dist/index.js"
33
+ },
34
+ "keywords": [],
35
+ "author": "",
36
+ "license": "ISC",
37
+ "type": "commonjs",
38
+ "dependencies": {
39
+ "@iarna/toml": "^2.2.5",
40
+ "commander": "^14.0.3",
41
+ "fs-extra": "^11.3.4"
42
+ },
43
+ "devDependencies": {
44
+ "@types/fs-extra": "^11.0.4",
45
+ "@types/iarna__toml": "^2.0.5",
46
+ "@types/node": "^25.5.0",
47
+ "ts-node": "^10.9.2",
48
+ "typescript": "^5.9.3"
49
+ }
50
+ }
51
+
52
+ ```
53
+ ---
54
+ ## File: src/generators/model-generator.ts
55
+
56
+ ```ts
57
+ // FILE: atmx-cli/src/generators/model-generator.ts
58
+ import { AxiomEnum, AxiomModel, MultiIR } from "../types";
59
+ import { pascalCase, camelCase, mapTypeToTs } from "./utils";
60
+
61
+ export function generateModels(multiIr: MultiIR): string {
62
+ const sections: string[] = [
63
+ `// GENERATED CODE – DO NOT EDIT.\n/* eslint-disable @typescript-eslint/no-explicit-any */\n`,
64
+ `/* eslint-disable @typescript-eslint/no-namespace */\n`, // ✨ FIX: Disable namespace lint error
65
+ ];
66
+
67
+ for (const [ns, ir] of Object.entries(multiIr)) {
68
+ const camelNs = camelCase(ns);
69
+ // ✨ FIX: Use proper TS namespaces
70
+ sections.push(`export namespace ${camelNs} {`);
71
+
72
+ const enumsList = Array.isArray(ir.enums)
73
+ ? ir.enums
74
+ : Object.values(ir.enums || {});
75
+ const modelsList = Array.isArray(ir.models)
76
+ ? ir.models
77
+ : Object.values(ir.models || {});
78
+
79
+ enumsList.forEach((en: any) => sections.push(generateEnum(en)));
80
+ modelsList.forEach((model: any) =>
81
+ sections.push(generateInterface(model, camelNs)),
82
+ );
83
+
84
+ sections.push(`}\n`);
85
+ }
86
+
87
+ sections.push(generateMappers(multiIr));
88
+ return sections.join("\n");
89
+ }
90
+
91
+ function generateEnum(en: AxiomEnum): string {
92
+ const name = pascalCase(en.name);
93
+ const values = en.values.map((v) => ` ${pascalCase(v)}: "${v}"`).join(",\n");
94
+ return `
95
+ export const ${name} = {
96
+ ${values}
97
+ } as const;
98
+ export type ${name} = typeof ${name}[keyof typeof ${name}];
99
+ `;
100
+ }
101
+
102
+ function generateInterface(model: AxiomModel, ns: string): string {
103
+ const name = pascalCase(model.name);
104
+ const fields = model.fields
105
+ .map((f) => {
106
+ const type = mapTypeToTs(f.typeRef, ns);
107
+ return ` ${camelCase(f.name)}${f.isOptional ? "?" : ""}: ${type};`;
108
+ })
109
+ .join("\n");
110
+
111
+ return `
112
+ export interface ${name} {
113
+ ${fields}
114
+ }
115
+ `;
116
+ }
117
+
118
+ function generateMappers(multiIr: MultiIR): string {
119
+ const lines: string[] = [`export const Mappers: Record<string, any> = {`];
120
+
121
+ for (const [ns, ir] of Object.entries(multiIr)) {
122
+ const camelNs = camelCase(ns);
123
+ lines.push(` ${camelNs}: {`);
124
+
125
+ const modelsList = Array.isArray(ir.models)
126
+ ? ir.models
127
+ : Object.values(ir.models || {});
128
+
129
+ modelsList.forEach((model: any) => {
130
+ const name = pascalCase(model.name);
131
+ const fullType = `${camelNs}.${name}`;
132
+
133
+ lines.push(
134
+ ` ${name}: {\n fromJson: (json: any): ${fullType} => ({`,
135
+ );
136
+ model.fields.forEach((f: any) => {
137
+ lines.push(
138
+ ` ${camelCase(f.name)}: ${generateJsonLogic(f.typeRef, `json["${f.name}"]`, f.isOptional, "fromJson", camelNs)},`,
139
+ );
140
+ });
141
+ lines.push(` }),\n toJson: (obj: any): any => ({`);
142
+ model.fields.forEach((f: any) => {
143
+ lines.push(
144
+ ` "${f.name}": ${generateJsonLogic(f.typeRef, `obj.${camelCase(f.name)}`, f.isOptional, "toJson", camelNs)},`,
145
+ );
146
+ });
147
+ lines.push(` })\n },`);
148
+ });
149
+ lines.push(` },`);
150
+ }
151
+ lines.push(`};\n`);
152
+ return lines.join("\n");
153
+ }
154
+
155
+ function generateJsonLogic(
156
+ typeRef: any,
157
+ access: string,
158
+ isOpt: boolean,
159
+ mode: "fromJson" | "toJson",
160
+ ns: string,
161
+ ): string {
162
+ const wrap = (logic: string) =>
163
+ isOpt ? `(${access} == null ? undefined : ${logic})` : logic;
164
+ if (!typeRef || !typeRef.kind) return access;
165
+ if (typeRef.kind === "dateTime")
166
+ return mode === "fromJson"
167
+ ? wrap(`new Date(${access})`)
168
+ : wrap(`${access}.toISOString()`);
169
+ if (typeRef.kind === "bytes")
170
+ return mode === "fromJson"
171
+ ? wrap(`new Uint8Array(${access})`)
172
+ : wrap(`Array.from(${access})`);
173
+ if (typeRef.kind === "named") {
174
+ const name = pascalCase(typeRef.value);
175
+ return wrap(
176
+ `(Mappers.${ns}["${name}"] ? Mappers.${ns}["${name}"].${mode}(${access}) : ${access})`,
177
+ );
178
+ }
179
+ if (typeRef.kind === "list")
180
+ return wrap(
181
+ `${access}.map((e: any) => ${generateJsonLogic(typeRef.value, "e", false, mode, ns)})`,
182
+ );
183
+ return access;
184
+ }
185
+
186
+ ```
187
+ ---
188
+ ## File: src/generators/sdk-generator.ts
189
+
190
+ ```ts
191
+ // FILE: atmx-cli/src/generators/sdk-generator.ts
192
+ import { AxiomEndpoint, AxiomParameter, MultiIR } from "../types";
193
+ import { pascalCase, camelCase, mapTypeToTs } from "./utils";
194
+
195
+ export function generateSdk(
196
+ multiIr: MultiIR,
197
+ isReact: boolean = false,
198
+ ): string {
199
+ const lines: string[] = [
200
+ `// GENERATED CODE – DO NOT EDIT.`,
201
+ `/* eslint-disable @typescript-eslint/no-explicit-any */`,
202
+ `import * as models from './models';\n`,
203
+ ];
204
+
205
+ if (isReact) {
206
+ // ✨ FIX: Auto-import the auth helpers to bind them to the module
207
+ lines.push(
208
+ `import { useAxiomQuery, useAxiomMutation, setAuthToken, clearAuthToken } from 'atmx-react';`,
209
+ );
210
+ lines.push(`import type { AxiomQueryDef } from 'atmx-react';\n`);
211
+ }
212
+
213
+ for (const [ns, ir] of Object.entries(multiIr)) {
214
+ const camelNs = camelCase(ns);
215
+ lines.push(`export const ${camelNs}Module = {`);
216
+
217
+ // ✨ FIX: Safely bind auth tokens using the EXACT namespace string from the TOML file!
218
+ if (isReact) {
219
+ lines.push(` setAuthToken(methodName: string, token: string) {`);
220
+ lines.push(` setAuthToken("${ns}", methodName, token);`);
221
+ lines.push(` },`);
222
+ lines.push(` clearAuthToken(methodName: string) {`);
223
+ lines.push(` clearAuthToken("${ns}", methodName);`);
224
+ lines.push(` },`);
225
+ } else {
226
+ lines.push(` setAuthToken(methodName: string, token: string) {`);
227
+ lines.push(
228
+ ` (window as any).atmx?.setAuthToken("${ns}", methodName, token);`,
229
+ );
230
+ lines.push(` },`);
231
+ lines.push(` clearAuthToken(methodName: string) {`);
232
+ lines.push(
233
+ ` (window as any).atmx?.clearAuthToken("${ns}", methodName);`,
234
+ );
235
+ lines.push(` },`);
236
+ }
237
+
238
+ const endpointsMap = ir.endpoints || {};
239
+ const endpoints = Array.isArray(endpointsMap)
240
+ ? endpointsMap
241
+ : Object.values(endpointsMap);
242
+
243
+ endpoints.forEach((ep: any) => {
244
+ lines.push(generateEndpointMethod(ep, ns, camelNs, isReact));
245
+ });
246
+ lines.push(`};\n`);
247
+ }
248
+
249
+ lines.push(`export const sdk = {`);
250
+ for (const ns of Object.keys(multiIr)) {
251
+ lines.push(` ${camelCase(ns)}: ${camelCase(ns)}Module,`);
252
+ }
253
+ lines.push(`};\n`);
254
+
255
+ lines.push(`export const AxiomDefaultConfig = {`);
256
+ lines.push(` contracts: {`);
257
+ for (const ns of Object.keys(multiIr)) {
258
+ lines.push(` "${ns}": {`);
259
+ lines.push(` contractUrl: "/${ns}.axiom",`);
260
+ lines.push(` baseUrl: "http://localhost:8000"`);
261
+ lines.push(` },`);
262
+ }
263
+ lines.push(` }`);
264
+ lines.push(`};\n`);
265
+
266
+ return lines.join("\n");
267
+ }
268
+
269
+ // FILE: atmx-cli/src/generators/sdk-generator.ts (Partial replacement)
270
+
271
+ function generateEndpointMethod(
272
+ ep: AxiomEndpoint,
273
+ ns: string,
274
+ camelNs: string,
275
+ isReact: boolean,
276
+ ): string {
277
+ const rawParams = ep.parameters || [];
278
+ const params = Array.isArray(rawParams)
279
+ ? rawParams
280
+ : Object.values(rawParams);
281
+
282
+ const isQuery = ep.method ? ep.method.toUpperCase() === "GET" : true;
283
+ const rawReturnType = mapTypeToTs(ep.returnType, camelNs);
284
+ const returnType =
285
+ rawReturnType === "void" || rawReturnType === "any"
286
+ ? rawReturnType
287
+ : prefixModels(rawReturnType);
288
+
289
+ // Map camelCase TS args back to original IR snake_case names!
290
+ const argsMapping = params
291
+ .map(
292
+ (p: any) =>
293
+ `if (args && '${camelCase(p.name)}' in args) { mappedArgs["${p.name}"] = (args as any)["${camelCase(p.name)}"]; delete mappedArgs["${camelCase(p.name)}"]; }`,
294
+ )
295
+ .join("\n ");
296
+
297
+ if (params.length === 0) {
298
+ if (isReact) {
299
+ const decLogic = generateLambda(ep.returnType, "fromJson", camelNs);
300
+ return `
301
+ get${pascalCase(ep.name)}Def(args?: Record<string, any>): AxiomQueryDef<${returnType}> {
302
+ return {
303
+ namespace: "${ns}", name: "${ep.name}", endpointId: ${ep.id},
304
+ method: "${ep.method ? ep.method.toUpperCase() : "GET"}", path: "${ep.path}",
305
+ args: args || {}, decoder: ${decLogic}, serializer: (p: any) => p, isStream: ${ep.isStream === true}
306
+ };
307
+ },
308
+ use${pascalCase(ep.name)}${!isQuery ? "Mutation" : ""}(options?: { enabled?: boolean }) {
309
+ ${isQuery ? `return useAxiomQuery<${returnType}>(this.get${pascalCase(ep.name)}Def(), options);` : `return useAxiomMutation<${returnType}, void | Record<string,any>>((a) => this.get${pascalCase(ep.name)}Def(a));`}
310
+ },`;
311
+ } else {
312
+ return `
313
+ ${camelCase(ep.name)}(args?: Record<string, any>): string {
314
+ const argsStr = args && Object.keys(args).length > 0 ? JSON.stringify(args) : '';
315
+ return \`${ns}.${ep.name}(\${argsStr})\`;
316
+ },`;
317
+ }
318
+ }
319
+
320
+ const argType = `{ ${params.map((p: any) => `${camelCase(p.name)}${p.isOptional ? "?" : ""}: ${prefixModels(mapTypeToTs(p.typeRef, camelNs))}`).join(", ")} }`;
321
+
322
+ if (isReact) {
323
+ const bodyParam = params.find(
324
+ (p: any) => p.source === "body",
325
+ ) as AxiomParameter;
326
+ const payloadLogic = bodyParam
327
+ ? `const payload = (args as any)?.${camelCase(bodyParam.name)};`
328
+ : `const payload = undefined;`;
329
+ const decLogic = generateLambda(ep.returnType, "fromJson", camelNs);
330
+ const serLogic = bodyParam
331
+ ? generateLambda(bodyParam.typeRef, "toJson", camelNs)
332
+ : `(p: any) => p`;
333
+
334
+ return `
335
+ get${pascalCase(ep.name)}Def(args?: ${argType}): AxiomQueryDef<${returnType}> {
336
+ ${payloadLogic}
337
+ const mappedArgs: any = { ...(args || {}) };
338
+ ${argsMapping}
339
+
340
+ return {
341
+ namespace: "${ns}", name: "${ep.name}", endpointId: ${ep.id},
342
+ method: "${ep.method ? ep.method.toUpperCase() : "GET"}", path: "${ep.path}",
343
+ payload: payload, args: mappedArgs, decoder: ${decLogic}, serializer: ${serLogic}, isStream: ${ep.isStream === true}
344
+ };
345
+ },
346
+ use${pascalCase(ep.name)}${!isQuery ? "Mutation" : ""}(args?: ${argType}, options?: { enabled?: boolean }) {
347
+ ${isQuery ? `return useAxiomQuery<${returnType}>(this.get${pascalCase(ep.name)}Def(args), options);` : `return useAxiomMutation<${returnType}, ${argType}>((a) => this.get${pascalCase(ep.name)}Def(a || args));`}
348
+ },`;
349
+ } else {
350
+ return `
351
+ ${camelCase(ep.name)}(args?: ${argType}): string {
352
+ const mappedArgs: any = { ...(args || {}) };
353
+ ${argsMapping}
354
+ const argsStr = Object.keys(mappedArgs).length > 0 ? JSON.stringify(mappedArgs) : '';
355
+ return \`${ns}.${ep.name}(\${argsStr})\`;
356
+ },`;
357
+ }
358
+ }
359
+
360
+ function generateLambda(
361
+ typeRef: any,
362
+ mode: "fromJson" | "toJson",
363
+ ns: string,
364
+ ): string {
365
+ if (!typeRef || !typeRef.kind || typeRef.kind === "void")
366
+ return mode === "fromJson" ? `() => undefined` : `(p: any) => p`;
367
+ if (typeRef.kind === "list" && typeRef.value?.kind === "named")
368
+ return `(data: any[]) => data.map(models.Mappers.${ns}.${pascalCase(typeRef.value.value)}.${mode})`;
369
+ if (typeRef.kind === "named")
370
+ return `models.Mappers.${ns}.${pascalCase(typeRef.value)}.${mode}`;
371
+ return `(data: any) => data`;
372
+ }
373
+
374
+ function prefixModels(type: string): string {
375
+ const primitives = [
376
+ "string",
377
+ "number",
378
+ "boolean",
379
+ "Date",
380
+ "Uint8Array",
381
+ "void",
382
+ "any",
383
+ ];
384
+ if (!type || primitives.includes(type)) return type;
385
+ if (type.endsWith("[]")) return `${prefixModels(type.slice(0, -2))}[]`;
386
+ if (type.startsWith("models.")) return type;
387
+ return `models.${type}`;
388
+ }
389
+
390
+ ```
391
+ ---
392
+ ## File: src/generators/utils.ts
393
+
394
+ ```ts
395
+ // FILE: atmx-cli/src/generators/utils.ts
396
+ export function pascalCase(str: string): string {
397
+ if (!str) return "";
398
+ return str
399
+ .split(/[_\-\s]+/)
400
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
401
+ .join("");
402
+ }
403
+
404
+ export function camelCase(str: string): string {
405
+ const pascal = pascalCase(str);
406
+ return pascal.charAt(0).toLowerCase() + pascal.slice(1);
407
+ }
408
+
409
+ export function normalizeIr(obj: any): any {
410
+ if (Array.isArray(obj)) return obj.map(normalizeIr);
411
+ if (obj !== null && typeof obj === "object") {
412
+ const newObj: any = {};
413
+ for (const key of Object.keys(obj)) {
414
+ const camelKey = key.replace(/_([a-z])/g, (g) => g[1].toUpperCase());
415
+ newObj[camelKey] = normalizeIr(obj[key]);
416
+ }
417
+ if (
418
+ newObj.endpoints &&
419
+ typeof newObj.endpoints === "object" &&
420
+ !Array.isArray(newObj.endpoints)
421
+ ) {
422
+ newObj.endpoints = Object.values(newObj.endpoints);
423
+ }
424
+ if (
425
+ newObj.models &&
426
+ typeof newObj.models === "object" &&
427
+ !Array.isArray(newObj.models)
428
+ ) {
429
+ newObj.models = Object.values(newObj.models);
430
+ }
431
+ if (
432
+ newObj.enums &&
433
+ typeof newObj.enums === "object" &&
434
+ !Array.isArray(newObj.enums)
435
+ ) {
436
+ newObj.enums = Object.values(newObj.enums);
437
+ }
438
+ if (Array.isArray(newObj.models)) {
439
+ newObj.models = newObj.models.map((model: any) => {
440
+ if (
441
+ model.fields &&
442
+ typeof model.fields === "object" &&
443
+ !Array.isArray(model.fields)
444
+ ) {
445
+ model.fields = Object.values(model.fields);
446
+ }
447
+ return model;
448
+ });
449
+ }
450
+ return newObj;
451
+ }
452
+ return obj;
453
+ }
454
+
455
+ export function mapTypeToTs(typeRef: any, ns?: string): string {
456
+ if (!typeRef || !typeRef.kind) return "any";
457
+
458
+ switch (typeRef.kind) {
459
+ case "string":
460
+ return "string";
461
+ case "int32":
462
+ case "int64":
463
+ case "float32":
464
+ case "float64":
465
+ return "number";
466
+ case "bool":
467
+ return "boolean";
468
+ case "dateTime":
469
+ return "Date";
470
+ case "bytes":
471
+ return "Uint8Array";
472
+ case "void":
473
+ return "void";
474
+ case "json":
475
+ return "any";
476
+ case "named":
477
+ const name = pascalCase(typeRef.value);
478
+ return ns ? `${ns}.${name}` : name;
479
+ case "list":
480
+ return `${mapTypeToTs(typeRef.value, ns)}[]`;
481
+ case "map":
482
+ const valType = typeRef.value?.[1]
483
+ ? mapTypeToTs(typeRef.value[1], ns)
484
+ : "any";
485
+ return `Record<string, ${valType}>`;
486
+ default:
487
+ return "any";
488
+ }
489
+ }
490
+
491
+ ```
492
+ ---
493
+ ## File: src/index.ts
494
+
495
+ ```ts
496
+ #!/usr/bin/env node
497
+ import { Command } from "commander";
498
+ import * as fs from "fs-extra";
499
+ import * as path from "path";
500
+ import * as toml from "@iarna/toml";
501
+ import { MultiIR } from "./types";
502
+ import { generateModels } from "./generators/model-generator";
503
+ import { generateSdk } from "./generators/sdk-generator";
504
+ import { normalizeIr } from "./generators/utils";
505
+
506
+ const program = new Command();
507
+
508
+ program
509
+ .name("atmx")
510
+ .description("Generate TypeScript SDK from AxiomDeps.toml")
511
+ .version("0.2.0");
512
+
513
+ program
514
+ .command("generate")
515
+ .requiredOption("-c, --config <path>", "Path to AxiomDeps.toml")
516
+ .requiredOption("-o, --output <dir>", "Output directory for generated files")
517
+ .option("-r, --react", "Generate React Hooks instead of Vanilla JS strings")
518
+ .action(async (options) => {
519
+ const configPath = path.resolve(options.config);
520
+ const outputDir = path.resolve(options.output);
521
+
522
+ if (!fs.existsSync(configPath)) {
523
+ console.error(`❌ Error: Config file not found at ${configPath}`);
524
+ process.exit(1);
525
+ }
526
+
527
+ // 1. Read and Parse TOML
528
+ const tomlString = await fs.readFile(configPath, "utf-8");
529
+ const rawConfig = toml.parse(tomlString) as any;
530
+
531
+ if (!rawConfig.contracts || Object.keys(rawConfig.contracts).length === 0) {
532
+ console.error("❌ Error: No contracts defined in AxiomDeps.toml.");
533
+ process.exit(1);
534
+ }
535
+
536
+ const multiIr: MultiIR = {};
537
+ const projectRoot = path.dirname(configPath); // Frontend project root
538
+
539
+ // 2. Loop through contracts
540
+ for (const [namespace, contract] of Object.entries(rawConfig.contracts)) {
541
+ // Rust CLI safely copies files to `public/[namespace].axiom`
542
+ const axiomFilePath = path.resolve(
543
+ projectRoot,
544
+ `public/${namespace}.axiom`,
545
+ );
546
+
547
+ if (!fs.existsSync(axiomFilePath)) {
548
+ console.warn(
549
+ `⚠️ Warning: Contract file not found at ${axiomFilePath}. Skipping...`,
550
+ );
551
+ continue;
552
+ }
553
+
554
+ const rawFile = await fs.readJSON(axiomFilePath);
555
+ if (!rawFile.ir) continue;
556
+
557
+ multiIr[namespace] = normalizeIr(rawFile.ir);
558
+ console.log(`✅ Loaded contract: [${namespace}] -> ${axiomFilePath}`);
559
+ }
560
+
561
+ await fs.ensureDir(outputDir);
562
+
563
+ const modelsContent = generateModels(multiIr);
564
+ await fs.writeFile(path.join(outputDir, "models.ts"), modelsContent);
565
+
566
+ const sdkContent = generateSdk(multiIr, options.react);
567
+ await fs.writeFile(path.join(outputDir, "sdk.ts"), sdkContent);
568
+
569
+ console.log(
570
+ `\n🎉 ATMX Multi-Contract SDK generated successfully in ${outputDir}`,
571
+ );
572
+ });
573
+
574
+ program.parse();
575
+
576
+ ```
577
+ ---
578
+ ## File: src/types.ts
579
+
580
+ ```ts
581
+ export interface AxiomIR {
582
+ serviceName: string;
583
+ endpoints: AxiomEndpoint[];
584
+ models: Record<string, AxiomModel>;
585
+ enums: Record<string, AxiomEnum>;
586
+ }
587
+
588
+ export interface AxiomEndpoint {
589
+ id: number;
590
+ name: string;
591
+ path: string;
592
+ method: string;
593
+ parameters: AxiomParameter[];
594
+ returnType: AxiomTypeRef;
595
+ returnIsOptional: boolean;
596
+ isStream: boolean;
597
+ }
598
+
599
+ export interface AxiomParameter {
600
+ name: string;
601
+ source: "path" | "query" | "body";
602
+ typeRef: AxiomTypeRef;
603
+ isOptional: boolean;
604
+ }
605
+
606
+ export type AxiomTypeRef =
607
+ | { kind: "primitive" | "named"; value: string }
608
+ | { kind: "list"; value: AxiomTypeRef }
609
+ | { kind: "map"; value: [AxiomTypeRef, AxiomTypeRef] }
610
+ | { kind: "void" };
611
+
612
+ export interface AxiomModel {
613
+ name: string;
614
+ fields: AxiomField[];
615
+ }
616
+
617
+ export interface AxiomField {
618
+ name: string;
619
+ typeRef: AxiomTypeRef;
620
+ isOptional: boolean;
621
+ }
622
+
623
+ export interface AxiomEnum {
624
+ name: string;
625
+ values: string[];
626
+ }
627
+
628
+ export interface AtmxContractConfig {
629
+ file: string; // Path relative to the config file (e.g., "./auth.axiom")
630
+ baseUrl: string; // The URL for runtime (not used during code generation, but part of schema)
631
+ }
632
+
633
+ export interface AtmxMultiConfig {
634
+ contracts: Record<string, AtmxContractConfig>;
635
+ }
636
+
637
+ // A Map holding the normalized IR for each contract
638
+ export type MultiIR = Record<string, AxiomIR>;
639
+
640
+ ```
641
+ ---
642
+ ## File: tsconfig.json
643
+
644
+ ```json
645
+ {
646
+ "compilerOptions": {
647
+ "target": "ES2020",
648
+ "module": "CommonJS",
649
+ "lib": [
650
+ "ES2020"
651
+ ],
652
+ "rootDir": "src",
653
+ "outDir": "dist",
654
+ "moduleResolution": "node",
655
+ "esModuleInterop": true,
656
+ "forceConsistentCasingInFileNames": true,
657
+ "strict": true,
658
+ "skipLibCheck": true
659
+ },
660
+ "include": [
661
+ "src/**/*"
662
+ ]
663
+ }
664
+ ```
665
+ ---
@@ -0,0 +1,6 @@
1
+ # Add custom ignore patterns here, one per line
2
+ # These patterns will be added to the default ignores and .gitignore patterns
3
+ # Example:
4
+ # *.log
5
+ # temp/
6
+ # secret.txt
@@ -0,0 +1 @@
1
+ []
@@ -0,0 +1,12 @@
1
+ {
2
+ "selected_files": [
3
+ "/Users/yashmakan/AxiomCore/AxiomCore/release/atmx-cli/package.json",
4
+ "/Users/yashmakan/AxiomCore/AxiomCore/release/atmx-cli/src/generators/model-generator.ts",
5
+ "/Users/yashmakan/AxiomCore/AxiomCore/release/atmx-cli/src/generators/sdk-generator.ts",
6
+ "/Users/yashmakan/AxiomCore/AxiomCore/release/atmx-cli/src/generators/utils.ts",
7
+ "/Users/yashmakan/AxiomCore/AxiomCore/release/atmx-cli/src/index.ts",
8
+ "/Users/yashmakan/AxiomCore/AxiomCore/release/atmx-cli/src/types.ts",
9
+ "/Users/yashmakan/AxiomCore/AxiomCore/release/atmx-cli/tsconfig.json"
10
+ ],
11
+ "compressed_files": []
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atmx-cli",
3
- "version": "0.62.0",
3
+ "version": "0.63.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {