atmx-cli 0.54.0 → 0.56.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.
@@ -9,13 +9,30 @@ function generateSdk(multiIr, isReact = false) {
9
9
  `import * as models from './models';\n`,
10
10
  ];
11
11
  if (isReact) {
12
- lines.push(`import { useAxiomQuery, useAxiomMutation } from 'atmx-react';`);
12
+ // ✨ FIX: Auto-import the auth helpers to bind them to the module
13
+ lines.push(`import { useAxiomQuery, useAxiomMutation, setAuthToken, clearAuthToken } from 'atmx-react';`);
13
14
  lines.push(`import type { AxiomQueryDef } from 'atmx-react';\n`);
14
15
  }
15
16
  for (const [ns, ir] of Object.entries(multiIr)) {
16
17
  const camelNs = (0, utils_1.camelCase)(ns);
17
- // ✨ FIX: Use an object literal instead of a Class to support React Hooks!
18
18
  lines.push(`export const ${camelNs}Module = {`);
19
+ // ✨ FIX: Safely bind auth tokens using the EXACT namespace string from the TOML file!
20
+ if (isReact) {
21
+ lines.push(` setAuthToken(methodName: string, token: string) {`);
22
+ lines.push(` setAuthToken("${ns}", methodName, token);`);
23
+ lines.push(` },`);
24
+ lines.push(` clearAuthToken(methodName: string) {`);
25
+ lines.push(` clearAuthToken("${ns}", methodName);`);
26
+ lines.push(` },`);
27
+ }
28
+ else {
29
+ lines.push(` setAuthToken(methodName: string, token: string) {`);
30
+ lines.push(` (window as any).atmx?.setAuthToken("${ns}", methodName, token);`);
31
+ lines.push(` },`);
32
+ lines.push(` clearAuthToken(methodName: string) {`);
33
+ lines.push(` (window as any).atmx?.clearAuthToken("${ns}", methodName);`);
34
+ lines.push(` },`);
35
+ }
19
36
  const endpointsMap = ir.endpoints || {};
20
37
  const endpoints = Array.isArray(endpointsMap)
21
38
  ? endpointsMap
@@ -25,13 +42,11 @@ function generateSdk(multiIr, isReact = false) {
25
42
  });
26
43
  lines.push(`};\n`);
27
44
  }
28
- // Generate main SDK object
29
45
  lines.push(`export const sdk = {`);
30
46
  for (const ns of Object.keys(multiIr)) {
31
47
  lines.push(` ${(0, utils_1.camelCase)(ns)}: ${(0, utils_1.camelCase)(ns)}Module,`);
32
48
  }
33
49
  lines.push(`};\n`);
34
- // Generate Config
35
50
  lines.push(`export const AxiomDefaultConfig = {`);
36
51
  lines.push(` contracts: {`);
37
52
  for (const ns of Object.keys(multiIr)) {
@@ -49,14 +64,38 @@ function generateEndpointMethod(ep, ns, camelNs, isReact) {
49
64
  const params = Array.isArray(rawParams)
50
65
  ? rawParams
51
66
  : Object.values(rawParams);
52
- const argType = params.length > 0
53
- ? `{ ${params.map((p) => `${(0, utils_1.camelCase)(p.name)}${p.isOptional ? "?" : ""}: ${prefixModels((0, utils_1.mapTypeToTs)(p.typeRef, camelNs))}`).join(", ")} }`
54
- : "void";
55
67
  const isQuery = ep.method ? ep.method.toUpperCase() === "GET" : true;
56
68
  const rawReturnType = (0, utils_1.mapTypeToTs)(ep.returnType, camelNs);
57
69
  const returnType = rawReturnType === "void" || rawReturnType === "any"
58
70
  ? rawReturnType
59
71
  : prefixModels(rawReturnType);
72
+ // ✨ FIX: If no parameters are defined, default to accepting an optional Record<string, any>
73
+ // This allows developers to pass undocumented fields (like FastAPI Form data)
74
+ if (params.length === 0) {
75
+ if (isReact) {
76
+ const decLogic = generateLambda(ep.returnType, "fromJson", camelNs);
77
+ return `
78
+ get${(0, utils_1.pascalCase)(ep.name)}Def(args?: Record<string, any>): AxiomQueryDef<${returnType}> {
79
+ return {
80
+ namespace: "${ns}", name: "${ep.name}", endpointId: ${ep.id},
81
+ method: "${ep.method ? ep.method.toUpperCase() : "GET"}", path: "${ep.path}",
82
+ args: args || {}, decoder: ${decLogic}, serializer: (p: any) => p, isStream: ${ep.isStream === true}
83
+ };
84
+ },
85
+ use${(0, utils_1.pascalCase)(ep.name)}${!isQuery ? "Mutation" : ""}(options?: { enabled?: boolean }) {
86
+ ${isQuery ? `return useAxiomQuery<${returnType}>(this.get${(0, utils_1.pascalCase)(ep.name)}Def(), options);` : `return useAxiomMutation<${returnType}, void | Record<string,any>>((a) => this.get${(0, utils_1.pascalCase)(ep.name)}Def(a));`}
87
+ },`;
88
+ }
89
+ else {
90
+ return `
91
+ ${(0, utils_1.camelCase)(ep.name)}(args?: Record<string, any>): string {
92
+ const argsStr = args && Object.keys(args).length > 0 ? JSON.stringify(args) : '';
93
+ return \`${ns}.${ep.name}(\${argsStr})\`;
94
+ },`;
95
+ }
96
+ }
97
+ // Endpoints with explicitly defined parameters
98
+ const argType = `{ ${params.map((p) => `${(0, utils_1.camelCase)(p.name)}${p.isOptional ? "?" : ""}: ${prefixModels((0, utils_1.mapTypeToTs)(p.typeRef, camelNs))}`).join(", ")} }`;
60
99
  if (isReact) {
61
100
  const bodyParam = params.find((p) => p.source === "body");
62
101
  const payloadLogic = bodyParam
@@ -67,31 +106,21 @@ function generateEndpointMethod(ep, ns, camelNs, isReact) {
67
106
  ? generateLambda(bodyParam.typeRef, "toJson", camelNs)
68
107
  : `(p: any) => p`;
69
108
  return `
70
- get${(0, utils_1.pascalCase)(ep.name)}Def(args${params.length > 0 ? "?" : ""}: ${argType === "void" ? "any" : argType}): AxiomQueryDef<${returnType}> {
109
+ get${(0, utils_1.pascalCase)(ep.name)}Def(args?: ${argType}): AxiomQueryDef<${returnType}> {
71
110
  ${payloadLogic}
72
111
  return {
73
- namespace: "${ns}",
74
- name: "${ep.name}",
75
- endpointId: ${ep.id},
76
- method: "${ep.method ? ep.method.toUpperCase() : "GET"}",
77
- path: "${ep.path}",
78
- payload: payload,
79
- args: args || {},
80
- decoder: ${decLogic},
81
- serializer: ${serLogic},
82
- isStream: ${ep.isStream === true}
112
+ namespace: "${ns}", name: "${ep.name}", endpointId: ${ep.id},
113
+ method: "${ep.method ? ep.method.toUpperCase() : "GET"}", path: "${ep.path}",
114
+ payload: payload, args: args || {}, decoder: ${decLogic}, serializer: ${serLogic}, isStream: ${ep.isStream === true}
83
115
  };
84
116
  },
85
-
86
- use${(0, utils_1.pascalCase)(ep.name)}${!isQuery ? "Mutation" : ""}(${isQuery ? `args${params.length > 0 ? "?" : ""}: ${argType === "void" ? "any" : argType}, options?: { enabled?: boolean }` : ""}) {
87
- ${isQuery
88
- ? `return useAxiomQuery<${returnType}>(this.get${(0, utils_1.pascalCase)(ep.name)}Def(args), options);`
89
- : `return useAxiomMutation<${returnType}, ${argType === "void" ? "void | Record<string,any>" : argType}>((args) => this.get${(0, utils_1.pascalCase)(ep.name)}Def(args));`}
117
+ use${(0, utils_1.pascalCase)(ep.name)}${!isQuery ? "Mutation" : ""}(args?: ${argType}, options?: { enabled?: boolean }) {
118
+ ${isQuery ? `return useAxiomQuery<${returnType}>(this.get${(0, utils_1.pascalCase)(ep.name)}Def(args), options);` : `return useAxiomMutation<${returnType}, ${argType}>((a) => this.get${(0, utils_1.pascalCase)(ep.name)}Def(a || args));`}
90
119
  },`;
91
120
  }
92
121
  else {
93
122
  return `
94
- ${(0, utils_1.camelCase)(ep.name)}(args${params.length > 0 ? "?" : ""}: ${argType === "void" ? "any" : argType}): string {
123
+ ${(0, utils_1.camelCase)(ep.name)}(args?: ${argType}): string {
95
124
  const argsStr = args && Object.keys(args).length > 0 ? JSON.stringify(args) : '';
96
125
  return \`${ns}.${ep.name}(\${argsStr})\`;
97
126
  },`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atmx-cli",
3
- "version": "0.54.0",
3
+ "version": "0.56.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -13,15 +13,38 @@ export function generateSdk(
13
13
  ];
14
14
 
15
15
  if (isReact) {
16
- lines.push(`import { useAxiomQuery, useAxiomMutation } from 'atmx-react';`);
16
+ // ✨ FIX: Auto-import the auth helpers to bind them to the module
17
+ lines.push(
18
+ `import { useAxiomQuery, useAxiomMutation, setAuthToken, clearAuthToken } from 'atmx-react';`,
19
+ );
17
20
  lines.push(`import type { AxiomQueryDef } from 'atmx-react';\n`);
18
21
  }
19
22
 
20
23
  for (const [ns, ir] of Object.entries(multiIr)) {
21
24
  const camelNs = camelCase(ns);
22
- // ✨ FIX: Use an object literal instead of a Class to support React Hooks!
23
25
  lines.push(`export const ${camelNs}Module = {`);
24
26
 
27
+ // ✨ FIX: Safely bind auth tokens using the EXACT namespace string from the TOML file!
28
+ if (isReact) {
29
+ lines.push(` setAuthToken(methodName: string, token: string) {`);
30
+ lines.push(` setAuthToken("${ns}", methodName, token);`);
31
+ lines.push(` },`);
32
+ lines.push(` clearAuthToken(methodName: string) {`);
33
+ lines.push(` clearAuthToken("${ns}", methodName);`);
34
+ lines.push(` },`);
35
+ } else {
36
+ lines.push(` setAuthToken(methodName: string, token: string) {`);
37
+ lines.push(
38
+ ` (window as any).atmx?.setAuthToken("${ns}", methodName, token);`,
39
+ );
40
+ lines.push(` },`);
41
+ lines.push(` clearAuthToken(methodName: string) {`);
42
+ lines.push(
43
+ ` (window as any).atmx?.clearAuthToken("${ns}", methodName);`,
44
+ );
45
+ lines.push(` },`);
46
+ }
47
+
25
48
  const endpointsMap = ir.endpoints || {};
26
49
  const endpoints = Array.isArray(endpointsMap)
27
50
  ? endpointsMap
@@ -33,14 +56,12 @@ export function generateSdk(
33
56
  lines.push(`};\n`);
34
57
  }
35
58
 
36
- // Generate main SDK object
37
59
  lines.push(`export const sdk = {`);
38
60
  for (const ns of Object.keys(multiIr)) {
39
61
  lines.push(` ${camelCase(ns)}: ${camelCase(ns)}Module,`);
40
62
  }
41
63
  lines.push(`};\n`);
42
64
 
43
- // Generate Config
44
65
  lines.push(`export const AxiomDefaultConfig = {`);
45
66
  lines.push(` contracts: {`);
46
67
  for (const ns of Object.keys(multiIr)) {
@@ -66,11 +87,6 @@ function generateEndpointMethod(
66
87
  ? rawParams
67
88
  : Object.values(rawParams);
68
89
 
69
- const argType =
70
- params.length > 0
71
- ? `{ ${params.map((p: any) => `${camelCase(p.name)}${p.isOptional ? "?" : ""}: ${prefixModels(mapTypeToTs(p.typeRef, camelNs))}`).join(", ")} }`
72
- : "void";
73
-
74
90
  const isQuery = ep.method ? ep.method.toUpperCase() === "GET" : true;
75
91
  const rawReturnType = mapTypeToTs(ep.returnType, camelNs);
76
92
  const returnType =
@@ -78,6 +94,34 @@ function generateEndpointMethod(
78
94
  ? rawReturnType
79
95
  : prefixModels(rawReturnType);
80
96
 
97
+ // ✨ FIX: If no parameters are defined, default to accepting an optional Record<string, any>
98
+ // This allows developers to pass undocumented fields (like FastAPI Form data)
99
+ if (params.length === 0) {
100
+ if (isReact) {
101
+ const decLogic = generateLambda(ep.returnType, "fromJson", camelNs);
102
+ return `
103
+ get${pascalCase(ep.name)}Def(args?: Record<string, any>): AxiomQueryDef<${returnType}> {
104
+ return {
105
+ namespace: "${ns}", name: "${ep.name}", endpointId: ${ep.id},
106
+ method: "${ep.method ? ep.method.toUpperCase() : "GET"}", path: "${ep.path}",
107
+ args: args || {}, decoder: ${decLogic}, serializer: (p: any) => p, isStream: ${ep.isStream === true}
108
+ };
109
+ },
110
+ use${pascalCase(ep.name)}${!isQuery ? "Mutation" : ""}(options?: { enabled?: boolean }) {
111
+ ${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));`}
112
+ },`;
113
+ } else {
114
+ return `
115
+ ${camelCase(ep.name)}(args?: Record<string, any>): string {
116
+ const argsStr = args && Object.keys(args).length > 0 ? JSON.stringify(args) : '';
117
+ return \`${ns}.${ep.name}(\${argsStr})\`;
118
+ },`;
119
+ }
120
+ }
121
+
122
+ // Endpoints with explicitly defined parameters
123
+ const argType = `{ ${params.map((p: any) => `${camelCase(p.name)}${p.isOptional ? "?" : ""}: ${prefixModels(mapTypeToTs(p.typeRef, camelNs))}`).join(", ")} }`;
124
+
81
125
  if (isReact) {
82
126
  const bodyParam = params.find(
83
127
  (p: any) => p.source === "body",
@@ -91,32 +135,20 @@ function generateEndpointMethod(
91
135
  : `(p: any) => p`;
92
136
 
93
137
  return `
94
- get${pascalCase(ep.name)}Def(args${params.length > 0 ? "?" : ""}: ${argType === "void" ? "any" : argType}): AxiomQueryDef<${returnType}> {
138
+ get${pascalCase(ep.name)}Def(args?: ${argType}): AxiomQueryDef<${returnType}> {
95
139
  ${payloadLogic}
96
140
  return {
97
- namespace: "${ns}",
98
- name: "${ep.name}",
99
- endpointId: ${ep.id},
100
- method: "${ep.method ? ep.method.toUpperCase() : "GET"}",
101
- path: "${ep.path}",
102
- payload: payload,
103
- args: args || {},
104
- decoder: ${decLogic},
105
- serializer: ${serLogic},
106
- isStream: ${ep.isStream === true}
141
+ namespace: "${ns}", name: "${ep.name}", endpointId: ${ep.id},
142
+ method: "${ep.method ? ep.method.toUpperCase() : "GET"}", path: "${ep.path}",
143
+ payload: payload, args: args || {}, decoder: ${decLogic}, serializer: ${serLogic}, isStream: ${ep.isStream === true}
107
144
  };
108
145
  },
109
-
110
- use${pascalCase(ep.name)}${!isQuery ? "Mutation" : ""}(${isQuery ? `args${params.length > 0 ? "?" : ""}: ${argType === "void" ? "any" : argType}, options?: { enabled?: boolean }` : ""}) {
111
- ${
112
- isQuery
113
- ? `return useAxiomQuery<${returnType}>(this.get${pascalCase(ep.name)}Def(args), options);`
114
- : `return useAxiomMutation<${returnType}, ${argType === "void" ? "void | Record<string,any>" : argType}>((args) => this.get${pascalCase(ep.name)}Def(args));`
115
- }
146
+ use${pascalCase(ep.name)}${!isQuery ? "Mutation" : ""}(args?: ${argType}, options?: { enabled?: boolean }) {
147
+ ${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));`}
116
148
  },`;
117
149
  } else {
118
150
  return `
119
- ${camelCase(ep.name)}(args${params.length > 0 ? "?" : ""}: ${argType === "void" ? "any" : argType}): string {
151
+ ${camelCase(ep.name)}(args?: ${argType}): string {
120
152
  const argsStr = args && Object.keys(args).length > 0 ? JSON.stringify(args) : '';
121
153
  return \`${ns}.${ep.name}(\${argsStr})\`;
122
154
  },`;