@aravinthan_p/appnest-sdk-core 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/appnestBackendLayer/backendLayer.js +27 -0
- package/appnestBackendLayer/loggerInterceptor.js +62 -0
- package/appnestBackendLayer/requestContext.js +18 -0
- package/appnestBackendLayer/requestWrapper.js +149 -0
- package/appnestUtils/ResultData.js +3 -0
- package/index.js +6 -0
- package/package.json +16 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { patchLogging } = require('./loggerInterceptor');
|
|
2
|
+
const { requestHandler } = require('./requestWrapper');
|
|
3
|
+
|
|
4
|
+
console.log("[backendLayer.js] Module loaded");
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const handleServerStart = () => {
|
|
8
|
+
patchLogging(); // ✅ Patch once per cold start
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const handleServerRequest = async ({ requestEvent, requestContext, appBackendServerFile, appBackendServerFolder }) => {
|
|
12
|
+
console.log('🚀 ~ handleServerRequest ~ requestEvent:', requestEvent);
|
|
13
|
+
console.log('🚀 ~ handleServerRequest ~ requestContext:', requestContext);
|
|
14
|
+
try {
|
|
15
|
+
return await requestHandler({ requestEvent, requestContext, appBackendServerFile, appBackendServerFolder });
|
|
16
|
+
} catch (error) {
|
|
17
|
+
return {
|
|
18
|
+
statusCode: 500,
|
|
19
|
+
body: JSON.stringify({ error: 'Internal server error occurred', errorMessage: error.message, errorStack: error.stack }),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
handleServerStart,
|
|
26
|
+
handleServerRequest
|
|
27
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// loggerInterceptor.js
|
|
2
|
+
const { getRequestContext } = require('./requestContext');
|
|
3
|
+
|
|
4
|
+
console.log("[loggerInterceptor.js] Module loaded");
|
|
5
|
+
|
|
6
|
+
let isPatched = false;
|
|
7
|
+
|
|
8
|
+
const patchLogging = () => {
|
|
9
|
+
if (isPatched) return; // avoid re-patching during warm starts
|
|
10
|
+
console.log('Patching the log started');
|
|
11
|
+
isPatched = true;
|
|
12
|
+
|
|
13
|
+
const buildMdcPrefix = () => {
|
|
14
|
+
const { mdc } = getRequestContext() || {};
|
|
15
|
+
if (!mdc || typeof mdc !== 'object') return '';
|
|
16
|
+
const parts = Object.entries(mdc)
|
|
17
|
+
.map(([key, value]) => `${key}:${value ?? '-'}`)
|
|
18
|
+
.join(' ');
|
|
19
|
+
return parts ? `[${parts}]` : '';
|
|
20
|
+
};
|
|
21
|
+
const buildPrefix = (level) => {
|
|
22
|
+
const ts = new Date().toISOString();
|
|
23
|
+
const levelTag = `[${level.toUpperCase()}]`;
|
|
24
|
+
const mdcTag = buildMdcPrefix();
|
|
25
|
+
return `[${ts}] ${levelTag} | MDC: ${mdcTag} | `.trim();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// ---- Patch console methods ----
|
|
29
|
+
const levelMap = {
|
|
30
|
+
log: 'info',
|
|
31
|
+
info: 'info',
|
|
32
|
+
warn: 'warn',
|
|
33
|
+
error: 'error',
|
|
34
|
+
debug: 'debug',
|
|
35
|
+
};
|
|
36
|
+
Object.entries(levelMap).forEach(([method, level]) => {
|
|
37
|
+
const original = console[method];
|
|
38
|
+
console[method] = (...args) => {
|
|
39
|
+
const prefix = buildPrefix(level);
|
|
40
|
+
original(prefix, ...args);
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// --- Patch stdout/stderr for third-party logs ---
|
|
45
|
+
const wrapStream = (stream, level) => {
|
|
46
|
+
const originalWrite = stream.write.bind(stream);
|
|
47
|
+
stream.write = (chunk, encoding, cb) => {
|
|
48
|
+
const prefix = buildPrefix(level);
|
|
49
|
+
const text = chunk.toString();
|
|
50
|
+
const formatted = text.startsWith('[')
|
|
51
|
+
? text
|
|
52
|
+
: `${prefix} ${text}`;
|
|
53
|
+
return originalWrite(formatted, encoding, cb);
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
wrapStream(process.stdout, 'info');
|
|
58
|
+
wrapStream(process.stderr, 'error');
|
|
59
|
+
console.log('Patching the log completed');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = { patchLogging }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// context.js
|
|
2
|
+
const { AsyncLocalStorage } = require('node:async_hooks');
|
|
3
|
+
|
|
4
|
+
const asyncContext = new AsyncLocalStorage();
|
|
5
|
+
|
|
6
|
+
const withRequestContext = ( context, handler) => {
|
|
7
|
+
return asyncContext.run(context, handler);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const getRequestContext = () => {
|
|
11
|
+
const requestContext = asyncContext.getStore();
|
|
12
|
+
return requestContext || {};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
module.exports = {
|
|
16
|
+
withRequestContext,
|
|
17
|
+
getRequestContext
|
|
18
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { v4: uuidv4 } = require('uuid');
|
|
3
|
+
const { withRequestContext } = require('./requestContext');
|
|
4
|
+
const { ResultData } = require('../appnestUtils/ResultData');
|
|
5
|
+
|
|
6
|
+
const getRequestBody = ({ requestEvent }) => {
|
|
7
|
+
let requestBody = null;
|
|
8
|
+
if (requestEvent.body) {
|
|
9
|
+
console.log('🚀 ~ getRequestBody ~ requestEvent.body:', requestEvent.body);
|
|
10
|
+
requestBody = JSON.parse(requestEvent.body);
|
|
11
|
+
} else {
|
|
12
|
+
console.log('🚀 ~ getRequestBody ~ requestEvent:', requestEvent);
|
|
13
|
+
requestBody = requestEvent;
|
|
14
|
+
}
|
|
15
|
+
console.log(JSON.stringify(requestBody, null, 2));
|
|
16
|
+
if (!requestBody) {
|
|
17
|
+
throw new Error('Request body is missing');
|
|
18
|
+
}
|
|
19
|
+
if (!requestBody.appConfig || !requestBody.appConfig.extraPayload) {
|
|
20
|
+
throw new Error('Invalid request body: Missing appConfig.extraPayload');
|
|
21
|
+
}
|
|
22
|
+
console.log('requestBody.appConfig:', JSON.stringify(requestBody.appConfig, null, 2));
|
|
23
|
+
const parentLayerConfigObject =
|
|
24
|
+
requestBody?.appConfig?.extraPayload?.parentLayerConfigObject;
|
|
25
|
+
const eventName = parentLayerConfigObject.event;
|
|
26
|
+
if (!eventName) {
|
|
27
|
+
throw new Error('Invalid request body: Missing event name');
|
|
28
|
+
}
|
|
29
|
+
return requestBody;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const getRequestContextData = ({ requestBody, requestContext }) => {
|
|
33
|
+
try {
|
|
34
|
+
const parentLayerConfigObject =
|
|
35
|
+
requestBody?.appConfig?.extraPayload?.parentLayerConfigObject;
|
|
36
|
+
|
|
37
|
+
let traceId = requestBody?.traceId;
|
|
38
|
+
if (!traceId) {
|
|
39
|
+
console.error('No traceId found in request body. Generating a new one.');
|
|
40
|
+
traceId = `NoOriginTrace-${uuidv4()}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const appFunctionName = parentLayerConfigObject.event;
|
|
44
|
+
const executionId = uuidv4();
|
|
45
|
+
const mdc = {
|
|
46
|
+
traceId,
|
|
47
|
+
appFunctionName,
|
|
48
|
+
executionId,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const contextData = {
|
|
52
|
+
traceId,
|
|
53
|
+
appFunctionName,
|
|
54
|
+
parentLayerConfigObject,
|
|
55
|
+
requestContext,
|
|
56
|
+
mdc,
|
|
57
|
+
};
|
|
58
|
+
console.log('Extracted Context Data:', contextData);
|
|
59
|
+
return contextData;
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error('Error extracting request context data:', error);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const handleAppFunctionResponse = ({ appFunctionResponse }) => {
|
|
67
|
+
if (appFunctionResponse.customAppnestClassFlag) {
|
|
68
|
+
if (appFunctionResponse instanceof ResultData) {
|
|
69
|
+
return {
|
|
70
|
+
statusCode: appFunctionResponse.statusCode,
|
|
71
|
+
body: appFunctionResponse.body
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
return {
|
|
76
|
+
statusCode: 200,
|
|
77
|
+
body: appFunctionResponse
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const executeAppFunction = async ({ requestBody, appBackendServerFile, appBackendServerFolder }) => {
|
|
83
|
+
console.log('🚀 ~ Current working directory:', process.cwd());
|
|
84
|
+
const serverfolderPath = appBackendServerFolder ? appBackendServerFolder : process.cwd();
|
|
85
|
+
console.log('🚀 ~ serverfolderPath:', serverfolderPath);
|
|
86
|
+
const serverPath = path.join(serverfolderPath, appBackendServerFile);
|
|
87
|
+
console.log('🚀 ~ serverPath:', serverPath);
|
|
88
|
+
const appServer = require(serverPath);
|
|
89
|
+
console.log('Loaded appServer from path :', serverPath);
|
|
90
|
+
const eventName =
|
|
91
|
+
requestBody.appConfig.extraPayload.parentLayerConfigObject.event;
|
|
92
|
+
if (typeof appServer[eventName] === 'function') {
|
|
93
|
+
try {
|
|
94
|
+
const appFunctionResponseData = await appServer[eventName]({
|
|
95
|
+
payload: requestBody.payload,
|
|
96
|
+
});
|
|
97
|
+
return appFunctionResponseData;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error(`Error executing app function - ${eventName}:`, error);
|
|
100
|
+
console.error(error.message);
|
|
101
|
+
console.error(error.stack);
|
|
102
|
+
return new ResultData({
|
|
103
|
+
body: { error: 'Internal server error occurred', errorMessage: error.message, errorStack: error.stack },
|
|
104
|
+
statusCode: 500,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
console.error(
|
|
109
|
+
'Invalid event or handler not found:',
|
|
110
|
+
eventName
|
|
111
|
+
);
|
|
112
|
+
return new ResultData({
|
|
113
|
+
body: { error: 'Invalid event or handler not found' },
|
|
114
|
+
statusCode: 500,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const requestHandler = async ({ requestEvent, requestContext, appBackendServerFile, appBackendServerFolder }) => {
|
|
120
|
+
console.log('Request Event:', requestEvent);
|
|
121
|
+
console.log('RequestContext:', requestContext);
|
|
122
|
+
const requestBody = getRequestBody({ requestEvent });
|
|
123
|
+
const contextData = getRequestContextData({ requestBody, requestContext });
|
|
124
|
+
const ctx = {
|
|
125
|
+
...contextData,
|
|
126
|
+
};
|
|
127
|
+
console.log('Final Request Context (ctx):', ctx);
|
|
128
|
+
console.log(JSON.stringify(ctx));
|
|
129
|
+
return withRequestContext(ctx, async () => {
|
|
130
|
+
try {
|
|
131
|
+
const response = await executeAppFunction({
|
|
132
|
+
requestBody,
|
|
133
|
+
appBackendServerFile,
|
|
134
|
+
appBackendServerFolder
|
|
135
|
+
});
|
|
136
|
+
return handleAppFunctionResponse({ appFunctionResponse: response });
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error('Error executing app function:', error);
|
|
139
|
+
return {
|
|
140
|
+
statusCode: 500,
|
|
141
|
+
body: JSON.stringify({ error: 'Internal server error occurred', errorMessage: error.message, errorStack: error.stack }),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
module.exports = {
|
|
148
|
+
requestHandler,
|
|
149
|
+
};
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aravinthan_p/appnest-sdk-core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [],
|
|
9
|
+
"author": "",
|
|
10
|
+
"license": "ISC",
|
|
11
|
+
"description": "",
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"uuid": "^9.0.0",
|
|
14
|
+
"appnest-sdk-common": "file:/Users/aravinthanp/Desktop/Appnest/Coding Worspace/sparrow-sdk/SDK-V2-CodeBase/sdk-layer/appnest-sdk-common"
|
|
15
|
+
}
|
|
16
|
+
}
|