@apexkit/cli 1.0.2 → 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 +0 -0
- package/README.md +0 -0
- package/package.json +1 -1
- package/src/index.js +348 -31
package/LICENSE
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
File without changes
|
package/package.json
CHANGED
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.
|
|
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 */
|
|
@@ -528,10 +698,58 @@ declare global {
|
|
|
528
698
|
base64EncodeBuffer(buffer: ArrayBuffer | Uint8Array): string;
|
|
529
699
|
base64Decode(text: string): string;
|
|
530
700
|
base64DecodeBuffer(text: string): ArrayBuffer;
|
|
701
|
+
textEncode(text: string): ArrayBuffer;
|
|
702
|
+
textDecode(data: ArrayBuffer | Uint8Array): string;
|
|
703
|
+
hexEncode(data: string | ArrayBuffer | Uint8Array): string;
|
|
704
|
+
hexDecode(hex: string): ArrayBuffer;
|
|
531
705
|
sleep(ms: number): Promise<void>;
|
|
532
706
|
randomHex(len?: number): string;
|
|
533
707
|
};
|
|
534
708
|
|
|
709
|
+
/** Standard Web APIs */
|
|
710
|
+
const crypto: {
|
|
711
|
+
randomUUID(): string;
|
|
712
|
+
getRandomValues<T extends Int8Array | Int16Array | Int32Array | Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array | DataView | null>(array: T): T;
|
|
713
|
+
subtle: {
|
|
714
|
+
digest(algorithm: string | any, data: ArrayBuffer | Uint8Array): Promise<ArrayBuffer>;
|
|
715
|
+
importKey(format: string, keyData: any, algo: any, extractable: boolean, usages: string[]): Promise<any>;
|
|
716
|
+
sign(algorithm: string | any, key: any, data: ArrayBuffer | Uint8Array): Promise<ArrayBuffer>;
|
|
717
|
+
verify(algorithm: string | any, key: any, signature: ArrayBuffer | Uint8Array, data: ArrayBuffer | Uint8Array): Promise<boolean>;
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
class Blob {
|
|
722
|
+
constructor(sources?: any[], options?: any);
|
|
723
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
724
|
+
text(): Promise<string>;
|
|
725
|
+
readonly size: number;
|
|
726
|
+
readonly type: string;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
class ReadableStream {
|
|
730
|
+
constructor(underlyingSource?: any);
|
|
731
|
+
getReader(): any;
|
|
732
|
+
cancel(): Promise<void>;
|
|
733
|
+
readonly locked: boolean;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
const btoa: (data: string) => string;
|
|
737
|
+
const atob: (data: string) => string;
|
|
738
|
+
|
|
739
|
+
class TextEncoder {
|
|
740
|
+
constructor(encoding?: string);
|
|
741
|
+
encode(input?: string): Uint8Array;
|
|
742
|
+
encodeInto(source: string, destination: Uint8Array): { read: number; written: number };
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
class TextDecoder {
|
|
746
|
+
constructor(label?: string, options?: { fatal?: boolean; ignoreBOM?: boolean });
|
|
747
|
+
decode(input?: ArrayBuffer | Uint8Array, options?: { stream?: boolean }): string;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
function setTimeout(callback: Function, ms: number): string;
|
|
751
|
+
function clearTimeout(id: string): void;
|
|
752
|
+
|
|
535
753
|
/** Environment & Configuration Secrets Accessor */
|
|
536
754
|
const $env: {
|
|
537
755
|
get(key: string): Promise<string>;
|
|
@@ -549,50 +767,122 @@ declare global {
|
|
|
549
767
|
init?: { method?: string; headers?: any; body?: any; redirect?: "follow" | "manual" | "error" }
|
|
550
768
|
): Promise<Response>;
|
|
551
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
|
+
|
|
552
816
|
export {};
|
|
553
817
|
`;
|
|
554
818
|
fs.writeFileSync("apexkit.d.ts", types.trim());
|
|
555
|
-
console.log(" 📄 Generated apexkit.d.ts with Accurate Scaled &
|
|
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
|
+
}
|
|
556
835
|
|
|
557
836
|
const jsconfig = {
|
|
558
837
|
compilerOptions: {
|
|
559
838
|
target: "ES2022",
|
|
560
839
|
module: "ESNext",
|
|
561
840
|
ignoreDeprecations: "6.0",
|
|
562
|
-
moduleResolution: "
|
|
841
|
+
moduleResolution: "bundler",
|
|
842
|
+
allowImportingTsExtensions: true,
|
|
843
|
+
jsx: "preserve",
|
|
563
844
|
baseUrl: ".",
|
|
564
|
-
paths:
|
|
565
|
-
"@/custom/*": ["./modules/custom/*"],
|
|
566
|
-
"@/esm/*": ["./modules/esm/*"],
|
|
567
|
-
},
|
|
845
|
+
paths: dynamicPaths,
|
|
568
846
|
allowJs: true,
|
|
569
847
|
checkJs: true,
|
|
570
848
|
},
|
|
571
|
-
include: [
|
|
849
|
+
include: [
|
|
850
|
+
"**/*.js",
|
|
851
|
+
"**/*.ts",
|
|
852
|
+
"**/*.jsx",
|
|
853
|
+
"**/*.tsx",
|
|
854
|
+
"**/*.html",
|
|
855
|
+
"apexkit.d.ts",
|
|
856
|
+
".apexkit/types/**/*.d.ts",
|
|
857
|
+
],
|
|
572
858
|
};
|
|
573
859
|
fs.writeFileSync("jsconfig.json", JSON.stringify(jsconfig, null, 2));
|
|
574
|
-
console.log(" 📄 Generated jsconfig.json
|
|
860
|
+
console.log(" 📄 Generated jsconfig.json with Auto-Mapped Remote Types & JSX Support");
|
|
575
861
|
}
|
|
576
862
|
|
|
577
863
|
// --- 5. INITIAL CODE GENERATOR ---
|
|
578
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
|
+
|
|
579
874
|
const metadata = {
|
|
580
875
|
name: cleanName,
|
|
581
876
|
extension: ext,
|
|
582
877
|
target_collection: targetCollection,
|
|
583
878
|
type: fileType,
|
|
584
|
-
path:
|
|
585
|
-
fileType === "template"
|
|
586
|
-
? "./templates/"
|
|
587
|
-
: fileType.includes("module")
|
|
588
|
-
? "./modules/custom/"
|
|
589
|
-
: "./webhooks/",
|
|
879
|
+
path: metadataPath,
|
|
590
880
|
trigger_type: triggerType,
|
|
591
881
|
active: true,
|
|
592
882
|
visibility: "private",
|
|
593
883
|
};
|
|
594
884
|
|
|
595
|
-
const header = `/** @type {import("
|
|
885
|
+
const header = `/** @type {import("${typeImportPath}").FileMetadata} */\nexport const __fileMetadata__ = ${JSON.stringify(
|
|
596
886
|
metadata,
|
|
597
887
|
null,
|
|
598
888
|
2
|
|
@@ -618,10 +908,11 @@ export function ${cleanName.replace(/-/g, "_")}(data = {}) {
|
|
|
618
908
|
__fileMetadata__ = ${JSON.stringify(metadata, null, 2)}
|
|
619
909
|
-->
|
|
620
910
|
<script server>
|
|
621
|
-
|
|
911
|
+
/** @type {import("../apexkit").ApexKitDb} */
|
|
912
|
+
const db = $db;
|
|
622
913
|
|
|
623
914
|
export default async function (context) {
|
|
624
|
-
const posts = await
|
|
915
|
+
const posts = await db.records.list(\`${targetCollection || "posts"}\`, { limit: 10 }).catch(() => ({ items: [] }));
|
|
625
916
|
return {
|
|
626
917
|
title: \`${cleanName.replace(/-/g, " ").toUpperCase()}\`,
|
|
627
918
|
items: posts.items
|
|
@@ -754,10 +1045,12 @@ async function runInitFile() {
|
|
|
754
1045
|
}
|
|
755
1046
|
|
|
756
1047
|
const cleanName = rawName.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
757
|
-
const
|
|
1048
|
+
const allowedScriptExts = ["js", "ts", "jsx", "tsx"];
|
|
1049
|
+
const rawExt =
|
|
758
1050
|
fileType === "template"
|
|
759
1051
|
? "html"
|
|
760
|
-
: ((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");
|
|
761
1054
|
|
|
762
1055
|
let triggerType = "manual";
|
|
763
1056
|
let targetCollection = null;
|
|
@@ -870,11 +1163,16 @@ async function runPull() {
|
|
|
870
1163
|
const payload = await scriptRes.json();
|
|
871
1164
|
const scripts = Array.isArray(payload) ? payload : payload.local || [];
|
|
872
1165
|
|
|
1166
|
+
const allowedScriptExts = ["js", "ts", "jsx", "tsx"];
|
|
1167
|
+
|
|
873
1168
|
scripts.forEach((script) => {
|
|
1169
|
+
const remoteExt = script.metadata?.extension?.toLowerCase();
|
|
1170
|
+
const extension = allowedScriptExts.includes(remoteExt) ? remoteExt : "js";
|
|
1171
|
+
|
|
874
1172
|
const meta = {
|
|
875
1173
|
id: script.id,
|
|
876
1174
|
name: script.name,
|
|
877
|
-
extension:
|
|
1175
|
+
extension: extension,
|
|
878
1176
|
target_collection: script.target_collection || null,
|
|
879
1177
|
type: script.metadata?.type || "webhook",
|
|
880
1178
|
path: script.metadata?.path || "./webhooks/",
|
|
@@ -886,7 +1184,9 @@ async function runPull() {
|
|
|
886
1184
|
const targetDir = meta.path.replace(/^\.\//, "");
|
|
887
1185
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
888
1186
|
|
|
889
|
-
const
|
|
1187
|
+
const typeImportPath = meta.path.includes("modules/") ? "../../apexkit" : "../apexkit";
|
|
1188
|
+
|
|
1189
|
+
const formattedContent = `/** @type {import("${typeImportPath}").FileMetadata} */\nexport const __fileMetadata__ = ${JSON.stringify(
|
|
890
1190
|
meta,
|
|
891
1191
|
null,
|
|
892
1192
|
2
|
|
@@ -948,9 +1248,11 @@ async function runPull() {
|
|
|
948
1248
|
console.warn(` ⚠️ AI Actions pull warning: ${e.message}`);
|
|
949
1249
|
}
|
|
950
1250
|
|
|
1251
|
+
// Ensure .apexkit/types is ready and regenerate workspace definitions + remote types
|
|
1252
|
+
fs.mkdirSync(path.join(".apexkit", "types"), { recursive: true });
|
|
951
1253
|
await generateWorkspaceFiles();
|
|
952
1254
|
|
|
953
|
-
console.log(`\n✨ Pull complete! Hydrated ${pulledCount} items
|
|
1255
|
+
console.log(`\n✨ Pull complete! Hydrated ${pulledCount} items and resolved remote types.`);
|
|
954
1256
|
process.exit(0);
|
|
955
1257
|
}
|
|
956
1258
|
|
|
@@ -991,7 +1293,7 @@ function inferFileMetadata(filePath, content) {
|
|
|
991
1293
|
return content;
|
|
992
1294
|
}
|
|
993
1295
|
|
|
994
|
-
// 3. Scripts / Webhooks / Modules -> JS Export metadata
|
|
1296
|
+
// 3. Scripts / Webhooks / Modules -> JS/TS/JSX/TSX Export metadata
|
|
995
1297
|
let deducedType = "webhook";
|
|
996
1298
|
let deducedPath = "./webhooks/";
|
|
997
1299
|
let deducedTrigger = "manual";
|
|
@@ -1004,7 +1306,7 @@ function inferFileMetadata(filePath, content) {
|
|
|
1004
1306
|
deducedPath = "./modules/esm/";
|
|
1005
1307
|
}
|
|
1006
1308
|
|
|
1007
|
-
const jsMetaRe = /(
|
|
1309
|
+
const jsMetaRe = /(?:\/\*\*[\s\S]*?\*\/\s*)?export\s+const\s+__fileMetadata__\s*=\s*(\{[\s\S]*?\});?/;
|
|
1008
1310
|
const match = content.match(jsMetaRe);
|
|
1009
1311
|
|
|
1010
1312
|
let metaObj = {};
|
|
@@ -1014,9 +1316,14 @@ function inferFileMetadata(filePath, content) {
|
|
|
1014
1316
|
} catch (e) {}
|
|
1015
1317
|
}
|
|
1016
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
|
+
|
|
1017
1324
|
const finalMeta = {
|
|
1018
1325
|
name: metaObj.name || baseName,
|
|
1019
|
-
extension:
|
|
1326
|
+
extension: prioritizedExt,
|
|
1020
1327
|
target_collection: metaObj.target_collection || null,
|
|
1021
1328
|
type: metaObj.type || deducedType,
|
|
1022
1329
|
path: metaObj.path || deducedPath,
|
|
@@ -1025,12 +1332,20 @@ function inferFileMetadata(filePath, content) {
|
|
|
1025
1332
|
visibility: metaObj.visibility || "private",
|
|
1026
1333
|
};
|
|
1027
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
|
+
|
|
1028
1342
|
if (!match) {
|
|
1029
|
-
return
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
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);
|
|
1034
1349
|
}
|
|
1035
1350
|
|
|
1036
1351
|
return content;
|
|
@@ -1345,6 +1660,8 @@ function startWatcher() {
|
|
|
1345
1660
|
if (
|
|
1346
1661
|
filename.endsWith(".js") ||
|
|
1347
1662
|
filename.endsWith(".ts") ||
|
|
1663
|
+
filename.endsWith(".jsx") ||
|
|
1664
|
+
filename.endsWith(".tsx") ||
|
|
1348
1665
|
filename.endsWith(".html") ||
|
|
1349
1666
|
filename.endsWith(".json")
|
|
1350
1667
|
) {
|