@ratio-mcp/dev-server 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/dist/api/developer.d.ts +13 -0
- package/dist/api/developer.d.ts.map +1 -0
- package/dist/api/developer.js +66 -0
- package/dist/api/developer.js.map +1 -0
- package/dist/api/oauth.d.ts +36 -0
- package/dist/api/oauth.d.ts.map +1 -0
- package/dist/api/oauth.js +77 -0
- package/dist/api/oauth.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +57 -0
- package/dist/server.js.map +1 -0
- package/dist/store/requirements-store.d.ts +8 -0
- package/dist/store/requirements-store.d.ts.map +1 -0
- package/dist/store/requirements-store.js +67 -0
- package/dist/store/requirements-store.js.map +1 -0
- package/dist/store/token-store.d.ts +12 -0
- package/dist/store/token-store.d.ts.map +1 -0
- package/dist/store/token-store.js +94 -0
- package/dist/store/token-store.js.map +1 -0
- package/dist/templates/backend/.env.example +20 -0
- package/dist/templates/backend/nest-cli.json +5 -0
- package/dist/templates/backend/package.json +26 -0
- package/dist/templates/backend/src/app.module.ts +10 -0
- package/dist/templates/backend/src/main.ts +12 -0
- package/dist/templates/backend/tsconfig.json +21 -0
- package/dist/templates/frontend/.env.example +6 -0
- package/dist/templates/frontend/index.html +13 -0
- package/dist/templates/frontend/package.json +24 -0
- package/dist/templates/frontend/src/App.tsx +32 -0
- package/dist/templates/frontend/src/components/Layout.tsx +53 -0
- package/dist/templates/frontend/src/context/AuthContext.tsx +59 -0
- package/dist/templates/frontend/src/index.css +48 -0
- package/dist/templates/frontend/src/main.tsx +16 -0
- package/dist/templates/frontend/src/pages/Callback.tsx +53 -0
- package/dist/templates/frontend/src/pages/Dashboard.tsx +24 -0
- package/dist/templates/frontend/src/pages/Login.tsx +42 -0
- package/dist/templates/frontend/src/services/api.ts +48 -0
- package/dist/templates/frontend/tsconfig.json +21 -0
- package/dist/templates/frontend/vite.config.ts +15 -0
- package/dist/tools/app-management.d.ts +3 -0
- package/dist/tools/app-management.d.ts.map +1 -0
- package/dist/tools/app-management.js +132 -0
- package/dist/tools/app-management.js.map +1 -0
- package/dist/tools/auth.d.ts +3 -0
- package/dist/tools/auth.d.ts.map +1 -0
- package/dist/tools/auth.js +164 -0
- package/dist/tools/auth.js.map +1 -0
- package/dist/tools/build.d.ts +3 -0
- package/dist/tools/build.d.ts.map +1 -0
- package/dist/tools/build.js +178 -0
- package/dist/tools/build.js.map +1 -0
- package/dist/tools/codegen.d.ts +3 -0
- package/dist/tools/codegen.d.ts.map +1 -0
- package/dist/tools/codegen.js +315 -0
- package/dist/tools/codegen.js.map +1 -0
- package/dist/tools/developer-auth.d.ts +3 -0
- package/dist/tools/developer-auth.d.ts.map +1 -0
- package/dist/tools/developer-auth.js +87 -0
- package/dist/tools/developer-auth.js.map +1 -0
- package/dist/tools/index.d.ts +16 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +27 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/lifecycle.d.ts +3 -0
- package/dist/tools/lifecycle.d.ts.map +1 -0
- package/dist/tools/lifecycle.js +95 -0
- package/dist/tools/lifecycle.js.map +1 -0
- package/dist/tools/requirements.d.ts +3 -0
- package/dist/tools/requirements.d.ts.map +1 -0
- package/dist/tools/requirements.js +169 -0
- package/dist/tools/requirements.js.map +1 -0
- package/dist/tools/scaffold.d.ts +3 -0
- package/dist/tools/scaffold.d.ts.map +1 -0
- package/dist/tools/scaffold.js +209 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/tools/submission.d.ts +3 -0
- package/dist/tools/submission.d.ts.map +1 -0
- package/dist/tools/submission.js +138 -0
- package/dist/tools/submission.js.map +1 -0
- package/dist/utils/errors.d.ts +34 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +81 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +29 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +74 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/zod-to-json.d.ts +7 -0
- package/dist/utils/zod-to-json.d.ts.map +1 -0
- package/dist/utils/zod-to-json.js +63 -0
- package/dist/utils/zod-to-json.js.map +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type AxiosRequestConfig } from 'axios';
|
|
2
|
+
export declare function setDeveloperCredentials(token: string, id: string): void;
|
|
3
|
+
export declare function getDeveloperToken(): string;
|
|
4
|
+
export declare function getDeveloperId(): string | null;
|
|
5
|
+
export interface DeveloperApiOptions {
|
|
6
|
+
skipAuth?: boolean;
|
|
7
|
+
axiosConfig?: Partial<AxiosRequestConfig>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Make a request to the Developer Dashboard API
|
|
11
|
+
*/
|
|
12
|
+
export declare function developerApiRequest<T>(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', endpoint: string, data?: unknown, options?: DeveloperApiOptions): Promise<T>;
|
|
13
|
+
//# sourceMappingURL=developer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"developer.d.ts","sourceRoot":"","sources":["../../src/api/developer.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAWvD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAGvE;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAO1C;AAED,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAE9C;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC3C;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,EACnD,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,CAAC,CAAC,CA+CZ"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { RATIO_API_BASE_URL } from '@ratio-mcp/shared';
|
|
3
|
+
import { AuthenticationError, RatioAPIError, extractAxiosMessage } from '../utils/errors.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
/**
|
|
6
|
+
* In-memory developer credentials (set by developer_login)
|
|
7
|
+
*/
|
|
8
|
+
let developerToken = null;
|
|
9
|
+
let developerId = null;
|
|
10
|
+
export function setDeveloperCredentials(token, id) {
|
|
11
|
+
developerToken = token;
|
|
12
|
+
developerId = id;
|
|
13
|
+
}
|
|
14
|
+
export function getDeveloperToken() {
|
|
15
|
+
if (!developerToken) {
|
|
16
|
+
throw new AuthenticationError('Developer token is required. Please use developer_login first.');
|
|
17
|
+
}
|
|
18
|
+
return developerToken;
|
|
19
|
+
}
|
|
20
|
+
export function getDeveloperId() {
|
|
21
|
+
return developerId;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Make a request to the Developer Dashboard API
|
|
25
|
+
*/
|
|
26
|
+
export async function developerApiRequest(method, endpoint, data, options = {}) {
|
|
27
|
+
const url = `${RATIO_API_BASE_URL}/api/v1${endpoint}`;
|
|
28
|
+
const headers = {
|
|
29
|
+
'Content-Type': 'application/json',
|
|
30
|
+
Accept: 'application/json',
|
|
31
|
+
...(options.axiosConfig?.headers ?? {}),
|
|
32
|
+
};
|
|
33
|
+
if (!options.skipAuth) {
|
|
34
|
+
const token = getDeveloperToken();
|
|
35
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
36
|
+
}
|
|
37
|
+
logger.apiRequest(method, url, data);
|
|
38
|
+
const startTime = Date.now();
|
|
39
|
+
try {
|
|
40
|
+
const response = await axios({
|
|
41
|
+
method,
|
|
42
|
+
url,
|
|
43
|
+
data,
|
|
44
|
+
...options.axiosConfig,
|
|
45
|
+
headers,
|
|
46
|
+
});
|
|
47
|
+
const duration = Date.now() - startTime;
|
|
48
|
+
logger.apiResponse(method, url, response.status, duration);
|
|
49
|
+
return response.data;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
const duration = Date.now() - startTime;
|
|
53
|
+
if (axios.isAxiosError(error)) {
|
|
54
|
+
const status = error.response?.status;
|
|
55
|
+
const message = extractAxiosMessage(error);
|
|
56
|
+
logger.apiError(method, url, status, duration, error.response?.data);
|
|
57
|
+
if (status === 401) {
|
|
58
|
+
throw new AuthenticationError('Developer token is invalid or expired. Please login again.', error.response?.data);
|
|
59
|
+
}
|
|
60
|
+
throw new RatioAPIError(message, endpoint, method, status, error.response?.data);
|
|
61
|
+
}
|
|
62
|
+
logger.apiError(method, url, undefined, duration, { message: String(error) });
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=developer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"developer.js","sourceRoot":"","sources":["../../src/api/developer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAkC,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC7F,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;GAEG;AACH,IAAI,cAAc,GAAkB,IAAI,CAAC;AACzC,IAAI,WAAW,GAAkB,IAAI,CAAC;AAEtC,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAE,EAAU;IAC/D,cAAc,GAAG,KAAK,CAAC;IACvB,WAAW,GAAG,EAAE,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,mBAAmB,CAC3B,gEAAgE,CACjE,CAAC;IACJ,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,WAAW,CAAC;AACrB,CAAC;AAOD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAmD,EACnD,QAAgB,EAChB,IAAc,EACd,UAA+B,EAAE;IAEjC,MAAM,GAAG,GAAG,GAAG,kBAAkB,UAAU,QAAQ,EAAE,CAAC;IAEtD,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,MAAM,EAAE,kBAAkB;QAC1B,GAAG,CAAE,OAAO,CAAC,WAAW,EAAE,OAAkC,IAAI,EAAE,CAAC;KACpE,CAAC;IAEF,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,iBAAiB,EAAE,CAAC;QAClC,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC;YAC3B,MAAM;YACN,GAAG;YACH,IAAI;YACJ,GAAG,OAAO,CAAC,WAAW;YACtB,OAAO;SACR,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC3D,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC;YACtC,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAErE,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAM,IAAI,mBAAmB,CAC3B,4DAA4D,EAC5D,KAAK,CAAC,QAAQ,EAAE,IAAI,CACrB,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9E,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
interface AuthorizeResponse {
|
|
2
|
+
success: boolean;
|
|
3
|
+
message: string;
|
|
4
|
+
data: {
|
|
5
|
+
code: string;
|
|
6
|
+
redirectUri: string;
|
|
7
|
+
expiresAt: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
interface TokenResponse {
|
|
11
|
+
access_token: string;
|
|
12
|
+
token_type: string;
|
|
13
|
+
expires_in: number;
|
|
14
|
+
refresh_token: string;
|
|
15
|
+
scope: string;
|
|
16
|
+
merchant_id: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function requestAuthorization(params: {
|
|
19
|
+
clientId: string;
|
|
20
|
+
merchantId: string;
|
|
21
|
+
redirectUri: string;
|
|
22
|
+
scopes: string[];
|
|
23
|
+
}): Promise<AuthorizeResponse>;
|
|
24
|
+
export declare function exchangeCodeForToken(params: {
|
|
25
|
+
code: string;
|
|
26
|
+
clientId: string;
|
|
27
|
+
clientSecret: string;
|
|
28
|
+
redirectUri: string;
|
|
29
|
+
}): Promise<TokenResponse>;
|
|
30
|
+
export declare function refreshToken(params: {
|
|
31
|
+
refreshToken: string;
|
|
32
|
+
clientId: string;
|
|
33
|
+
clientSecret: string;
|
|
34
|
+
}): Promise<TokenResponse>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/api/oauth.ts"],"names":[],"mappings":"AAcA,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,UAAU,aAAa;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqB7B;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,aAAa,CAAC,CAyBzB;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,aAAa,CAAC,CAwBzB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { RATIO_API_BASE_URL, OAUTH_BASE_PATH } from '@ratio-mcp/shared';
|
|
3
|
+
import { handleAxiosError } from '../utils/errors.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
const OAUTH_HEADERS = {
|
|
6
|
+
'Content-Type': 'application/json',
|
|
7
|
+
Accept: '*/*',
|
|
8
|
+
};
|
|
9
|
+
function getOAuthUrl() {
|
|
10
|
+
return `${RATIO_API_BASE_URL}${OAUTH_BASE_PATH}`;
|
|
11
|
+
}
|
|
12
|
+
export async function requestAuthorization(params) {
|
|
13
|
+
const url = `${getOAuthUrl()}/authorize`;
|
|
14
|
+
const body = {
|
|
15
|
+
clientId: params.clientId,
|
|
16
|
+
redirectUri: params.redirectUri,
|
|
17
|
+
merchantId: params.merchantId,
|
|
18
|
+
scopes: params.scopes,
|
|
19
|
+
};
|
|
20
|
+
logger.info(`API_REQ: → POST ${url} | clientId: ${params.clientId}, merchantId: ${params.merchantId}, scopes: [${params.scopes.join(', ')}]`);
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
try {
|
|
23
|
+
const response = await axios.post(url, body, { headers: OAUTH_HEADERS });
|
|
24
|
+
const duration = Date.now() - startTime;
|
|
25
|
+
logger.info(`API_RES: ← POST ${url} | ${response.status} | ${duration}ms`);
|
|
26
|
+
return response.data;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
const duration = Date.now() - startTime;
|
|
30
|
+
logger.error(`API_ERR: ✗ POST ${url} | ${duration}ms`, error);
|
|
31
|
+
handleAxiosError(error, '/oauth/authorize', 'POST');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function exchangeCodeForToken(params) {
|
|
35
|
+
const url = `${getOAuthUrl()}/token`;
|
|
36
|
+
logger.info(`API_REQ: → POST ${url} | grant_type: authorization_code, clientId: ${params.clientId}`);
|
|
37
|
+
const startTime = Date.now();
|
|
38
|
+
try {
|
|
39
|
+
const response = await axios.post(url, {
|
|
40
|
+
grant_type: 'authorization_code',
|
|
41
|
+
code: params.code,
|
|
42
|
+
clientId: params.clientId,
|
|
43
|
+
clientSecret: params.clientSecret,
|
|
44
|
+
redirectUri: params.redirectUri,
|
|
45
|
+
}, { headers: OAUTH_HEADERS });
|
|
46
|
+
const duration = Date.now() - startTime;
|
|
47
|
+
logger.info(`API_RES: ← POST ${url} | ${response.status} | ${duration}ms | token_type: ${response.data.token_type}`);
|
|
48
|
+
return response.data;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
const duration = Date.now() - startTime;
|
|
52
|
+
logger.error(`API_ERR: ✗ POST ${url} | ${duration}ms`, error);
|
|
53
|
+
handleAxiosError(error, '/oauth/token', 'POST');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export async function refreshToken(params) {
|
|
57
|
+
const url = `${getOAuthUrl()}/token`;
|
|
58
|
+
logger.info(`API_REQ: → POST ${url} | grant_type: refresh_token, clientId: ${params.clientId}`);
|
|
59
|
+
const startTime = Date.now();
|
|
60
|
+
try {
|
|
61
|
+
const response = await axios.post(url, {
|
|
62
|
+
grant_type: 'refresh_token',
|
|
63
|
+
refresh_token: params.refreshToken,
|
|
64
|
+
clientId: params.clientId,
|
|
65
|
+
clientSecret: params.clientSecret,
|
|
66
|
+
}, { headers: OAUTH_HEADERS });
|
|
67
|
+
const duration = Date.now() - startTime;
|
|
68
|
+
logger.info(`API_RES: ← POST ${url} | ${response.status} | ${duration}ms`);
|
|
69
|
+
return response.data;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const duration = Date.now() - startTime;
|
|
73
|
+
logger.error(`API_ERR: ✗ POST ${url} | ${duration}ms`, error);
|
|
74
|
+
handleAxiosError(error, '/oauth/token', 'POST');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/api/oauth.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { createDevServer } from './server.js';
|
|
4
|
+
import { logger } from './utils/logger.js';
|
|
5
|
+
async function main() {
|
|
6
|
+
logger.info('Starting Ratio Dev MCP Server...');
|
|
7
|
+
const server = createDevServer();
|
|
8
|
+
const transport = new StdioServerTransport();
|
|
9
|
+
await server.connect(transport);
|
|
10
|
+
logger.info('Ratio Dev MCP Server is running on stdio');
|
|
11
|
+
}
|
|
12
|
+
main().catch((error) => {
|
|
13
|
+
logger.error('Fatal error:', error);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;AAC1D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE;;GAEG;AACH,wBAAgB,eAAe,IAAI,SAAS,CA2D3C"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { DEV_SERVER_NAME, DEV_SERVER_VERSION } from '@ratio-mcp/shared';
|
|
3
|
+
import { allDevTools } from './tools/index.js';
|
|
4
|
+
import { logger } from './utils/logger.js';
|
|
5
|
+
/**
|
|
6
|
+
* Create and configure the Ratio Dev MCP Server
|
|
7
|
+
*/
|
|
8
|
+
export function createDevServer() {
|
|
9
|
+
const server = new McpServer({
|
|
10
|
+
name: DEV_SERVER_NAME,
|
|
11
|
+
version: DEV_SERVER_VERSION,
|
|
12
|
+
});
|
|
13
|
+
// Register all tools
|
|
14
|
+
for (const tool of allDevTools) {
|
|
15
|
+
// Pass Zod shape directly — MCP SDK handles Zod-to-JSON conversion internally
|
|
16
|
+
const shape = tool.inputSchema.shape;
|
|
17
|
+
server.tool(tool.name, tool.description, shape, async (args) => {
|
|
18
|
+
logger.toolCall(tool.name, args);
|
|
19
|
+
const startTime = Date.now();
|
|
20
|
+
try {
|
|
21
|
+
const result = await tool.handler(args);
|
|
22
|
+
const duration = Date.now() - startTime;
|
|
23
|
+
logger.toolResult(tool.name, duration, result);
|
|
24
|
+
return {
|
|
25
|
+
content: [
|
|
26
|
+
{
|
|
27
|
+
type: 'text',
|
|
28
|
+
text: JSON.stringify(result, null, 2),
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
const duration = Date.now() - startTime;
|
|
35
|
+
logger.toolError(tool.name, duration, error);
|
|
36
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: 'text',
|
|
41
|
+
text: JSON.stringify({
|
|
42
|
+
error: true,
|
|
43
|
+
message,
|
|
44
|
+
tool: tool.name,
|
|
45
|
+
}, null, 2),
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
isError: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
logger.debug(`Registered tool: ${tool.name}`);
|
|
53
|
+
}
|
|
54
|
+
logger.info(`${DEV_SERVER_NAME} initialized with ${allDevTools.length} tools`);
|
|
55
|
+
return server;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,kBAAkB;KAC5B,CAAC,CAAC;IAEH,qBAAqB;IACrB,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,8EAA8E;QAC9E,MAAM,KAAK,GAAI,IAAI,CAAC,WAA0C,CAAC,KAAK,CAAC;QAErE,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,WAAW,EAChB,KAAK,EACL,KAAK,EAAE,IAA6B,EAAE,EAAE;YACtC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAE7B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;gBACxC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAE/C,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;yBACtC;qBACF;iBACF,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;gBACxC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAE7C,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACnB,KAAK,EAAE,IAAI;gCACX,OAAO;gCACP,IAAI,EAAE,IAAI,CAAC,IAAI;6BAChB,EAAE,IAAI,EAAE,CAAC,CAAC;yBACZ;qBACF;oBACD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;QACH,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,oBAAoB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,qBAAqB,WAAW,CAAC,MAAM,QAAQ,CAAC,CAAC;IAC/E,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AppRequirements } from '@ratio-mcp/shared';
|
|
2
|
+
export declare function saveRequirements(appId: string, requirements: AppRequirements): void;
|
|
3
|
+
export declare function getRequirements(appId: string): AppRequirements | undefined;
|
|
4
|
+
export declare function getAllRequirements(): Record<string, AppRequirements>;
|
|
5
|
+
export declare function getRequirementsByClientId(clientId: string): AppRequirements | undefined;
|
|
6
|
+
export declare function updateRequirementsField(appId: string, updates: Partial<Pick<AppRequirements, 'project_path' | 'client_id'>>): boolean;
|
|
7
|
+
export declare function deleteRequirements(appId: string): boolean;
|
|
8
|
+
//# sourceMappingURL=requirements-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements-store.d.ts","sourceRoot":"","sources":["../../src/store/requirements-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAgCzD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,GAAG,IAAI,CAMnF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAE1E;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAEpE;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAGvF;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,cAAc,GAAG,WAAW,CAAC,CAAC,GACpE,OAAO,CAaT;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAQzD"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { STORE_DIR, REQUIREMENTS_FILE } from '@ratio-mcp/shared';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
function ensureStoreDir() {
|
|
5
|
+
if (!existsSync(STORE_DIR)) {
|
|
6
|
+
mkdirSync(STORE_DIR, { recursive: true });
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function readStore() {
|
|
10
|
+
try {
|
|
11
|
+
if (!existsSync(REQUIREMENTS_FILE)) {
|
|
12
|
+
return { version: 1, requirements: {} };
|
|
13
|
+
}
|
|
14
|
+
const raw = readFileSync(REQUIREMENTS_FILE, 'utf-8');
|
|
15
|
+
return JSON.parse(raw);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
logger.warn('Failed to read requirements store, starting fresh');
|
|
19
|
+
return { version: 1, requirements: {} };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function writeStore(store) {
|
|
23
|
+
ensureStoreDir();
|
|
24
|
+
writeFileSync(REQUIREMENTS_FILE, JSON.stringify(store, null, 2), 'utf-8');
|
|
25
|
+
}
|
|
26
|
+
export function saveRequirements(appId, requirements) {
|
|
27
|
+
const store = readStore();
|
|
28
|
+
requirements.updated_at = new Date().toISOString();
|
|
29
|
+
store.requirements[appId] = requirements;
|
|
30
|
+
writeStore(store);
|
|
31
|
+
logger.info(`Requirements saved for app_id: ${appId}`);
|
|
32
|
+
}
|
|
33
|
+
export function getRequirements(appId) {
|
|
34
|
+
return readStore().requirements[appId];
|
|
35
|
+
}
|
|
36
|
+
export function getAllRequirements() {
|
|
37
|
+
return readStore().requirements;
|
|
38
|
+
}
|
|
39
|
+
export function getRequirementsByClientId(clientId) {
|
|
40
|
+
const store = readStore();
|
|
41
|
+
return Object.values(store.requirements).find((r) => r.client_id === clientId);
|
|
42
|
+
}
|
|
43
|
+
export function updateRequirementsField(appId, updates) {
|
|
44
|
+
const store = readStore();
|
|
45
|
+
const existing = store.requirements[appId];
|
|
46
|
+
if (!existing)
|
|
47
|
+
return false;
|
|
48
|
+
if (updates.project_path !== undefined)
|
|
49
|
+
existing.project_path = updates.project_path;
|
|
50
|
+
if (updates.client_id !== undefined)
|
|
51
|
+
existing.client_id = updates.client_id;
|
|
52
|
+
existing.updated_at = new Date().toISOString();
|
|
53
|
+
store.requirements[appId] = existing;
|
|
54
|
+
writeStore(store);
|
|
55
|
+
logger.info(`Requirements updated for app_id: ${appId}`);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
export function deleteRequirements(appId) {
|
|
59
|
+
const store = readStore();
|
|
60
|
+
if (store.requirements[appId]) {
|
|
61
|
+
delete store.requirements[appId];
|
|
62
|
+
writeStore(store);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=requirements-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements-store.js","sourceRoot":"","sources":["../../src/store/requirements-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { StoredToken } from '@ratio-mcp/shared';
|
|
2
|
+
export declare function saveToken(clientId: string, token: StoredToken): void;
|
|
3
|
+
export declare function getToken(clientId: string): StoredToken | undefined;
|
|
4
|
+
export declare function getLatestToken(): StoredToken | undefined;
|
|
5
|
+
export declare function getAllTokens(): Record<string, StoredToken>;
|
|
6
|
+
export declare function removeToken(clientId: string): boolean;
|
|
7
|
+
export declare function isTokenExpired(token: StoredToken, bufferSeconds?: number): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Write token values into an existing backend .env file
|
|
10
|
+
*/
|
|
11
|
+
export declare function writeTokenToScaffoldEnv(envPath: string, token: StoredToken): void;
|
|
12
|
+
//# sourceMappingURL=token-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/store/token-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAiCrD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAKpE;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAGlE;AAED,wBAAgB,cAAc,IAAI,WAAW,GAAG,SAAS,CAOxD;AAED,wBAAgB,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAE1D;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,aAAa,SAAM,GAAG,OAAO,CAI/E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CA0BjF"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { STORE_DIR, TOKENS_FILE } from '@ratio-mcp/shared';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
function ensureStoreDir() {
|
|
5
|
+
if (!existsSync(STORE_DIR)) {
|
|
6
|
+
mkdirSync(STORE_DIR, { recursive: true });
|
|
7
|
+
logger.info(`Created store directory: ${STORE_DIR}`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function readStore() {
|
|
11
|
+
try {
|
|
12
|
+
if (!existsSync(TOKENS_FILE)) {
|
|
13
|
+
return { version: 1, tokens: {} };
|
|
14
|
+
}
|
|
15
|
+
const raw = readFileSync(TOKENS_FILE, 'utf-8');
|
|
16
|
+
return JSON.parse(raw);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
logger.warn('Failed to read token store, starting fresh');
|
|
20
|
+
return { version: 1, tokens: {} };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function writeStore(store) {
|
|
24
|
+
ensureStoreDir();
|
|
25
|
+
writeFileSync(TOKENS_FILE, JSON.stringify(store, null, 2), 'utf-8');
|
|
26
|
+
}
|
|
27
|
+
export function saveToken(clientId, token) {
|
|
28
|
+
const store = readStore();
|
|
29
|
+
store.tokens[clientId] = token;
|
|
30
|
+
writeStore(store);
|
|
31
|
+
logger.info(`Token saved for client_id: ${clientId}`);
|
|
32
|
+
}
|
|
33
|
+
export function getToken(clientId) {
|
|
34
|
+
const store = readStore();
|
|
35
|
+
return store.tokens[clientId];
|
|
36
|
+
}
|
|
37
|
+
export function getLatestToken() {
|
|
38
|
+
const store = readStore();
|
|
39
|
+
const tokens = Object.values(store.tokens);
|
|
40
|
+
if (tokens.length === 0)
|
|
41
|
+
return undefined;
|
|
42
|
+
return tokens.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0];
|
|
43
|
+
}
|
|
44
|
+
export function getAllTokens() {
|
|
45
|
+
return readStore().tokens;
|
|
46
|
+
}
|
|
47
|
+
export function removeToken(clientId) {
|
|
48
|
+
const store = readStore();
|
|
49
|
+
if (store.tokens[clientId]) {
|
|
50
|
+
delete store.tokens[clientId];
|
|
51
|
+
writeStore(store);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
export function isTokenExpired(token, bufferSeconds = 300) {
|
|
57
|
+
if (!token.expires_at)
|
|
58
|
+
return false;
|
|
59
|
+
const expiresAt = new Date(token.expires_at).getTime();
|
|
60
|
+
return Date.now() + bufferSeconds * 1000 >= expiresAt;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Write token values into an existing backend .env file
|
|
64
|
+
*/
|
|
65
|
+
export function writeTokenToScaffoldEnv(envPath, token) {
|
|
66
|
+
try {
|
|
67
|
+
if (!existsSync(envPath)) {
|
|
68
|
+
logger.warn(`Backend .env not found at: ${envPath}`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
let content = readFileSync(envPath, 'utf-8');
|
|
72
|
+
const replacements = {
|
|
73
|
+
RATIO_ACCESS_TOKEN: token.access_token,
|
|
74
|
+
RATIO_REFRESH_TOKEN: token.refresh_token,
|
|
75
|
+
RATIO_MERCHANT_ID: token.merchant_id,
|
|
76
|
+
RATIO_SCOPES: token.scopes.join(','),
|
|
77
|
+
};
|
|
78
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
79
|
+
const regex = new RegExp(`^${key}=.*$`, 'm');
|
|
80
|
+
if (regex.test(content)) {
|
|
81
|
+
content = content.replace(regex, `${key}=${value}`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
content += `\n${key}=${value}`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
writeFileSync(envPath, content, 'utf-8');
|
|
88
|
+
logger.info(`Token injected into: ${envPath}`);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
logger.error(`Failed to write token to .env: ${envPath}`, err);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=token-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../src/store/token-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Ratio App Backend Configuration
|
|
2
|
+
PORT=3000
|
|
3
|
+
NODE_ENV=development
|
|
4
|
+
|
|
5
|
+
# Ratio App Credentials
|
|
6
|
+
RATIO_APP_ID=your_app_id
|
|
7
|
+
RATIO_APP_SECRET=your_app_secret
|
|
8
|
+
RATIO_REDIRECT_URI=http://localhost:3000/auth/callback
|
|
9
|
+
RATIO_API_BASE_URL=https://dev-os-ecosystem.dev.gokwik.io
|
|
10
|
+
RATIO_API_VERSION=v1
|
|
11
|
+
|
|
12
|
+
# OAuth Tokens (auto-filled by MCP after OAuth flow)
|
|
13
|
+
RATIO_ACCESS_TOKEN=
|
|
14
|
+
RATIO_REFRESH_TOKEN=
|
|
15
|
+
RATIO_MERCHANT_ID=
|
|
16
|
+
RATIO_SCOPES=
|
|
17
|
+
|
|
18
|
+
# JWT
|
|
19
|
+
JWT_SECRET=your_jwt_secret_change_this
|
|
20
|
+
JWT_EXPIRES_IN=7d
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ratio-app-backend",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "nest build",
|
|
7
|
+
"start": "nest start",
|
|
8
|
+
"start:dev": "nest start --watch",
|
|
9
|
+
"start:prod": "node dist/main"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@nestjs/common": "^10.3.0",
|
|
13
|
+
"@nestjs/core": "^10.3.0",
|
|
14
|
+
"@nestjs/platform-express": "^10.3.0",
|
|
15
|
+
"@nestjs/config": "^3.1.0",
|
|
16
|
+
"reflect-metadata": "^0.1.14",
|
|
17
|
+
"rxjs": "^7.8.1",
|
|
18
|
+
"axios": "^1.6.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@nestjs/cli": "^10.3.0",
|
|
22
|
+
"@types/express": "^4.17.21",
|
|
23
|
+
"@types/node": "^20.10.0",
|
|
24
|
+
"typescript": "^5.3.0"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { ConfigModule } from '@nestjs/config';
|
|
3
|
+
|
|
4
|
+
@Module({
|
|
5
|
+
imports: [
|
|
6
|
+
ConfigModule.forRoot({ isGlobal: true }),
|
|
7
|
+
// Resource modules will be added here by generate_api_routes
|
|
8
|
+
],
|
|
9
|
+
})
|
|
10
|
+
export class AppModule {}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NestFactory } from '@nestjs/core';
|
|
2
|
+
import { AppModule } from './app.module';
|
|
3
|
+
|
|
4
|
+
async function bootstrap() {
|
|
5
|
+
const app = await NestFactory.create(AppModule);
|
|
6
|
+
app.enableCors();
|
|
7
|
+
|
|
8
|
+
const port = process.env.PORT || 3000;
|
|
9
|
+
await app.listen(port);
|
|
10
|
+
console.log(`Ratio app backend running on http://localhost:${port}`);
|
|
11
|
+
}
|
|
12
|
+
bootstrap();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "commonjs",
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"removeComments": true,
|
|
6
|
+
"emitDecoratorMetadata": true,
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"allowSyntheticDefaultImports": true,
|
|
9
|
+
"target": "ES2021",
|
|
10
|
+
"sourceMap": true,
|
|
11
|
+
"outDir": "./dist",
|
|
12
|
+
"baseUrl": "./",
|
|
13
|
+
"incremental": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"strictNullChecks": false,
|
|
16
|
+
"noImplicitAny": false,
|
|
17
|
+
"strictBindCallApply": false,
|
|
18
|
+
"forceConsistentCasingInFileNames": false,
|
|
19
|
+
"noFallthroughCasesInSwitch": false
|
|
20
|
+
}
|
|
21
|
+
}
|