seishiro 0.1.90-dev → 0.2.1-release
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/README.md +6 -6
- package/cjs/index.js +1 -1
- package/cjs/lib/actions.js +1 -1
- package/cjs/lib/message.js +1 -1
- package/cjs/lib/policy.js +1 -1
- package/cjs/lib/registry.js +1 -1
- package/cjs/types/actions.types.js +1 -0
- package/cjs/utils/extract-lang.js +1 -1
- package/esm/index.d.ts +4 -4
- package/esm/index.js +1 -1
- package/esm/lib/actions.d.ts +43 -42
- package/esm/lib/actions.js +1 -1
- package/esm/lib/message.d.ts +2 -2
- package/esm/lib/message.js +1 -1
- package/esm/lib/policy.d.ts +16 -20
- package/esm/lib/policy.js +1 -1
- package/esm/lib/registry.d.ts +1 -1
- package/esm/lib/registry.js +1 -1
- package/esm/types/actions.types.d.ts +6 -0
- package/esm/types/actions.types.js +1 -0
- package/esm/types/message.type.d.ts +2 -6
- package/esm/types/registry.type.d.ts +8 -3
- package/esm/utils/extract-lang.d.ts +1 -1
- package/esm/utils/extract-lang.js +1 -1
- package/package.json +14 -1
- package/cjs/constants/message.d.ts +0 -1
- package/cjs/constants/registry.d.ts +0 -3
- package/cjs/index.d.ts +0 -4
- package/cjs/lib/actions.d.ts +0 -178
- package/cjs/lib/message.d.ts +0 -69
- package/cjs/lib/policy.d.ts +0 -70
- package/cjs/lib/registry.d.ts +0 -46
- package/cjs/types/message.type.d.ts +0 -13
- package/cjs/types/policy.type.d.ts +0 -10
- package/cjs/types/registry.type.d.ts +0 -16
- package/cjs/utils/extract-lang.d.ts +0 -11
- package/cjs/utils/format-key.d.ts +0 -13
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Seishiro API
|
|
2
2
|
|
|
3
3
|
Seishiro eliminates the complexity of routing folder structures and replaces them with a single control center. Just use one endpoint, manage it through the Registry, and control your entire application data flow (Web, Mobile, and SSR) with consistent standards.
|
|
4
|
-
|
|
4
|
+
<!--
|
|
5
5
|
## Tasks
|
|
6
6
|
|
|
7
7
|
- [x] Registry Controllers
|
|
@@ -11,8 +11,8 @@ Seishiro eliminates the complexity of routing folder structures and replaces the
|
|
|
11
11
|
- [x] Protocol Response
|
|
12
12
|
- [x] Middleware Runner
|
|
13
13
|
- [x] Action Executed
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
14
|
+
- [x] Versioning Header
|
|
15
|
+
- [x] Language Switch -->
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
@@ -78,7 +78,7 @@ const sysaction = await action.SystemAction({
|
|
|
78
78
|
system: {
|
|
79
79
|
headers: {...}, // Header KV (Key, Value)
|
|
80
80
|
cookies: {...}, // Cookie KV (Key, Value)
|
|
81
|
-
ip: "
|
|
81
|
+
ip: "127.0.0.1", // IP Address (IP Client - Example)
|
|
82
82
|
location: "JKT, Jakarta, Jakarta Pusat", // Location (Location Client By IP & PeerDB - Example)
|
|
83
83
|
},
|
|
84
84
|
type: "user:login", // Type Action
|
|
@@ -94,7 +94,7 @@ const serveraction = await action.ServerAction({
|
|
|
94
94
|
system: {
|
|
95
95
|
headers: {...}, // Header KV (Key, Value)
|
|
96
96
|
cookies: {...}, // Cookie KV (Key, Value)
|
|
97
|
-
ip: "
|
|
97
|
+
ip: "127.0.0.1", // IP Address (IP Client - Example)
|
|
98
98
|
location: "JKT, Jakarta, Jakarta Pusat", // Location (Location Client By IP & PeerDB - Example)
|
|
99
99
|
},
|
|
100
100
|
type: "user:profile", // Type Action
|
|
@@ -109,7 +109,7 @@ const apiaction = action.APIAction({
|
|
|
109
109
|
system: {
|
|
110
110
|
headers: {...}, // Header KV (Key, Value)
|
|
111
111
|
cookies: {...}, // Cookie KV (Key, Value)
|
|
112
|
-
ip: "
|
|
112
|
+
ip: "127.0.0.1", // IP Address (IP Client - Example)
|
|
113
113
|
location: "JKT, Jakarta, Jakarta Pusat", // Location (Location Client By IP & PeerDB - Example)
|
|
114
114
|
},
|
|
115
115
|
type: "user:profile", // Type Action
|
package/cjs/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.Actions=exports.PolicyBuilder=exports.MessageBuilder=exports.RegistryBuilder=void 0;var
|
|
1
|
+
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.Actions=exports.PolicyBuilder=exports.MessageBuilder=exports.RegistryBuilder=void 0;var registry_js_1=require("./lib/registry.js");Object.defineProperty(exports,"RegistryBuilder",{enumerable:!0,get:function(){return __importDefault(registry_js_1).default}});var message_js_1=require("./lib/message.js");Object.defineProperty(exports,"MessageBuilder",{enumerable:!0,get:function(){return __importDefault(message_js_1).default}});var policy_js_1=require("./lib/policy.js");Object.defineProperty(exports,"PolicyBuilder",{enumerable:!0,get:function(){return __importDefault(policy_js_1).default}});var actions_js_1=require("./lib/actions.js");Object.defineProperty(exports,"Actions",{enumerable:!0,get:function(){return __importDefault(actions_js_1).default}});
|
package/cjs/lib/actions.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const crypto_1=__importDefault(require("crypto")),buffer_1=require("buffer");class Actions{registry;message;policy;constructor({registry:e,message:
|
|
1
|
+
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const crypto_1=__importDefault(require("crypto")),buffer_1=require("buffer"),extract_lang_js_1=__importDefault(require("../utils/extract-lang.js"));class Actions{registry;message;policy;cache_book;constructor({registry:e,message:t,policy:r}){this.registry=e,this.message=t,this.policy=r,this.cache_book=null}BookRegistry(){if(this.cache_book)return this.cache_book;const e="hex",t=crypto_1.default.randomBytes(16),r=this.policy.apply(),s=this.registry.apply(),i=crypto_1.default.createHash("sha256").update(String(r.passkey||"").trim()).digest(),o={listkey:Object.keys(s).filter(e=>!r.noaction_api.includes(e)),version_now:r.version_now,version_min:r.version_min,version_forceupdate:r.version_forceupdate},a=crypto_1.default.createCipheriv("aes-256-ctr",i,t),n=buffer_1.Buffer.concat([t,a.update(JSON.stringify(o),"utf-8"),a.final()]),c={iv_length:16,type_base:e,iv:t.toString(e),data:n.toString(e)};return this.cache_book=c,c}ResponseBuilder(e={},t,r="en"){const s=!e||"object"!=typeof e||Array.isArray(e)||!!e.error||!e.data,i=e?.status||(s?400:200),o=e?.redirect||null,a=[];if(e?.headers&&"object"==typeof e.headers&&!Array.isArray(e.headers))for(const[t,r]of Object.entries(e.headers))a.push({key:t,value:r});const n=[];if(Array.isArray(e?.set_cookie))for(const t of e.set_cookie)t&&"object"==typeof t&&t.key&&t.value&&n.push(t);const c=[];if(Array.isArray(e?.rm_cookie))for(const t of e.rm_cookie)t&&"string"==typeof t&&c.push(t);const l={header:a,set_cookie:n,rm_cookie:c,status:i,redirect:o};if(s){const t=e?.error||"system:no-response-sending",s=this.message.error(t,e?.params||[],r);return{...l,error:t,response:{status:i,message:s.message,protocol:s.protocol,context:s.context,params:s.params}}}return{...l,error:null,response:{status:i,data:e.data||{}}}}async SystemAction({system:e,middleware:t={},context_manager:r="system-action",type:s,data:i}){const o=e?.headers||{},a=o["x-seishiro-lang"]||o["accept-language"],n=a?(0,extract_lang_js_1.default)(a):e?.lang||"en";try{const a=this.policy.apply(),c=o["x-seishiro-client"];if("api-action"===r&&!c)return this.ResponseBuilder({error:"system:client-version-required",status:400},e,n);if(c&&"api-action"===r){const t=this.policy.version_info(c);if(!t.is_version_min&&t.info_upgrade)return this.ResponseBuilder({error:"system:need-upgrade-client",status:426,params:[{min:a.version_min,now:a.version_now}]},e,n)}const l=this.registry.get(s||"");if(!l)return this.ResponseBuilder({error:"system:no-registry",status:404},e,n);const u={...e,lang:n};let p=t,y=l;if(Array.isArray(l)){const[e,r]=l,o=await e({system:u,middleware:t,type:s,data:i});p=a.skip_middleware_context||o?.skipBuilder?o:this.ResponseBuilder(o,u,n),y=r}const d=await y({system:u,middleware:p,type:s,data:i});return this.ResponseBuilder(d,u,n)}catch(t){return console.error("[Seishiro Core Error]:",t),this.ResponseBuilder({error:"system:internal-server-error",status:500},e,n)}}async ServerAction({system:e,middleware:t,type:r,data:s}){if(this.policy.apply().noaction_server.includes(r||"")){const t=(0,extract_lang_js_1.default)(e?.headers?.["x-seishiro-lang"]||e?.headers?.["accept-language"]||e?.lang||"en");return this.ResponseBuilder({error:"system:no-registry",status:404},e,t)}return this.SystemAction({system:e,middleware:t,context_manager:"server-action",type:r,data:s})}async APIAction({system:e,middleware:t,type:r,data:s}){if(this.policy.apply().noaction_api.includes(r||"")){const t=(0,extract_lang_js_1.default)(e?.headers?.["x-seishiro-lang"]||e?.headers?.["accept-language"]||e?.lang||"en");return this.ResponseBuilder({error:"system:no-registry",status:404},e,t)}return this.SystemAction({system:e,middleware:t,context_manager:"api-action",type:r,data:s})}}exports.default=Actions;
|
package/cjs/lib/message.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const
|
|
1
|
+
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const format_key_js_1=__importDefault(require("../utils/format-key.js")),message_js_1=require("../constants/message.js");class MessageBuilder{message_build_lang="";message_logic=new Map;constructor(e="en"){this.message_build_lang=String(e||"en").toLowerCase().replace(/[^a-z]/g,"").slice(0,2),this.message_logic=new Map}set(e,s){if("string"!=typeof s||"string"!=typeof e)throw new Error("Key and Value must be string!");const t=(0,format_key_js_1.default)(e);this.message_logic.has(this.message_build_lang)||this.message_logic.set(this.message_build_lang,new Map),this.message_logic.get(this.message_build_lang).set(t,s.trim())}get(e="",s=this.message_build_lang){const t=(0,format_key_js_1.default)(e);let a=this.message_logic.get(s);return a||(a=this.message_logic.get(message_js_1.DefaultLanguage),!a&&this.message_logic.size>0&&(a=this.message_logic.values().next().value)),a?a.get(t)||"":`[!NoneVariable ${t}]`}errorMessage(e="",s={},t=this.message_build_lang){const a=this.get(e,t);return s&&0!==Object.keys(s).length?a.replace(/{{(\w+)}}/g,(e,t)=>s[t]||e):a}error(e="",s=[],t=this.message_build_lang){const a=e.indexOf(":");if(-1===a)return{protocol:"unknown",context:[e],params:s,message:e};const i=(0,format_key_js_1.default)(e.substring(0,a)),r=e.substring(a+1).split("|");let g="";for(let e=0;e<r.length;e++){g+=(0===e?"":", ")+this.errorMessage(r[e],s[e],t)}return{protocol:i,context:r,params:s,message:g}}apply(){return this.message_logic}use(e){if(e instanceof MessageBuilder){e.apply().forEach((e,s)=>{let t=this.message_logic.get(s);t||(t=new Map,this.message_logic.set(s,t)),e.forEach((e,s)=>{t.set(s,e)})})}else{if("object"!=typeof e||null===e)throw new Error('The "use" input must be a MessageBuilder or mapping object!');for(const s in e)Object.prototype.hasOwnProperty.call(e,s)&&this.set(s,e[s])}}}exports.default=MessageBuilder;
|
package/cjs/lib/policy.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});class PolicyBuilder{passkey;version_now;version_min;version_forceupdate;noaction_api;noaction_server;constructor({passkey:
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});class PolicyBuilder{passkey;version_now;version_min;version_forceupdate;noaction_api;noaction_server;compiled_policy=null;skip_middleware_context;parsed_min;parsed_now;constructor({passkey:e,version_now:i,version_min:o,version_forceupdate:s=!0,skip_middleware_context:r=!1}){if(!e||!i||!o)throw new Error("PolicyBuilder: passkey, version_now, and version_min are required!");this.passkey=e,this.version_now=i,this.version_min=o,this.parsed_min=this.parseVersion(o),this.parsed_now=this.parseVersion(i),this.version_forceupdate=s,this.noaction_api=[],this.noaction_server=[],this.skip_middleware_context=r,this.refresh()}noaction(e="",i=[]){const o=["server-action","api-action"];for(let e of i)if(!o.includes(e))throw new Error(`Invalid action type: ${e}. Only allowed actions are: ${o.join(", ")}`);if("string"!=typeof e)throw new Error("Invalid key type, it only string!");for(let o of i)"api-action"===o?this.noaction_api.push(e):"server-action"===o&&this.noaction_server.push(e)}parseVersion(e){return e.split(".").map(Number)}compare(e,i){const o=Math.max(e.length,i.length);for(let s=0;s<o;s++){const o=e[s]||0,r=i[s]||0;if(o!==r)return o>r?1:-1}return 0}version_info(e=""){const i=this.parseVersion(e);return{info_upgrade:this.version_forceupdate,is_version_min:this.compare(i,this.parsed_min)>=0,is_version_now:this.compare(i,this.parsed_now)>=0}}refresh(){this.compiled_policy={passkey:this.passkey,version_now:this.version_now,version_min:this.version_min,version_forceupdate:this.version_forceupdate,noaction_api:this.noaction_api,noaction_server:this.noaction_server,skip_middleware_context:this.skip_middleware_context}}apply(){return this.compiled_policy}}exports.default=PolicyBuilder;
|
package/cjs/lib/registry.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(exports,"__esModule",{value:!0});const
|
|
1
|
+
"use strict";var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(exports,"__esModule",{value:!0});const format_key_js_1=__importDefault(require("../utils/format-key.js"));class RegistryBuilder{registry_logic;constructor(){this.registry_logic=new Map}set(t,e,r){const i=(0,format_key_js_1.default)(t);if("function"!=typeof e)throw new Error("Registry function is only type function!");if("string"!=typeof t)throw new Error("Registry key is only type string!");r&&"function"==typeof r?this.registry_logic.set(i,[r,e]):this.registry_logic.set(i,e)}get(t){const e=(0,format_key_js_1.default)(t);return this.registry_logic.get(e)||void 0}apply(){return this.registry_logic}use(t){if(t instanceof RegistryBuilder)for(const[e,r]of t.registry_logic)this.registry_logic.set(e,r);else{if("object"!=typeof t||null===t)throw new Error('The "use" input must be a RegistryBuilder or mapping object!');for(const[e,r]of Object.entries(t))Array.isArray(r)?this.set(e,r[1],r[0]):"function"==typeof r&&this.set(e,r)}}}exports.default=RegistryBuilder;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";function extractLanguage(t=""){return String(t||"").trim().split(",").map(t=>t.split(";")[0].split("-")[0].trim()).filter((t,
|
|
1
|
+
"use strict";function extractLanguage(t=""){return String(t||"").trim().split(",").map(t=>t.split(";")[0].split("-")[0].trim()).filter((t,e,r)=>r.indexOf(t)===e)[0]}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=extractLanguage;
|
package/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { default as RegistryBuilder } from "./lib/registry";
|
|
2
|
-
export { default as MessageBuilder } from "./lib/message";
|
|
3
|
-
export { default as PolicyBuilder } from "./lib/policy";
|
|
4
|
-
export { default as Actions } from "./lib/actions";
|
|
1
|
+
export { default as RegistryBuilder } from "./lib/registry.js";
|
|
2
|
+
export { default as MessageBuilder } from "./lib/message.js";
|
|
3
|
+
export { default as PolicyBuilder } from "./lib/policy.js";
|
|
4
|
+
export { default as Actions } from "./lib/actions.js";
|
package/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{default as RegistryBuilder}from"./lib/registry";export{default as MessageBuilder}from"./lib/message";export{default as PolicyBuilder}from"./lib/policy";export{default as Actions}from"./lib/actions";
|
|
1
|
+
export{default as RegistryBuilder}from"./lib/registry.js";export{default as MessageBuilder}from"./lib/message.js";export{default as PolicyBuilder}from"./lib/policy.js";export{default as Actions}from"./lib/actions.js";
|
package/esm/lib/actions.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { RegistryParams } from "../types/registry.type";
|
|
2
|
-
import RegistryBuilder from "./registry";
|
|
3
|
-
import MessageBuilder from "./message";
|
|
4
|
-
import PolicyBuilder from "./policy";
|
|
1
|
+
import { RegistryParams } from "../types/registry.type.js";
|
|
2
|
+
import RegistryBuilder from "./registry.js";
|
|
3
|
+
import MessageBuilder from "./message.js";
|
|
4
|
+
import PolicyBuilder from "./policy.js";
|
|
5
5
|
/**
|
|
6
6
|
* @class Actions
|
|
7
7
|
* @description The main orchestrator of the Seishiro API. It handles the execution flow
|
|
@@ -11,6 +11,7 @@ export default class Actions {
|
|
|
11
11
|
private registry;
|
|
12
12
|
private message;
|
|
13
13
|
private policy;
|
|
14
|
+
private cache_book;
|
|
14
15
|
/**
|
|
15
16
|
* @constructor
|
|
16
17
|
* @param {Object} params - Configuration instances.
|
|
@@ -27,7 +28,7 @@ export default class Actions {
|
|
|
27
28
|
* @method BookRegistry
|
|
28
29
|
* @description Generates an encrypted list of available API registries and application versions.
|
|
29
30
|
* This is used to securely expose allowed actions to the client side.
|
|
30
|
-
* @returns {Object} An object containing encryption metadata (iv, type_base) and the encrypted
|
|
31
|
+
* @returns {Object} An object containing encryption metadata (iv, type_base) and the encrypted "data" string.
|
|
31
32
|
*/
|
|
32
33
|
BookRegistry(): {
|
|
33
34
|
iv_length: number;
|
|
@@ -50,33 +51,25 @@ export default class Actions {
|
|
|
50
51
|
* @param {RegistryParams} params - The request payload containing system info, type, data, and optional middleware state.
|
|
51
52
|
* @returns {Promise<Object>} A promise that resolves to a standardized response object via ResponseBuilder.
|
|
52
53
|
*/
|
|
53
|
-
SystemAction({ system, middleware, type, data }: RegistryParams): Promise<{
|
|
54
|
-
header: {
|
|
55
|
-
key: string;
|
|
56
|
-
value: unknown;
|
|
57
|
-
}[];
|
|
58
|
-
set_cookie: any;
|
|
59
|
-
rm_cookie: any;
|
|
60
|
-
status: any;
|
|
61
|
-
redirect: any;
|
|
54
|
+
SystemAction({ system, middleware, context_manager, type, data, }: RegistryParams): Promise<{
|
|
62
55
|
error: any;
|
|
63
56
|
response: {
|
|
64
57
|
status: any;
|
|
65
58
|
message: string;
|
|
66
59
|
protocol: string;
|
|
67
60
|
context: string[];
|
|
68
|
-
params:
|
|
61
|
+
params: import("../types/message.type.js").MessageErrorContextOpt[];
|
|
69
62
|
data?: undefined;
|
|
70
63
|
};
|
|
71
|
-
} | {
|
|
72
64
|
header: {
|
|
73
65
|
key: string;
|
|
74
66
|
value: unknown;
|
|
75
67
|
}[];
|
|
76
|
-
set_cookie: any;
|
|
77
|
-
rm_cookie:
|
|
68
|
+
set_cookie: any[];
|
|
69
|
+
rm_cookie: string[];
|
|
78
70
|
status: any;
|
|
79
71
|
redirect: any;
|
|
72
|
+
} | {
|
|
80
73
|
error: null;
|
|
81
74
|
response: {
|
|
82
75
|
status: any;
|
|
@@ -86,6 +79,14 @@ export default class Actions {
|
|
|
86
79
|
context?: undefined;
|
|
87
80
|
params?: undefined;
|
|
88
81
|
};
|
|
82
|
+
header: {
|
|
83
|
+
key: string;
|
|
84
|
+
value: unknown;
|
|
85
|
+
}[];
|
|
86
|
+
set_cookie: any[];
|
|
87
|
+
rm_cookie: string[];
|
|
88
|
+
status: any;
|
|
89
|
+
redirect: any;
|
|
89
90
|
}>;
|
|
90
91
|
/**
|
|
91
92
|
* @method ServerAction
|
|
@@ -95,32 +96,24 @@ export default class Actions {
|
|
|
95
96
|
* @returns {Promise<Object>} The standardized response or a 404 error if the action is restricted by policy.
|
|
96
97
|
*/
|
|
97
98
|
ServerAction({ system, middleware, type, data }: RegistryParams): Promise<{
|
|
98
|
-
header: {
|
|
99
|
-
key: string;
|
|
100
|
-
value: unknown;
|
|
101
|
-
}[];
|
|
102
|
-
set_cookie: any;
|
|
103
|
-
rm_cookie: any;
|
|
104
|
-
status: any;
|
|
105
|
-
redirect: any;
|
|
106
99
|
error: any;
|
|
107
100
|
response: {
|
|
108
101
|
status: any;
|
|
109
102
|
message: string;
|
|
110
103
|
protocol: string;
|
|
111
104
|
context: string[];
|
|
112
|
-
params:
|
|
105
|
+
params: import("../types/message.type.js").MessageErrorContextOpt[];
|
|
113
106
|
data?: undefined;
|
|
114
107
|
};
|
|
115
|
-
} | {
|
|
116
108
|
header: {
|
|
117
109
|
key: string;
|
|
118
110
|
value: unknown;
|
|
119
111
|
}[];
|
|
120
|
-
set_cookie: any;
|
|
121
|
-
rm_cookie:
|
|
112
|
+
set_cookie: any[];
|
|
113
|
+
rm_cookie: string[];
|
|
122
114
|
status: any;
|
|
123
115
|
redirect: any;
|
|
116
|
+
} | {
|
|
124
117
|
error: null;
|
|
125
118
|
response: {
|
|
126
119
|
status: any;
|
|
@@ -130,6 +123,14 @@ export default class Actions {
|
|
|
130
123
|
context?: undefined;
|
|
131
124
|
params?: undefined;
|
|
132
125
|
};
|
|
126
|
+
header: {
|
|
127
|
+
key: string;
|
|
128
|
+
value: unknown;
|
|
129
|
+
}[];
|
|
130
|
+
set_cookie: any[];
|
|
131
|
+
rm_cookie: string[];
|
|
132
|
+
status: any;
|
|
133
|
+
redirect: any;
|
|
133
134
|
}>;
|
|
134
135
|
/**
|
|
135
136
|
* @method APIAction
|
|
@@ -139,32 +140,24 @@ export default class Actions {
|
|
|
139
140
|
* @returns {Promise<Object>} The standardized response or a 404 error if the action is restricted by policy.
|
|
140
141
|
*/
|
|
141
142
|
APIAction({ system, middleware, type, data }: RegistryParams): Promise<{
|
|
142
|
-
header: {
|
|
143
|
-
key: string;
|
|
144
|
-
value: unknown;
|
|
145
|
-
}[];
|
|
146
|
-
set_cookie: any;
|
|
147
|
-
rm_cookie: any;
|
|
148
|
-
status: any;
|
|
149
|
-
redirect: any;
|
|
150
143
|
error: any;
|
|
151
144
|
response: {
|
|
152
145
|
status: any;
|
|
153
146
|
message: string;
|
|
154
147
|
protocol: string;
|
|
155
148
|
context: string[];
|
|
156
|
-
params:
|
|
149
|
+
params: import("../types/message.type.js").MessageErrorContextOpt[];
|
|
157
150
|
data?: undefined;
|
|
158
151
|
};
|
|
159
|
-
} | {
|
|
160
152
|
header: {
|
|
161
153
|
key: string;
|
|
162
154
|
value: unknown;
|
|
163
155
|
}[];
|
|
164
|
-
set_cookie: any;
|
|
165
|
-
rm_cookie:
|
|
156
|
+
set_cookie: any[];
|
|
157
|
+
rm_cookie: string[];
|
|
166
158
|
status: any;
|
|
167
159
|
redirect: any;
|
|
160
|
+
} | {
|
|
168
161
|
error: null;
|
|
169
162
|
response: {
|
|
170
163
|
status: any;
|
|
@@ -174,5 +167,13 @@ export default class Actions {
|
|
|
174
167
|
context?: undefined;
|
|
175
168
|
params?: undefined;
|
|
176
169
|
};
|
|
170
|
+
header: {
|
|
171
|
+
key: string;
|
|
172
|
+
value: unknown;
|
|
173
|
+
}[];
|
|
174
|
+
set_cookie: any[];
|
|
175
|
+
rm_cookie: string[];
|
|
176
|
+
status: any;
|
|
177
|
+
redirect: any;
|
|
177
178
|
}>;
|
|
178
179
|
}
|
package/esm/lib/actions.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import crypto from"crypto";import{Buffer}from"buffer";export default class Actions{registry;message;policy;constructor({registry:e,message:r,policy:t}){this.registry=e,this.message=r,this.policy=t}BookRegistry(){const e="hex",r=crypto.randomBytes(16),t=this.policy.apply(),s=this.registry.apply(),o=crypto.createHash("sha256").update(String(t.passkey||"").trim()).digest(),i={listkey:Object.keys(s).filter(e=>!t.noaction_api.includes(e)),version_now:t.version_now,version_min:t.version_min,version_forceupdate:t.version_forceupdate},a=crypto.createCipheriv("aes-256-ctr",o,r),n=Buffer.concat([r,a.update(JSON.stringify(i),"utf-8"),a.final()])
|
|
1
|
+
import crypto from"crypto";import{Buffer}from"buffer";import extractLanguage from"../utils/extract-lang.js";export default class Actions{registry;message;policy;cache_book;constructor({registry:e,message:r,policy:t}){this.registry=e,this.message=r,this.policy=t,this.cache_book=null}BookRegistry(){if(this.cache_book)return this.cache_book;const e="hex",r=crypto.randomBytes(16),t=this.policy.apply(),s=this.registry.apply(),o=crypto.createHash("sha256").update(String(t.passkey||"").trim()).digest(),i={listkey:Object.keys(s).filter(e=>!t.noaction_api.includes(e)),version_now:t.version_now,version_min:t.version_min,version_forceupdate:t.version_forceupdate},a=crypto.createCipheriv("aes-256-ctr",o,r),n=Buffer.concat([r,a.update(JSON.stringify(i),"utf-8"),a.final()]),c={iv_length:16,type_base:e,iv:r.toString(e),data:n.toString(e)};return this.cache_book=c,c}ResponseBuilder(e={},r,t="en"){const s=!e||"object"!=typeof e||Array.isArray(e)||!!e.error||!e.data,o=e?.status||(s?400:200),i=e?.redirect||null,a=[];if(e?.headers&&"object"==typeof e.headers&&!Array.isArray(e.headers))for(const[r,t]of Object.entries(e.headers))a.push({key:r,value:t});const n=[];if(Array.isArray(e?.set_cookie))for(const r of e.set_cookie)r&&"object"==typeof r&&r.key&&r.value&&n.push(r);const c=[];if(Array.isArray(e?.rm_cookie))for(const r of e.rm_cookie)r&&"string"==typeof r&&c.push(r);const p={header:a,set_cookie:n,rm_cookie:c,status:o,redirect:i};if(s){const r=e?.error||"system:no-response-sending",s=this.message.error(r,e?.params||[],t);return{...p,error:r,response:{status:o,message:s.message,protocol:s.protocol,context:s.context,params:s.params}}}return{...p,error:null,response:{status:o,data:e.data||{}}}}async SystemAction({system:e,middleware:r={},context_manager:t="system-action",type:s,data:o}){const i=e?.headers||{},a=i["x-seishiro-lang"]||i["accept-language"],n=a?extractLanguage(a):e?.lang||"en";try{const a=this.policy.apply(),c=i["x-seishiro-client"];if("api-action"===t&&!c)return this.ResponseBuilder({error:"system:client-version-required",status:400},e,n);if(c&&"api-action"===t){const r=this.policy.version_info(c);if(!r.is_version_min&&r.info_upgrade)return this.ResponseBuilder({error:"system:need-upgrade-client",status:426,params:[{min:a.version_min,now:a.version_now}]},e,n)}const p=this.registry.get(s||"");if(!p)return this.ResponseBuilder({error:"system:no-registry",status:404},e,n);const y={...e,lang:n};let l=r,u=p;if(Array.isArray(p)){const[e,t]=p,i=await e({system:y,middleware:r,type:s,data:o});l=a.skip_middleware_context||i?.skipBuilder?i:this.ResponseBuilder(i,y,n),u=t}const d=await u({system:y,middleware:l,type:s,data:o});return this.ResponseBuilder(d,y,n)}catch(r){return console.error("[Seishiro Core Error]:",r),this.ResponseBuilder({error:"system:internal-server-error",status:500},e,n)}}async ServerAction({system:e,middleware:r,type:t,data:s}){if(this.policy.apply().noaction_server.includes(t||"")){const r=extractLanguage(e?.headers?.["x-seishiro-lang"]||e?.headers?.["accept-language"]||e?.lang||"en");return this.ResponseBuilder({error:"system:no-registry",status:404},e,r)}return this.SystemAction({system:e,middleware:r,context_manager:"server-action",type:t,data:s})}async APIAction({system:e,middleware:r,type:t,data:s}){if(this.policy.apply().noaction_api.includes(t||"")){const r=extractLanguage(e?.headers?.["x-seishiro-lang"]||e?.headers?.["accept-language"]||e?.lang||"en");return this.ResponseBuilder({error:"system:no-registry",status:404},e,r)}return this.SystemAction({system:e,middleware:r,context_manager:"api-action",type:t,data:s})}}
|
package/esm/lib/message.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MessageKey, MessageValue, MessageLang, MessageLogic, MessageLogicLang, MessageErrorContext, MessageErrorContextOpt, MessageErrorContextSlug } from "../types/message.type";
|
|
1
|
+
import type { MessageKey, MessageValue, MessageLang, MessageLogic, MessageLogicLang, MessageErrorContext, MessageErrorContextOpt, MessageErrorContextSlug } from "../types/message.type.js";
|
|
2
2
|
/**
|
|
3
3
|
* @class MessageBuilder
|
|
4
4
|
* @description Handles multi-language response messages, error formatting, and dynamic template replacement.
|
|
@@ -50,7 +50,7 @@ export default class MessageBuilder {
|
|
|
50
50
|
error(errorStr?: MessageErrorContext, errorOpts?: MessageErrorContextOpt[], lang?: MessageLang): {
|
|
51
51
|
protocol: string;
|
|
52
52
|
context: string[];
|
|
53
|
-
params:
|
|
53
|
+
params: MessageErrorContextOpt[];
|
|
54
54
|
message: string;
|
|
55
55
|
};
|
|
56
56
|
/**
|
package/esm/lib/message.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import formatKey from"../utils/format-key";import{DefaultLanguage}from"../constants/message";export default class MessageBuilder{message_build_lang="";message_logic=
|
|
1
|
+
import formatKey from"../utils/format-key.js";import{DefaultLanguage}from"../constants/message.js";export default class MessageBuilder{message_build_lang="";message_logic=new Map;constructor(e="en"){this.message_build_lang=String(e||"en").toLowerCase().replace(/[^a-z]/g,"").slice(0,2),this.message_logic=new Map}set(e,s){if("string"!=typeof s||"string"!=typeof e)throw new Error("Key and Value must be string!");const t=formatKey(e);this.message_logic.has(this.message_build_lang)||this.message_logic.set(this.message_build_lang,new Map),this.message_logic.get(this.message_build_lang).set(t,s.trim())}get(e="",s=this.message_build_lang){const t=formatKey(e);let a=this.message_logic.get(s);return a||(a=this.message_logic.get(DefaultLanguage),!a&&this.message_logic.size>0&&(a=this.message_logic.values().next().value)),a?a.get(t)||"":`[!NoneVariable ${t}]`}errorMessage(e="",s={},t=this.message_build_lang){const a=this.get(e,t);return s&&0!==Object.keys(s).length?a.replace(/{{(\w+)}}/g,(e,t)=>s[t]||e):a}error(e="",s=[],t=this.message_build_lang){const a=e.indexOf(":");if(-1===a)return{protocol:"unknown",context:[e],params:s,message:e};const g=formatKey(e.substring(0,a)),i=e.substring(a+1).split("|");let r="";for(let e=0;e<i.length;e++){r+=(0===e?"":", ")+this.errorMessage(i[e],s[e],t)}return{protocol:g,context:i,params:s,message:r}}apply(){return this.message_logic}use(e){if(e instanceof MessageBuilder){e.apply().forEach((e,s)=>{let t=this.message_logic.get(s);t||(t=new Map,this.message_logic.set(s,t)),e.forEach((e,s)=>{t.set(s,e)})})}else{if("object"!=typeof e||null===e)throw new Error('The "use" input must be a MessageBuilder or mapping object!');for(const s in e)Object.prototype.hasOwnProperty.call(e,s)&&this.set(s,e[s])}}}
|
package/esm/lib/policy.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PolicyNoActionKey, PolicyNoActionBase } from "../types/policy.type.js";
|
|
2
2
|
/**
|
|
3
3
|
* @class PolicyBuilder
|
|
4
4
|
* @description Manages application policies including security passkeys, version control,
|
|
@@ -11,6 +11,10 @@ export default class PolicyBuilder {
|
|
|
11
11
|
private version_forceupdate;
|
|
12
12
|
private noaction_api;
|
|
13
13
|
private noaction_server;
|
|
14
|
+
private compiled_policy;
|
|
15
|
+
private skip_middleware_context;
|
|
16
|
+
private parsed_min;
|
|
17
|
+
private parsed_now;
|
|
14
18
|
/**
|
|
15
19
|
* @constructor
|
|
16
20
|
* @param {Object} config - The policy configuration.
|
|
@@ -20,11 +24,12 @@ export default class PolicyBuilder {
|
|
|
20
24
|
* @param {boolean} [config.version_forceupdate=true] - Flag to indicate if clients below version_min must update.
|
|
21
25
|
* @throws {Error} If passkey, version_now, or version_min is missing.
|
|
22
26
|
*/
|
|
23
|
-
constructor({ passkey, version_now, version_min, version_forceupdate, }: {
|
|
27
|
+
constructor({ passkey, version_now, version_min, version_forceupdate, skip_middleware_context, }: {
|
|
24
28
|
passkey: string;
|
|
25
29
|
version_now: string;
|
|
26
30
|
version_min: string;
|
|
27
31
|
version_forceupdate?: boolean;
|
|
32
|
+
skip_middleware_context?: boolean;
|
|
28
33
|
});
|
|
29
34
|
/**
|
|
30
35
|
* @method noaction
|
|
@@ -34,37 +39,28 @@ export default class PolicyBuilder {
|
|
|
34
39
|
* @throws {Error} If the protocol type is invalid or the key is not a string.
|
|
35
40
|
*/
|
|
36
41
|
noaction(type?: PolicyNoActionKey, action?: PolicyNoActionBase): void;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* @private
|
|
40
|
-
* @description Compares two semantic version strings to determine their order.
|
|
41
|
-
* @param {string} v1 - First version string.
|
|
42
|
-
* @param {string} v2 - Second version string.
|
|
43
|
-
* @returns {number} 1 if v1 > v2, -1 if v1 < v2, and 0 if they are equal.
|
|
44
|
-
*/
|
|
45
|
-
private compareVersions;
|
|
42
|
+
private parseVersion;
|
|
43
|
+
private compare;
|
|
46
44
|
/**
|
|
47
45
|
* @method version_info
|
|
48
46
|
* @description Checks a provided version against the minimum and current version requirements.
|
|
49
47
|
* @param {string} [version=""] - The version string to validate (usually from the client).
|
|
50
48
|
* @returns {Object} An object containing upgrade flags and version compatibility status.
|
|
51
49
|
*/
|
|
52
|
-
version_info(
|
|
50
|
+
version_info(clientVersion?: string): {
|
|
53
51
|
info_upgrade: boolean;
|
|
54
52
|
is_version_min: boolean;
|
|
55
53
|
is_version_now: boolean;
|
|
56
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* @method refresh
|
|
57
|
+
* @description Refreshes the compiled policy.
|
|
58
|
+
*/
|
|
59
|
+
private refresh;
|
|
57
60
|
/**
|
|
58
61
|
* @method apply
|
|
59
62
|
* @description Retrieves the compiled policy configuration.
|
|
60
63
|
* @returns {Object} All policy settings including restricted actions and versioning data.
|
|
61
64
|
*/
|
|
62
|
-
apply():
|
|
63
|
-
passkey: string;
|
|
64
|
-
version_now: string;
|
|
65
|
-
version_min: string;
|
|
66
|
-
version_forceupdate: boolean;
|
|
67
|
-
noaction_api: PolicyNoActionAPIAction;
|
|
68
|
-
noaction_server: PolicyNoActionServerAction;
|
|
69
|
-
};
|
|
65
|
+
apply(): any;
|
|
70
66
|
}
|
package/esm/lib/policy.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default class PolicyBuilder{passkey;version_now;version_min;version_forceupdate;noaction_api;noaction_server;constructor({passkey:i,version_now:
|
|
1
|
+
export default class PolicyBuilder{passkey;version_now;version_min;version_forceupdate;noaction_api;noaction_server;compiled_policy=null;skip_middleware_context;parsed_min;parsed_now;constructor({passkey:i,version_now:e,version_min:o,version_forceupdate:s=!0,skip_middleware_context:n=!1}){if(!i||!e||!o)throw new Error("PolicyBuilder: passkey, version_now, and version_min are required!");this.passkey=i,this.version_now=e,this.version_min=o,this.parsed_min=this.parseVersion(o),this.parsed_now=this.parseVersion(e),this.version_forceupdate=s,this.noaction_api=[],this.noaction_server=[],this.skip_middleware_context=n,this.refresh()}noaction(i="",e=[]){const o=["server-action","api-action"];for(let i of e)if(!o.includes(i))throw new Error(`Invalid action type: ${i}. Only allowed actions are: ${o.join(", ")}`);if("string"!=typeof i)throw new Error("Invalid key type, it only string!");for(let o of e)"api-action"===o?this.noaction_api.push(i):"server-action"===o&&this.noaction_server.push(i)}parseVersion(i){return i.split(".").map(Number)}compare(i,e){const o=Math.max(i.length,e.length);for(let s=0;s<o;s++){const o=i[s]||0,n=e[s]||0;if(o!==n)return o>n?1:-1}return 0}version_info(i=""){const e=this.parseVersion(i);return{info_upgrade:this.version_forceupdate,is_version_min:this.compare(e,this.parsed_min)>=0,is_version_now:this.compare(e,this.parsed_now)>=0}}refresh(){this.compiled_policy={passkey:this.passkey,version_now:this.version_now,version_min:this.version_min,version_forceupdate:this.version_forceupdate,noaction_api:this.noaction_api,noaction_server:this.noaction_server,skip_middleware_context:this.skip_middleware_context}}apply(){return this.compiled_policy}}
|
package/esm/lib/registry.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RegistryKey, RegistryFunction, RegistryLogic, RegistryMiddleware } from "../types/registry.type";
|
|
1
|
+
import type { RegistryKey, RegistryFunction, RegistryLogic, RegistryMiddleware } from "../types/registry.type.js";
|
|
2
2
|
/**
|
|
3
3
|
* @class RegistryBuilder
|
|
4
4
|
* @description Centralizes the mapping of unique action keys to their respective controllers
|
package/esm/lib/registry.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import formatKey from"../utils/format-key";export default class RegistryBuilder{registry_logic
|
|
1
|
+
import formatKey from"../utils/format-key.js";export default class RegistryBuilder{registry_logic;constructor(){this.registry_logic=new Map}set(t,r,e){const i=formatKey(t);if("function"!=typeof r)throw new Error("Registry function is only type function!");if("string"!=typeof t)throw new Error("Registry key is only type string!");e&&"function"==typeof e?this.registry_logic.set(i,[e,r]):this.registry_logic.set(i,r)}get(t){const r=formatKey(t);return this.registry_logic.get(r)||void 0}apply(){return this.registry_logic}use(t){if(t instanceof RegistryBuilder)for(const[r,e]of t.registry_logic)this.registry_logic.set(r,e);else{if("object"!=typeof t||null===t)throw new Error('The "use" input must be a RegistryBuilder or mapping object!');for(const[r,e]of Object.entries(t))Array.isArray(e)?this.set(r,e[1],e[0]):"function"==typeof e&&this.set(r,e)}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -3,11 +3,7 @@ export type MessageLang = string | "en" | "id";
|
|
|
3
3
|
export type MessageValue = string;
|
|
4
4
|
export type MessageErrorContext = string;
|
|
5
5
|
export type MessageErrorContextSlug = string;
|
|
6
|
-
export type MessageErrorContextOpt =
|
|
6
|
+
export type MessageErrorContextOpt = Record<string, string>;
|
|
7
7
|
export type MessageErrorContextTrack = string;
|
|
8
|
-
export type MessageLogicLang =
|
|
9
|
-
[key: MessageLang]: {
|
|
10
|
-
[key: MessageKey]: MessageValue;
|
|
11
|
-
};
|
|
12
|
-
};
|
|
8
|
+
export type MessageLogicLang = Map<MessageLang, Map<MessageKey, MessageValue>>;
|
|
13
9
|
export type MessageLogic = Record<MessageKey, MessageValue>;
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
export type RegistryKey = string;
|
|
2
2
|
export type RegistryParams = {
|
|
3
3
|
system: {
|
|
4
|
-
cookies:
|
|
5
|
-
|
|
4
|
+
cookies: {
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
};
|
|
7
|
+
headers: {
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
};
|
|
6
10
|
ip: string;
|
|
7
11
|
location: string;
|
|
8
12
|
lang: string | "en";
|
|
9
13
|
};
|
|
10
14
|
type: RegistryKey;
|
|
15
|
+
context_manager?: string;
|
|
11
16
|
middleware?: object | Function | Promise<any>;
|
|
12
17
|
data: object;
|
|
13
18
|
};
|
|
14
19
|
export type RegistryFunction = (params: RegistryParams) => any;
|
|
15
20
|
export type RegistryMiddleware = (params: RegistryParams) => any;
|
|
16
|
-
export type RegistryLogic =
|
|
21
|
+
export type RegistryLogic = Map<RegistryKey, RegistryFunction | [RegistryMiddleware, RegistryFunction]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export default function extractLanguage(t=""){return String(t||"").trim().split(",").map(t=>t.split(";")[0].split("-")[0].trim()).filter((t,i,r)=>r.indexOf(t)===i)[0]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "seishiro",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1-release",
|
|
4
4
|
"description": "A simple response context API that eliminates the complexity of routing folder structures and replaces them with a single control center.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./cjs/index.js",
|
|
@@ -31,5 +31,18 @@
|
|
|
31
31
|
"@types/node": "^25.2.2",
|
|
32
32
|
"glob": "^13.0.2",
|
|
33
33
|
"terser": "^5.46.0"
|
|
34
|
+
},
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/ernestoyoofi/seishiro.git"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/ernestoyoofi/seishiro#readme",
|
|
40
|
+
"keywords": [
|
|
41
|
+
"api",
|
|
42
|
+
"context",
|
|
43
|
+
"seishiro"
|
|
44
|
+
],
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/ernestoyoofi/seishiro/issues"
|
|
34
47
|
}
|
|
35
48
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const DefaultLanguage: string;
|
package/cjs/index.d.ts
DELETED
package/cjs/lib/actions.d.ts
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { RegistryParams } from "../types/registry.type";
|
|
2
|
-
import RegistryBuilder from "./registry";
|
|
3
|
-
import MessageBuilder from "./message";
|
|
4
|
-
import PolicyBuilder from "./policy";
|
|
5
|
-
/**
|
|
6
|
-
* @class Actions
|
|
7
|
-
* @description The main orchestrator of the Seishiro API. It handles the execution flow
|
|
8
|
-
* by coordinating between Registry, Message, and Policy builders across different protocols.
|
|
9
|
-
*/
|
|
10
|
-
export default class Actions {
|
|
11
|
-
private registry;
|
|
12
|
-
private message;
|
|
13
|
-
private policy;
|
|
14
|
-
/**
|
|
15
|
-
* @constructor
|
|
16
|
-
* @param {Object} params - Configuration instances.
|
|
17
|
-
* @param {RegistryBuilder} params.registry - Instance to manage route/controller mapping.
|
|
18
|
-
* @param {MessageBuilder} params.message - Instance to handle localized error/response messages.
|
|
19
|
-
* @param {PolicyBuilder} params.policy - Instance to manage security and versioning rules.
|
|
20
|
-
*/
|
|
21
|
-
constructor({ registry, message, policy, }: {
|
|
22
|
-
registry: RegistryBuilder;
|
|
23
|
-
message: MessageBuilder;
|
|
24
|
-
policy: PolicyBuilder;
|
|
25
|
-
});
|
|
26
|
-
/**
|
|
27
|
-
* @method BookRegistry
|
|
28
|
-
* @description Generates an encrypted list of available API registries and application versions.
|
|
29
|
-
* This is used to securely expose allowed actions to the client side.
|
|
30
|
-
* @returns {Object} An object containing encryption metadata (iv, type_base) and the encrypted 'data' string.
|
|
31
|
-
*/
|
|
32
|
-
BookRegistry(): {
|
|
33
|
-
iv_length: number;
|
|
34
|
-
type_base: string;
|
|
35
|
-
iv: string;
|
|
36
|
-
data: string;
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* @method ResponseBuilder
|
|
40
|
-
* @private
|
|
41
|
-
* @description Standardizes the response structure for all action types, handling headers, cookies, and errors.
|
|
42
|
-
* @param {any} dataRes - The raw result or error object from the controller/middleware.
|
|
43
|
-
* @param {RegistryParams["system"]} system - The system context (headers, cookies, ip, etc.) from the request.
|
|
44
|
-
* @returns {Object} A unified response object containing headers, cookies, status code, and the final data/error payload.
|
|
45
|
-
*/
|
|
46
|
-
private ResponseBuilder;
|
|
47
|
-
/**
|
|
48
|
-
* @method SystemAction
|
|
49
|
-
* @description The core execution engine that processes controllers and middlewares.
|
|
50
|
-
* @param {RegistryParams} params - The request payload containing system info, type, data, and optional middleware state.
|
|
51
|
-
* @returns {Promise<Object>} A promise that resolves to a standardized response object via ResponseBuilder.
|
|
52
|
-
*/
|
|
53
|
-
SystemAction({ system, middleware, type, data }: RegistryParams): Promise<{
|
|
54
|
-
header: {
|
|
55
|
-
key: string;
|
|
56
|
-
value: unknown;
|
|
57
|
-
}[];
|
|
58
|
-
set_cookie: any;
|
|
59
|
-
rm_cookie: any;
|
|
60
|
-
status: any;
|
|
61
|
-
redirect: any;
|
|
62
|
-
error: any;
|
|
63
|
-
response: {
|
|
64
|
-
status: any;
|
|
65
|
-
message: string;
|
|
66
|
-
protocol: string;
|
|
67
|
-
context: string[];
|
|
68
|
-
params: object[];
|
|
69
|
-
data?: undefined;
|
|
70
|
-
};
|
|
71
|
-
} | {
|
|
72
|
-
header: {
|
|
73
|
-
key: string;
|
|
74
|
-
value: unknown;
|
|
75
|
-
}[];
|
|
76
|
-
set_cookie: any;
|
|
77
|
-
rm_cookie: any;
|
|
78
|
-
status: any;
|
|
79
|
-
redirect: any;
|
|
80
|
-
error: null;
|
|
81
|
-
response: {
|
|
82
|
-
status: any;
|
|
83
|
-
data: any;
|
|
84
|
-
message?: undefined;
|
|
85
|
-
protocol?: undefined;
|
|
86
|
-
context?: undefined;
|
|
87
|
-
params?: undefined;
|
|
88
|
-
};
|
|
89
|
-
}>;
|
|
90
|
-
/**
|
|
91
|
-
* @method ServerAction
|
|
92
|
-
* @description Entry point for Server-side actions (e.g., Next.js Server Actions).
|
|
93
|
-
* It checks against server-specific policies before executing.
|
|
94
|
-
* @param {RegistryParams} params - The request payload.
|
|
95
|
-
* @returns {Promise<Object>} The standardized response or a 404 error if the action is restricted by policy.
|
|
96
|
-
*/
|
|
97
|
-
ServerAction({ system, middleware, type, data }: RegistryParams): Promise<{
|
|
98
|
-
header: {
|
|
99
|
-
key: string;
|
|
100
|
-
value: unknown;
|
|
101
|
-
}[];
|
|
102
|
-
set_cookie: any;
|
|
103
|
-
rm_cookie: any;
|
|
104
|
-
status: any;
|
|
105
|
-
redirect: any;
|
|
106
|
-
error: any;
|
|
107
|
-
response: {
|
|
108
|
-
status: any;
|
|
109
|
-
message: string;
|
|
110
|
-
protocol: string;
|
|
111
|
-
context: string[];
|
|
112
|
-
params: object[];
|
|
113
|
-
data?: undefined;
|
|
114
|
-
};
|
|
115
|
-
} | {
|
|
116
|
-
header: {
|
|
117
|
-
key: string;
|
|
118
|
-
value: unknown;
|
|
119
|
-
}[];
|
|
120
|
-
set_cookie: any;
|
|
121
|
-
rm_cookie: any;
|
|
122
|
-
status: any;
|
|
123
|
-
redirect: any;
|
|
124
|
-
error: null;
|
|
125
|
-
response: {
|
|
126
|
-
status: any;
|
|
127
|
-
data: any;
|
|
128
|
-
message?: undefined;
|
|
129
|
-
protocol?: undefined;
|
|
130
|
-
context?: undefined;
|
|
131
|
-
params?: undefined;
|
|
132
|
-
};
|
|
133
|
-
}>;
|
|
134
|
-
/**
|
|
135
|
-
* @method APIAction
|
|
136
|
-
* @description Entry point for REST API requests.
|
|
137
|
-
* It checks against API-specific policies to prevent unauthorized access to sensitive endpoints.
|
|
138
|
-
* @param {RegistryParams} params - The request payload.
|
|
139
|
-
* @returns {Promise<Object>} The standardized response or a 404 error if the action is restricted by policy.
|
|
140
|
-
*/
|
|
141
|
-
APIAction({ system, middleware, type, data }: RegistryParams): Promise<{
|
|
142
|
-
header: {
|
|
143
|
-
key: string;
|
|
144
|
-
value: unknown;
|
|
145
|
-
}[];
|
|
146
|
-
set_cookie: any;
|
|
147
|
-
rm_cookie: any;
|
|
148
|
-
status: any;
|
|
149
|
-
redirect: any;
|
|
150
|
-
error: any;
|
|
151
|
-
response: {
|
|
152
|
-
status: any;
|
|
153
|
-
message: string;
|
|
154
|
-
protocol: string;
|
|
155
|
-
context: string[];
|
|
156
|
-
params: object[];
|
|
157
|
-
data?: undefined;
|
|
158
|
-
};
|
|
159
|
-
} | {
|
|
160
|
-
header: {
|
|
161
|
-
key: string;
|
|
162
|
-
value: unknown;
|
|
163
|
-
}[];
|
|
164
|
-
set_cookie: any;
|
|
165
|
-
rm_cookie: any;
|
|
166
|
-
status: any;
|
|
167
|
-
redirect: any;
|
|
168
|
-
error: null;
|
|
169
|
-
response: {
|
|
170
|
-
status: any;
|
|
171
|
-
data: any;
|
|
172
|
-
message?: undefined;
|
|
173
|
-
protocol?: undefined;
|
|
174
|
-
context?: undefined;
|
|
175
|
-
params?: undefined;
|
|
176
|
-
};
|
|
177
|
-
}>;
|
|
178
|
-
}
|
package/cjs/lib/message.d.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { MessageKey, MessageValue, MessageLang, MessageLogic, MessageLogicLang, MessageErrorContext, MessageErrorContextOpt, MessageErrorContextSlug } from "../types/message.type";
|
|
2
|
-
/**
|
|
3
|
-
* @class MessageBuilder
|
|
4
|
-
* @description Handles multi-language response messages, error formatting, and dynamic template replacement.
|
|
5
|
-
* It allows the application to return consistent, localized messages across different platforms.
|
|
6
|
-
*/
|
|
7
|
-
export default class MessageBuilder {
|
|
8
|
-
private message_build_lang;
|
|
9
|
-
private message_logic;
|
|
10
|
-
/**
|
|
11
|
-
* @constructor
|
|
12
|
-
* @param {MessageLang} [language="en"] - The default language code (e.g., 'en', 'id').
|
|
13
|
-
* It will be sanitized to a 2-character lowercase string.
|
|
14
|
-
*/
|
|
15
|
-
constructor(language?: MessageLang);
|
|
16
|
-
/**
|
|
17
|
-
* @method set
|
|
18
|
-
* @description Registers a specific message template for the current active language.
|
|
19
|
-
* @param {MessageKey} key - The unique identifier for the message.
|
|
20
|
-
* @param {MessageValue} value - The message string (supports {{variable}} placeholders).
|
|
21
|
-
* @throws {Error} If key or value is not a string.
|
|
22
|
-
*/
|
|
23
|
-
set(key: MessageKey, value: MessageValue): void;
|
|
24
|
-
/**
|
|
25
|
-
* @method get
|
|
26
|
-
* @description Retrieves a raw message template based on the key and language.
|
|
27
|
-
* Falls back to the default language if the requested language is not found.
|
|
28
|
-
* @param {MessageKey} [key=""] - The message identifier to look up.
|
|
29
|
-
* @param {MessageLang} [lang=this.message_build_lang] - Optional language override.
|
|
30
|
-
* @returns {MessageValue} The raw message string or a fallback indicator if not found.
|
|
31
|
-
*/
|
|
32
|
-
get(key?: MessageKey, lang?: MessageLang): MessageValue;
|
|
33
|
-
/**
|
|
34
|
-
* @method errorMessage
|
|
35
|
-
* @description Processes a template by replacing {{key}} placeholders with actual values.
|
|
36
|
-
* @param {MessageErrorContextSlug} [errorSlug=""] - The message key/slug.
|
|
37
|
-
* @param {MessageErrorContextOpt} [errorOpt={}] - Object containing key-value pairs for replacement.
|
|
38
|
-
* @param {MessageLang} [lang=this.message_build_lang] - The language to use.
|
|
39
|
-
* @returns {string} The fully formatted message string.
|
|
40
|
-
*/
|
|
41
|
-
errorMessage(errorSlug?: MessageErrorContextSlug, errorOpt?: MessageErrorContextOpt, lang?: MessageLang): string;
|
|
42
|
-
/**
|
|
43
|
-
* @method error
|
|
44
|
-
* @description Parses a complex error string (protocol:slug|slug) and returns a structured error object.
|
|
45
|
-
* @param {MessageErrorContext} [errorStr=""] - The raw error string (e.g., "auth:user-not-found").
|
|
46
|
-
* @param {MessageErrorContextOpt[]} [errorOpts=[]] - Array of option objects for multiple slugs.
|
|
47
|
-
* @param {MessageLang} [lang=this.message_build_lang] - The target language.
|
|
48
|
-
* @returns {Object} Structured error containing protocol, context array, params, and the final joined message.
|
|
49
|
-
*/
|
|
50
|
-
error(errorStr?: MessageErrorContext, errorOpts?: MessageErrorContextOpt[], lang?: MessageLang): {
|
|
51
|
-
protocol: string;
|
|
52
|
-
context: string[];
|
|
53
|
-
params: object[];
|
|
54
|
-
message: string;
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* @method apply
|
|
58
|
-
* @description Returns the entire compiled message logic object.
|
|
59
|
-
* @returns {MessageLogicLang} The internal storage of languages and their messages.
|
|
60
|
-
*/
|
|
61
|
-
apply(): MessageLogicLang;
|
|
62
|
-
/**
|
|
63
|
-
* @method use
|
|
64
|
-
* @description Merges messages from another MessageBuilder instance or a plain object into the current one.
|
|
65
|
-
* @param {MessageBuilder | MessageLogic} input - The source of new messages.
|
|
66
|
-
* @throws {Error} If the input type is invalid.
|
|
67
|
-
*/
|
|
68
|
-
use(input: MessageBuilder | MessageLogic): void;
|
|
69
|
-
}
|
package/cjs/lib/policy.d.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { PolicyNoActionAPIAction, PolicyNoActionServerAction, PolicyNoActionKey, PolicyNoActionBase } from "../types/policy.type";
|
|
2
|
-
/**
|
|
3
|
-
* @class PolicyBuilder
|
|
4
|
-
* @description Manages application policies including security passkeys, version control,
|
|
5
|
-
* and protocol-specific action restrictions (Gatekeeping).
|
|
6
|
-
*/
|
|
7
|
-
export default class PolicyBuilder {
|
|
8
|
-
private passkey;
|
|
9
|
-
private version_now;
|
|
10
|
-
private version_min;
|
|
11
|
-
private version_forceupdate;
|
|
12
|
-
private noaction_api;
|
|
13
|
-
private noaction_server;
|
|
14
|
-
/**
|
|
15
|
-
* @constructor
|
|
16
|
-
* @param {Object} config - The policy configuration.
|
|
17
|
-
* @param {string} config.passkey - Secret key used for registry encryption (SHA-256).
|
|
18
|
-
* @param {string} config.version_now - The current stable version of the application.
|
|
19
|
-
* @param {string} config.version_min - The minimum required version for clients to operate.
|
|
20
|
-
* @param {boolean} [config.version_forceupdate=true] - Flag to indicate if clients below version_min must update.
|
|
21
|
-
* @throws {Error} If passkey, version_now, or version_min is missing.
|
|
22
|
-
*/
|
|
23
|
-
constructor({ passkey, version_now, version_min, version_forceupdate, }: {
|
|
24
|
-
passkey: string;
|
|
25
|
-
version_now: string;
|
|
26
|
-
version_min: string;
|
|
27
|
-
version_forceupdate?: boolean;
|
|
28
|
-
});
|
|
29
|
-
/**
|
|
30
|
-
* @method noaction
|
|
31
|
-
* @description Restricts specific action types from being accessed via certain protocols.
|
|
32
|
-
* @param {PolicyNoActionKey} [type=""] - The registry key/action type to restrict.
|
|
33
|
-
* @param {PolicyNoActionBase} [action=[]] - Array of protocols to block ('server-action' or 'api-action').
|
|
34
|
-
* @throws {Error} If the protocol type is invalid or the key is not a string.
|
|
35
|
-
*/
|
|
36
|
-
noaction(type?: PolicyNoActionKey, action?: PolicyNoActionBase): void;
|
|
37
|
-
/**
|
|
38
|
-
* @method compareVersions
|
|
39
|
-
* @private
|
|
40
|
-
* @description Compares two semantic version strings to determine their order.
|
|
41
|
-
* @param {string} v1 - First version string.
|
|
42
|
-
* @param {string} v2 - Second version string.
|
|
43
|
-
* @returns {number} 1 if v1 > v2, -1 if v1 < v2, and 0 if they are equal.
|
|
44
|
-
*/
|
|
45
|
-
private compareVersions;
|
|
46
|
-
/**
|
|
47
|
-
* @method version_info
|
|
48
|
-
* @description Checks a provided version against the minimum and current version requirements.
|
|
49
|
-
* @param {string} [version=""] - The version string to validate (usually from the client).
|
|
50
|
-
* @returns {Object} An object containing upgrade flags and version compatibility status.
|
|
51
|
-
*/
|
|
52
|
-
version_info(version?: string): {
|
|
53
|
-
info_upgrade: boolean;
|
|
54
|
-
is_version_min: boolean;
|
|
55
|
-
is_version_now: boolean;
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* @method apply
|
|
59
|
-
* @description Retrieves the compiled policy configuration.
|
|
60
|
-
* @returns {Object} All policy settings including restricted actions and versioning data.
|
|
61
|
-
*/
|
|
62
|
-
apply(): {
|
|
63
|
-
passkey: string;
|
|
64
|
-
version_now: string;
|
|
65
|
-
version_min: string;
|
|
66
|
-
version_forceupdate: boolean;
|
|
67
|
-
noaction_api: PolicyNoActionAPIAction;
|
|
68
|
-
noaction_server: PolicyNoActionServerAction;
|
|
69
|
-
};
|
|
70
|
-
}
|
package/cjs/lib/registry.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { RegistryKey, RegistryFunction, RegistryLogic, RegistryMiddleware } from "../types/registry.type";
|
|
2
|
-
/**
|
|
3
|
-
* @class RegistryBuilder
|
|
4
|
-
* @description Centralizes the mapping of unique action keys to their respective controllers
|
|
5
|
-
* and optional middlewares. It acts as the routing table for the Seishiro API system.
|
|
6
|
-
*/
|
|
7
|
-
export default class RegistryBuilder {
|
|
8
|
-
private registry_logic;
|
|
9
|
-
/**
|
|
10
|
-
* @constructor
|
|
11
|
-
* @description Initializes an empty registry storage.
|
|
12
|
-
*/
|
|
13
|
-
constructor();
|
|
14
|
-
/**
|
|
15
|
-
* @method set
|
|
16
|
-
* @description Registers a controller and an optional middleware to a specific key.
|
|
17
|
-
* If a middleware is provided, the registry will store them as an array [middleware, function].
|
|
18
|
-
* @param {RegistryKey} key - The unique identifier for the action (e.g., 'user:login').
|
|
19
|
-
* @param {RegistryFunction} function_regis - The main controller function to execute.
|
|
20
|
-
* @param {RegistryMiddleware} [middleware] - Optional middleware function to execute before the main controller.
|
|
21
|
-
* @throws {Error} If the controller is not a function or the key is not a string.
|
|
22
|
-
*/
|
|
23
|
-
set(key: RegistryKey, function_regis: RegistryFunction, middleware?: RegistryMiddleware): void;
|
|
24
|
-
/**
|
|
25
|
-
* @method get
|
|
26
|
-
* @description Retrieves the registered function(s) associated with a specific key.
|
|
27
|
-
* @param {RegistryKey} key - The key to look up in the registry.
|
|
28
|
-
* @returns {RegistryFunction | [RegistryMiddleware, RegistryFunction] | undefined}
|
|
29
|
-
* Returns a single function, an array containing [middleware, controller], or undefined if not found.
|
|
30
|
-
*/
|
|
31
|
-
get(key: RegistryKey): RegistryFunction | [RegistryMiddleware, RegistryFunction] | undefined;
|
|
32
|
-
/**
|
|
33
|
-
* @method apply
|
|
34
|
-
* @description Returns the raw internal registry logic mapping.
|
|
35
|
-
* @returns {RegistryLogic} The complete object mapping of keys to functions/middlewares.
|
|
36
|
-
*/
|
|
37
|
-
apply(): RegistryLogic;
|
|
38
|
-
/**
|
|
39
|
-
* @method use
|
|
40
|
-
* @description Merges another RegistryBuilder instance or a raw registry object into the current instance.
|
|
41
|
-
* This is useful for modularizing routes across different files.
|
|
42
|
-
* @param {RegistryBuilder | RegistryLogic} input - The source registry to be merged.
|
|
43
|
-
* @throws {Error} If the input is not a RegistryBuilder instance or a valid mapping object.
|
|
44
|
-
*/
|
|
45
|
-
use(input: RegistryBuilder | RegistryLogic): void;
|
|
46
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export type MessageKey = string;
|
|
2
|
-
export type MessageLang = string | "en" | "id";
|
|
3
|
-
export type MessageValue = string;
|
|
4
|
-
export type MessageErrorContext = string;
|
|
5
|
-
export type MessageErrorContextSlug = string;
|
|
6
|
-
export type MessageErrorContextOpt = object;
|
|
7
|
-
export type MessageErrorContextTrack = string;
|
|
8
|
-
export type MessageLogicLang = {
|
|
9
|
-
[key: MessageLang]: {
|
|
10
|
-
[key: MessageKey]: MessageValue;
|
|
11
|
-
};
|
|
12
|
-
};
|
|
13
|
-
export type MessageLogic = Record<MessageKey, MessageValue>;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export type PolicyPassKey = string;
|
|
2
|
-
export type PolicyVersionNow = string;
|
|
3
|
-
export type PolicyVersionMin = string;
|
|
4
|
-
export type PolicyVersionForceUpdate = boolean;
|
|
5
|
-
export type PolicyNoActionKey = string;
|
|
6
|
-
type AllowedActions = "server-action" | "api-action";
|
|
7
|
-
export type PolicyNoActionBase = AllowedActions[];
|
|
8
|
-
export type PolicyNoActionAPIAction = string[];
|
|
9
|
-
export type PolicyNoActionServerAction = string[];
|
|
10
|
-
export {};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export type RegistryKey = string;
|
|
2
|
-
export type RegistryParams = {
|
|
3
|
-
system: {
|
|
4
|
-
cookies: object;
|
|
5
|
-
headers: object;
|
|
6
|
-
ip: string;
|
|
7
|
-
location: string;
|
|
8
|
-
lang: string | "en";
|
|
9
|
-
};
|
|
10
|
-
type: RegistryKey;
|
|
11
|
-
middleware?: object | Function | Promise<any>;
|
|
12
|
-
data: object;
|
|
13
|
-
};
|
|
14
|
-
export type RegistryFunction = (params: RegistryParams) => any;
|
|
15
|
-
export type RegistryMiddleware = (params: RegistryParams) => any;
|
|
16
|
-
export type RegistryLogic = Record<RegistryKey, RegistryFunction | [RegistryMiddleware, RegistryFunction]>;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @function extractLanguage
|
|
3
|
-
* @description Parses the HTTP 'Accept-Language' header string into a clean array of unique language codes.
|
|
4
|
-
* It handles weights (q-values) and sub-tags (e.g., 'en-US' becomes 'en') to simplify language matching.
|
|
5
|
-
* * @param {string} [lang=""] - The raw Accept-Language header string (e.g., "en-US,en;q=0.9,id;q=0.8").
|
|
6
|
-
* @returns {string[]} An array of unique, two-letter language codes (e.g., ["en", "id"]).
|
|
7
|
-
* * @example
|
|
8
|
-
* extractLanguage("en-GB,en-US;q=0.9,id;q=0.8")
|
|
9
|
-
* // returns ["en", "id"]
|
|
10
|
-
*/
|
|
11
|
-
declare function extractLanguage(lang?: string): string[];
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @function formatKey
|
|
3
|
-
* @description Sanitizes and standardizes a string key by removing whitespace and illegal characters.
|
|
4
|
-
* It ensures that keys used in Registry, Message, and Policy builders remain consistent
|
|
5
|
-
* and safe for object property mapping.
|
|
6
|
-
* * @param {string} [strkey=""] - The raw string key to be formatted.
|
|
7
|
-
* @param {string} Returns a sanitized string containing only alphanumeric characters,
|
|
8
|
-
* hyphens (-), dots (.), and colons (:).
|
|
9
|
-
* * @example
|
|
10
|
-
* formatKey(" user:login @") // returns "user:login"
|
|
11
|
-
* formatKey("System-Error!") // returns "System-error"
|
|
12
|
-
*/
|
|
13
|
-
export default function formatKey(strkey?: string): string;
|