@apexkit/cli 1.0.4 → 1.0.5

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +61 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apexkit/cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "The official CLI and developer sync engine for ApexKit",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/index.js CHANGED
@@ -138,7 +138,10 @@ const TRIGGER_DEFINITIONS = [
138
138
  { id: "after_ai_run", name: "after_ai_run", desc: "Runs after AI Prompt execution." },
139
139
  { id: "on_vectorization_start", name: "on_vectorization_start", desc: "Fires when revectorization job begins." },
140
140
  { id: "cron", name: "cron (Scheduled Job)", desc: "Executed periodically according to Cron expression settings." },
141
- { id: "graphql", name: "graphql (Custom Resolver)", desc: "Dynamic Query/Mutation field resolver for GraphQL schema." }
141
+ { id: "graphql", name: "graphql (Custom Resolver)", desc: "Dynamic Query/Mutation field resolver for GraphQL schema." },
142
+ { id: "before_realtime_connection_established", name: "before_realtime_connection_established", desc: "Runs before an incoming SSE or WebSocket connection is accepted. Can block connections." },
143
+ { id: "before_realtime_data_pushed", name: "before_realtime_data_pushed", desc: "Intercepts and mutates real-time event payloads right before sending to a client." },
144
+ { id: "after_realtime_connection_desconnected", name: "after_realtime_connection_desconnected", desc: "Runs after an SSE or WebSocket client disconnects or connection is dropped." },
142
145
  ];
143
146
 
144
147
  // --- 4. AUTOMATED REMOTE TYPE RESOLUTION & SCANNER ---
@@ -999,6 +1002,62 @@ export default async function (event) {
999
1002
  data
1000
1003
  });
1001
1004
  }
1005
+ `;
1006
+
1007
+ case "before_realtime_connection_established":
1008
+ return `${header}/**
1009
+ * Hook: before_realtime_connection_established
1010
+ * Intercepts incoming Realtime connections before upgrading/accepting.
1011
+ *
1012
+ * @param {{ trigger: string, data: { ip: string, protocol: 'sse' | 'websocket', headers: Record<string, string> }, auth: import("${typeImportPath}").AuthContext | null }} event
1013
+ */
1014
+ export default async function (event) {
1015
+ const { ip, protocol, headers } = event.data;
1016
+
1017
+ // Example: Block suspicious user-agents or IPs (throwing an error drops the connection)
1018
+ // if (headers["user-agent"]?.includes("BadBot")) {
1019
+ // throw new Error("Connection denied");
1020
+ // }
1021
+
1022
+ return true;
1023
+ }
1024
+ `;
1025
+
1026
+ case "before_realtime_data_pushed":
1027
+ return `${header}/**
1028
+ * Hook: before_realtime_data_pushed
1029
+ * Intercepts event data just before broadcasting to the connected client.
1030
+ *
1031
+ * @param {{ trigger: string, data: any, auth: import("${typeImportPath}").AuthContext | null }} event
1032
+ * @returns {Promise<any>} Return modified payload, or throw an error to send an empty object {}
1033
+ */
1034
+ export default async function (event) {
1035
+ const eventPayload = event.data;
1036
+
1037
+ // Example: Redact sensitive information before the client receives it
1038
+ // (NOTE: $realtime.send is blocked inside this hook to avoid infinite loops)
1039
+ // if (eventPayload.data && eventPayload.data.internal_secret) {
1040
+ // delete eventPayload.data.internal_secret;
1041
+ // }
1042
+
1043
+ return eventPayload;
1044
+ }
1045
+ `;
1046
+
1047
+ case "after_realtime_connection_desconnected":
1048
+ return `${header}/**
1049
+ * Hook: after_realtime_connection_desconnected
1050
+ * Fires asynchronously when a client stream/socket disconnects or drops.
1051
+ *
1052
+ * @param {{ trigger: string, data: { ip: string, protocol: 'sse' | 'websocket', headers: Record<string, string> }, auth: import("${typeImportPath}").AuthContext | null }} event
1053
+ */
1054
+ export default async function (event) {
1055
+ const { ip, protocol } = event.data;
1056
+
1057
+ console.log(\`Client disconnected (\${protocol}) from \${ip}\`);
1058
+
1059
+ return true;
1060
+ }
1002
1061
  `;
1003
1062
 
1004
1063
  default:
@@ -1061,7 +1120,7 @@ async function runInitFile() {
1061
1120
  console.log(` ${String(i + 1).padStart(2, " ")}) ${t.name}`);
1062
1121
  });
1063
1122
 
1064
- const trigChoice = parseInt((await rl.question("\nChoice (1-42) [1]: ")).trim() || "1", 10);
1123
+ const trigChoice = parseInt((await rl.question("\nChoice (1-45) [1]: ")).trim() || "1", 10);
1065
1124
  const selectedTrig = TRIGGER_DEFINITIONS[trigChoice - 1] || TRIGGER_DEFINITIONS[0];
1066
1125
  triggerType = selectedTrig.id;
1067
1126