@apexkit/cli 1.0.3 → 1.0.4

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/LICENSE CHANGED
File without changes
package/README.md CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apexkit/cli",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
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
@@ -141,7 +141,157 @@ const TRIGGER_DEFINITIONS = [
141
141
  { id: "graphql", name: "graphql (Custom Resolver)", desc: "Dynamic Query/Mutation field resolver for GraphQL schema." }
142
142
  ];
143
143
 
144
- // --- 4. ACCURATE WORKSPACE TYPES & CONFIG GENERATOR ---
144
+ // --- 4. AUTOMATED REMOTE TYPE RESOLUTION & SCANNER ---
145
+ function scanWorkspaceForRemoteUrls() {
146
+ const urls = new Set();
147
+ const dirs = ["./webhooks", "./modules", "./templates"];
148
+ const urlRegex =
149
+ /(?:import|export)\s+(?:[\s\S]*?from\s+)?["'](https?:\/\/[^"']+)["']|import\s*\(\s*["'](https?:\/\/[^"']+)["']\s*\)|@jsxImportSource\s+(https?:\/\/[^\s*]+)/g;
150
+
151
+ dirs.forEach((dir) => {
152
+ if (!fs.existsSync(dir)) return;
153
+ const files = fs.readdirSync(dir, { recursive: true });
154
+ files.forEach((file) => {
155
+ const fullPath = path.join(dir, file);
156
+ if (fs.statSync(fullPath).isFile()) {
157
+ const ext = path.extname(fullPath);
158
+ if ([".js", ".ts", ".jsx", ".tsx", ".html"].includes(ext)) {
159
+ try {
160
+ const content = fs.readFileSync(fullPath, "utf-8");
161
+ let match;
162
+ while ((match = urlRegex.exec(content)) !== null) {
163
+ const url = match[1] || match[2] || match[3];
164
+ if (url) urls.add(url.trim());
165
+ }
166
+ } catch (e) {}
167
+ }
168
+ }
169
+ });
170
+ });
171
+
172
+ return Array.from(urls);
173
+ }
174
+
175
+ async function resolveRemoteTypeUrl(importUrl) {
176
+ try {
177
+ const res = await fetch(importUrl, {
178
+ method: "GET",
179
+ headers: { "User-Agent": "ApexKit-CLI/1.0" },
180
+ redirect: "follow",
181
+ });
182
+
183
+ const dtsHeader = res.headers.get("x-typescript-types");
184
+ if (dtsHeader) {
185
+ return dtsHeader.startsWith("http") ? dtsHeader : new URL(dtsHeader, importUrl).href;
186
+ }
187
+
188
+ if (importUrl.endsWith(".d.ts")) {
189
+ return importUrl;
190
+ }
191
+
192
+ if (importUrl.includes("esm.sh")) {
193
+ const dtsParamUrl = importUrl.includes("?") ? `${importUrl}&dts` : `${importUrl}?dts`;
194
+ const paramRes = await fetch(dtsParamUrl, { method: "HEAD", redirect: "follow" });
195
+ const paramHeader = paramRes.headers.get("x-typescript-types");
196
+ if (paramHeader) {
197
+ return paramHeader.startsWith("http") ? paramHeader : new URL(paramHeader, importUrl).href;
198
+ }
199
+ }
200
+ } catch (e) {}
201
+ return null;
202
+ }
203
+
204
+ /**
205
+ * Recursively fetches a .d.ts file and all relative imports/exports inside it
206
+ */
207
+ async function downloadDtsTree(currentDtsUrl, baseDir, relativeSubpath = "index.d.ts", visited = new Set()) {
208
+ if (visited.has(currentDtsUrl)) return;
209
+ visited.add(currentDtsUrl);
210
+
211
+ const localFilePath = path.join(baseDir, relativeSubpath);
212
+ fs.mkdirSync(path.dirname(localFilePath), { recursive: true });
213
+
214
+ try {
215
+ const res = await fetch(currentDtsUrl, {
216
+ headers: { "User-Agent": "ApexKit-CLI/1.0" },
217
+ redirect: "follow",
218
+ });
219
+ if (!res.ok) return;
220
+
221
+ let content = await res.text();
222
+
223
+ // Regex to locate relative imports or exports like:
224
+ // import { Hono } from './hono.d.ts';
225
+ // export * from './types.d.ts';
226
+ const relImportRegex = /(?:import|export)\s+[\s\S]*?from\s+["'](\.[^"']+)["']/g;
227
+ const relMatches = [];
228
+ let match;
229
+ while ((match = relImportRegex.exec(content)) !== null) {
230
+ relMatches.push(match[1]);
231
+ }
232
+
233
+ // Write file locally
234
+ fs.writeFileSync(localFilePath, content);
235
+
236
+ // Recursively pull all dependencies relative to current URL
237
+ for (const relPath of relMatches) {
238
+ // Normalize extension: ensure it resolves to .d.ts on the CDN
239
+ let targetRel = relPath;
240
+ if (!targetRel.endsWith(".d.ts") && !targetRel.endsWith(".ts")) {
241
+ targetRel = `${targetRel}.d.ts`;
242
+ }
243
+
244
+ const nextUrl = new URL(targetRel, currentDtsUrl).href;
245
+ const nextLocalSubpath = path.normalize(
246
+ path.join(path.dirname(relativeSubpath), targetRel.replace(/^\.\//, ""))
247
+ );
248
+
249
+ await downloadDtsTree(nextUrl, baseDir, nextLocalSubpath, visited);
250
+ }
251
+ } catch (err) {
252
+ console.warn(` ⚠️ Failed to recursively pull: ${currentDtsUrl} -> ${err.message}`);
253
+ }
254
+ }
255
+
256
+ async function pullRemoteModuleTypes(urls) {
257
+ const typesDir = path.join(".apexkit", "types");
258
+ fs.mkdirSync(typesDir, { recursive: true });
259
+
260
+ const resolvedPaths = {};
261
+
262
+ for (const rawUrl of urls) {
263
+ try {
264
+ // Use directory container for each package to support relative child imports cleanly
265
+ const urlFolder = rawUrl.replace(/[^a-zA-Z0-9_.-]/g, "_");
266
+ const packageDir = path.join(typesDir, urlFolder);
267
+ const rootDtsFile = path.join(packageDir, "index.d.ts");
268
+
269
+ if (fs.existsSync(rootDtsFile) && fs.statSync(rootDtsFile).size > 0) {
270
+ resolvedPaths[rawUrl] = `./${rootDtsFile.replace(/\\/g, "/")}`;
271
+ continue;
272
+ }
273
+
274
+ console.log(` 🌐 [Types]: Resolving remote type tree for ${rawUrl}...`);
275
+ const dtsUrl = await resolveRemoteTypeUrl(rawUrl);
276
+
277
+ if (dtsUrl) {
278
+ fs.mkdirSync(packageDir, { recursive: true });
279
+ await downloadDtsTree(dtsUrl, packageDir, "index.d.ts");
280
+
281
+ if (fs.existsSync(rootDtsFile)) {
282
+ resolvedPaths[rawUrl] = `./${rootDtsFile.replace(/\\/g, "/")}`;
283
+ console.log(` 📦 [Types]: Successfully cached dependency tree in ${packageDir}`);
284
+ }
285
+ }
286
+ } catch (err) {
287
+ console.warn(` ⚠️ Could not pull remote types for ${rawUrl}: ${err.message}`);
288
+ }
289
+ }
290
+
291
+ return resolvedPaths;
292
+ }
293
+
294
+ // --- 5. ACCURATE WORKSPACE TYPES & CONFIG GENERATOR ---
145
295
  async function generateWorkspaceFiles() {
146
296
  console.log(" ⏳ Fetching collection schemas from DB...");
147
297
  let collectionsData = [];
@@ -332,6 +482,13 @@ export interface FileMetadata {
332
482
  visibility?: ScriptVisibility;
333
483
  }
334
484
 
485
+ export type ApexKitDb = typeof $db;
486
+ export type ApexKitHttp = typeof $http;
487
+ export type ApexKitFiles = typeof $files;
488
+ export type ApexKitFs = typeof $fs;
489
+ export type ApexKitCache = typeof $cache;
490
+ export type ApexKitEnv = typeof $env;
491
+
335
492
  export interface AuthContext {
336
493
  id: number | string;
337
494
  email: string;
@@ -369,6 +526,19 @@ export interface VoidHookEvent {
369
526
  }
370
527
 
371
528
  declare global {
529
+ namespace JSX {
530
+ interface Element extends Promise<string>, String {
531
+ [key: string]: any;
532
+ toString(): string;
533
+ }
534
+ interface IntrinsicElements {
535
+ [elemName: string]: any;
536
+ }
537
+ interface ElementChildrenAttribute {
538
+ children: {};
539
+ }
540
+ }
541
+
372
542
  const __fileMetadata__: FileMetadata;
373
543
 
374
544
  /** ApexKit Database Client */
@@ -597,50 +767,122 @@ declare global {
597
767
  init?: { method?: string; headers?: any; body?: any; redirect?: "follow" | "manual" | "error" }
598
768
  ): Promise<Response>;
599
769
  }
770
+
771
+ // --- RUNTIME MODULE DEFINITIONS ---
772
+ declare module "react/jsx-runtime" {
773
+ export const jsx: any;
774
+ export const jsxs: any;
775
+ export const Fragment: any;
776
+ }
777
+
778
+ declare module "react/jsx-dev-runtime" {
779
+ export const jsxDEV: any;
780
+ export const Fragment: any;
781
+ }
782
+
783
+ declare module "hono/jsx/jsx-runtime" {
784
+ export const jsx: any;
785
+ export const jsxs: any;
786
+ export const Fragment: any;
787
+ }
788
+
789
+ declare module "hono/jsx" {
790
+ export const jsx: any;
791
+ export const jsxs: any;
792
+ export const Fragment: any;
793
+ export type FC<T = any> = (props: T) => any;
794
+ }
795
+
796
+ // --- HONO CONTEXT OVERLOADS ---
797
+ declare module "hono" {
798
+ interface Context {
799
+ html(html: string | Promise<string> | JSX.Element | any, status?: any, headers?: any): Response | Promise<Response>;
800
+ }
801
+ }
802
+
803
+ // --- REMOTE URL MODULE DECLARATIONS & FALLBACKS ---
804
+ declare module "https://*" {
805
+ const content: any;
806
+ export default content;
807
+ export * from "https://*";
808
+ }
809
+
810
+ declare module "http://*" {
811
+ const content: any;
812
+ export default content;
813
+ export * from "http://*";
814
+ }
815
+
600
816
  export {};
601
817
  `;
602
818
  fs.writeFileSync("apexkit.d.ts", types.trim());
603
- console.log(" 📄 Generated apexkit.d.ts with Accurate Scaled & Relational Typings");
819
+ console.log(" 📄 Generated apexkit.d.ts with Accurate Scaled Typings & Universal JSX");
820
+
821
+ // Dynamically scan all files and auto-pull remote module types
822
+ const remoteUrls = scanWorkspaceForRemoteUrls();
823
+ const resolvedRemoteTypes = await pullRemoteModuleTypes(remoteUrls);
824
+
825
+ const dynamicPaths = {
826
+ "@/custom/*": ["./modules/custom/*"],
827
+ "@/esm/*": ["./modules/esm/*"],
828
+ };
829
+
830
+ // Map each pulled remote URL to its local cached definition
831
+ for (const [remoteUrl, localPath] of Object.entries(resolvedRemoteTypes)) {
832
+ dynamicPaths[remoteUrl] = [localPath];
833
+ dynamicPaths[`${remoteUrl}/*`] = [`${localPath}/*`];
834
+ }
604
835
 
605
836
  const jsconfig = {
606
837
  compilerOptions: {
607
838
  target: "ES2022",
608
839
  module: "ESNext",
609
840
  ignoreDeprecations: "6.0",
610
- moduleResolution: "node",
841
+ moduleResolution: "bundler",
842
+ allowImportingTsExtensions: true,
843
+ jsx: "preserve",
611
844
  baseUrl: ".",
612
- paths: {
613
- "@/custom/*": ["./modules/custom/*"],
614
- "@/esm/*": ["./modules/esm/*"],
615
- },
845
+ paths: dynamicPaths,
616
846
  allowJs: true,
617
847
  checkJs: true,
618
848
  },
619
- include: ["**/*.js", "**/*.ts", "**/*.html", "apexkit.d.ts"],
849
+ include: [
850
+ "**/*.js",
851
+ "**/*.ts",
852
+ "**/*.jsx",
853
+ "**/*.tsx",
854
+ "**/*.html",
855
+ "apexkit.d.ts",
856
+ ".apexkit/types/**/*.d.ts",
857
+ ],
620
858
  };
621
859
  fs.writeFileSync("jsconfig.json", JSON.stringify(jsconfig, null, 2));
622
- console.log(" 📄 Generated jsconfig.json for module resolution");
860
+ console.log(" 📄 Generated jsconfig.json with Auto-Mapped Remote Types & JSX Support");
623
861
  }
624
862
 
625
863
  // --- 5. INITIAL CODE GENERATOR ---
626
864
  function getBoilerplateCode(fileType, cleanName, ext, triggerType, targetCollection) {
865
+ const metadataPath =
866
+ fileType === "template"
867
+ ? "./templates/"
868
+ : fileType.includes("module")
869
+ ? "./modules/custom/"
870
+ : "./webhooks/";
871
+
872
+ const typeImportPath = metadataPath.includes("modules/") ? "../../apexkit" : "../apexkit";
873
+
627
874
  const metadata = {
628
875
  name: cleanName,
629
876
  extension: ext,
630
877
  target_collection: targetCollection,
631
878
  type: fileType,
632
- path:
633
- fileType === "template"
634
- ? "./templates/"
635
- : fileType.includes("module")
636
- ? "./modules/custom/"
637
- : "./webhooks/",
879
+ path: metadataPath,
638
880
  trigger_type: triggerType,
639
881
  active: true,
640
882
  visibility: "private",
641
883
  };
642
884
 
643
- const header = `/** @type {import("../apexkit").FileMetadata} */\nexport const __fileMetadata__ = ${JSON.stringify(
885
+ const header = `/** @type {import("${typeImportPath}").FileMetadata} */\nexport const __fileMetadata__ = ${JSON.stringify(
644
886
  metadata,
645
887
  null,
646
888
  2
@@ -666,10 +908,11 @@ export function ${cleanName.replace(/-/g, "_")}(data = {}) {
666
908
  __fileMetadata__ = ${JSON.stringify(metadata, null, 2)}
667
909
  -->
668
910
  <script server>
669
- /// <reference path="../apexkit.d.ts" />
911
+ /** @type {import("../apexkit").ApexKitDb} */
912
+ const db = $db;
670
913
 
671
914
  export default async function (context) {
672
- const posts = await $db.records.list(\`${targetCollection || "posts"}\`, { limit: 10 }).catch(() => ({ items: [] }));
915
+ const posts = await db.records.list(\`${targetCollection || "posts"}\`, { limit: 10 }).catch(() => ({ items: [] }));
673
916
  return {
674
917
  title: \`${cleanName.replace(/-/g, " ").toUpperCase()}\`,
675
918
  items: posts.items
@@ -802,10 +1045,12 @@ async function runInitFile() {
802
1045
  }
803
1046
 
804
1047
  const cleanName = rawName.replace(/[^a-zA-Z0-9_-]/g, "");
805
- const ext =
1048
+ const allowedScriptExts = ["js", "ts", "jsx", "tsx"];
1049
+ const rawExt =
806
1050
  fileType === "template"
807
1051
  ? "html"
808
- : ((await rl.question("Extension (js/ts) [js]: ")).trim() || "js");
1052
+ : ((await rl.question("Extension (js/ts/jsx/tsx) [js]: ")).trim().toLowerCase() || "js");
1053
+ const ext = fileType === "template" ? "html" : (allowedScriptExts.includes(rawExt) ? rawExt : "js");
809
1054
 
810
1055
  let triggerType = "manual";
811
1056
  let targetCollection = null;
@@ -918,11 +1163,16 @@ async function runPull() {
918
1163
  const payload = await scriptRes.json();
919
1164
  const scripts = Array.isArray(payload) ? payload : payload.local || [];
920
1165
 
1166
+ const allowedScriptExts = ["js", "ts", "jsx", "tsx"];
1167
+
921
1168
  scripts.forEach((script) => {
1169
+ const remoteExt = script.metadata?.extension?.toLowerCase();
1170
+ const extension = allowedScriptExts.includes(remoteExt) ? remoteExt : "js";
1171
+
922
1172
  const meta = {
923
1173
  id: script.id,
924
1174
  name: script.name,
925
- extension: "js",
1175
+ extension: extension,
926
1176
  target_collection: script.target_collection || null,
927
1177
  type: script.metadata?.type || "webhook",
928
1178
  path: script.metadata?.path || "./webhooks/",
@@ -934,7 +1184,9 @@ async function runPull() {
934
1184
  const targetDir = meta.path.replace(/^\.\//, "");
935
1185
  fs.mkdirSync(targetDir, { recursive: true });
936
1186
 
937
- const formattedContent = `/** @type {import("../apexkit").FileMetadata} */\nexport const __fileMetadata__ = ${JSON.stringify(
1187
+ const typeImportPath = meta.path.includes("modules/") ? "../../apexkit" : "../apexkit";
1188
+
1189
+ const formattedContent = `/** @type {import("${typeImportPath}").FileMetadata} */\nexport const __fileMetadata__ = ${JSON.stringify(
938
1190
  meta,
939
1191
  null,
940
1192
  2
@@ -996,9 +1248,11 @@ async function runPull() {
996
1248
  console.warn(` ⚠️ AI Actions pull warning: ${e.message}`);
997
1249
  }
998
1250
 
1251
+ // Ensure .apexkit/types is ready and regenerate workspace definitions + remote types
1252
+ fs.mkdirSync(path.join(".apexkit", "types"), { recursive: true });
999
1253
  await generateWorkspaceFiles();
1000
1254
 
1001
- console.log(`\n✨ Pull complete! Hydrated ${pulledCount} items to local workspace.`);
1255
+ console.log(`\n✨ Pull complete! Hydrated ${pulledCount} items and resolved remote types.`);
1002
1256
  process.exit(0);
1003
1257
  }
1004
1258
 
@@ -1039,7 +1293,7 @@ function inferFileMetadata(filePath, content) {
1039
1293
  return content;
1040
1294
  }
1041
1295
 
1042
- // 3. Scripts / Webhooks / Modules -> JS Export metadata
1296
+ // 3. Scripts / Webhooks / Modules -> JS/TS/JSX/TSX Export metadata
1043
1297
  let deducedType = "webhook";
1044
1298
  let deducedPath = "./webhooks/";
1045
1299
  let deducedTrigger = "manual";
@@ -1052,7 +1306,7 @@ function inferFileMetadata(filePath, content) {
1052
1306
  deducedPath = "./modules/esm/";
1053
1307
  }
1054
1308
 
1055
- const jsMetaRe = /(?:export\s+const\s+__fileMetadata__\s*=\s*)(\{[\s\S]*?\});?/;
1309
+ const jsMetaRe = /(?:\/\*\*[\s\S]*?\*\/\s*)?export\s+const\s+__fileMetadata__\s*=\s*(\{[\s\S]*?\});?/;
1056
1310
  const match = content.match(jsMetaRe);
1057
1311
 
1058
1312
  let metaObj = {};
@@ -1062,9 +1316,14 @@ function inferFileMetadata(filePath, content) {
1062
1316
  } catch (e) {}
1063
1317
  }
1064
1318
 
1319
+ // Prioritize real file extension if js|ts|jsx|tsx, otherwise force to js
1320
+ const allowedScriptExts = ["js", "ts", "jsx", "tsx"];
1321
+ const fileExt = ext.toLowerCase();
1322
+ const prioritizedExt = allowedScriptExts.includes(fileExt) ? fileExt : "js";
1323
+
1065
1324
  const finalMeta = {
1066
1325
  name: metaObj.name || baseName,
1067
- extension: metaObj.extension || ext || "js",
1326
+ extension: prioritizedExt,
1068
1327
  target_collection: metaObj.target_collection || null,
1069
1328
  type: metaObj.type || deducedType,
1070
1329
  path: metaObj.path || deducedPath,
@@ -1073,12 +1332,20 @@ function inferFileMetadata(filePath, content) {
1073
1332
  visibility: metaObj.visibility || "private",
1074
1333
  };
1075
1334
 
1335
+ const typeImportPath = finalMeta.path.includes("modules/") ? "../../apexkit" : "../apexkit";
1336
+ const formattedMetadata = `/** @type {import("${typeImportPath}").FileMetadata} */\nexport const __fileMetadata__ = ${JSON.stringify(
1337
+ finalMeta,
1338
+ null,
1339
+ 2
1340
+ )};`;
1341
+
1076
1342
  if (!match) {
1077
- return `/** @type {import("../apexkit").FileMetadata} */\nexport const __fileMetadata__ = ${JSON.stringify(
1078
- finalMeta,
1079
- null,
1080
- 2
1081
- )};\n\n${content}`;
1343
+ return `${formattedMetadata}\n\n${content}`;
1344
+ }
1345
+
1346
+ // If metadata extension differed or needs updating, replace with prioritized definition
1347
+ if (metaObj.extension !== prioritizedExt || content.includes('import("../apexkit")') && typeImportPath.includes("../..")) {
1348
+ return content.replace(jsMetaRe, formattedMetadata);
1082
1349
  }
1083
1350
 
1084
1351
  return content;
@@ -1393,6 +1660,8 @@ function startWatcher() {
1393
1660
  if (
1394
1661
  filename.endsWith(".js") ||
1395
1662
  filename.endsWith(".ts") ||
1663
+ filename.endsWith(".jsx") ||
1664
+ filename.endsWith(".tsx") ||
1396
1665
  filename.endsWith(".html") ||
1397
1666
  filename.endsWith(".json")
1398
1667
  ) {