Skip to content

Commit 7c7d56f

Browse files
committed
Clean up spell manager demo (slightly)
1 parent dc63874 commit 7c7d56f

File tree

4 files changed

+483
-491
lines changed

4 files changed

+483
-491
lines changed
Lines changed: 127 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
import ts from 'typescript';
1+
import ts from "typescript";
22
import * as commonHtml from "@commontools/common-html";
33
import * as commonBuilder from "@commontools/common-builder";
44
import * as commonSystem from "@commontools/common-system";
55
import * as zod from "zod";
6-
import * as zodToJsonSchema from 'zod-to-json-schema';
6+
import * as zodToJsonSchema from "zod-to-json-schema";
77

88
import * as collectionSugar from "./sugar/build.js";
99
import * as querySugar from "./sugar/query.js";
1010
import * as eventSugar from "./sugar/event.js";
11+
import * as zodSugar from "./sugar/zod.js";
1112
import * as sugar from "./sugar.js";
13+
import * as spellUtil from "./spells/spell.jsx";
14+
import * as merkleReference from "merkle-reference";
1215

1316
// NOTE(ja): this isn't currently doing typechecking, but it could...
1417

@@ -20,126 +23,142 @@ import * as sugar from "./sugar.js";
2023
const importCache: Record<string, any> = {};
2124

2225
const ensureRequires = async (js: string): Promise<Record<string, any>> => {
23-
const requires = /require\((['"])([^'"]+)\1\)/g;
24-
const sagaCastorPattern = /https:\/\/paas\.saga-castor\.ts\.net\/blobby\/blob\/[^/]+\/src/;
25-
26-
const matches = [...js.matchAll(requires)];
27-
const localImports: Record<string, any> = {};
28-
for (const match of matches) {
29-
const modulePath = match[2];
30-
if (sagaCastorPattern.test(modulePath)) {
31-
if (!importCache[modulePath]) {
32-
// Fetch and compile the module
33-
const importSrc = await fetch(modulePath).then((resp) => resp.text());
34-
const importedModule = await tsToExports(importSrc);
35-
if (importedModule.errors) {
36-
throw new Error(`Failed to import ${modulePath}: ${importedModule.errors}`);
37-
}
38-
importCache[modulePath] = importedModule.exports;
39-
}
40-
localImports[modulePath] = importCache[modulePath];
26+
const requires = /require\((['"])([^'"]+)\1\)/g;
27+
const sagaCastorPattern =
28+
/https:\/\/paas\.saga-castor\.ts\.net\/blobby\/blob\/[^/]+\/src/;
29+
30+
const matches = [...js.matchAll(requires)];
31+
const localImports: Record<string, any> = {};
32+
for (const match of matches) {
33+
const modulePath = match[2];
34+
if (sagaCastorPattern.test(modulePath)) {
35+
if (!importCache[modulePath]) {
36+
// Fetch and compile the module
37+
const importSrc = await fetch(modulePath).then(resp => resp.text());
38+
const importedModule = await tsToExports(importSrc);
39+
if (importedModule.errors) {
40+
throw new Error(
41+
`Failed to import ${modulePath}: ${importedModule.errors}`,
42+
);
4143
}
44+
importCache[modulePath] = importedModule.exports;
45+
}
46+
localImports[modulePath] = importCache[modulePath];
4247
}
43-
return localImports;
44-
}
45-
46-
export const tsToExports = async (src: string): Promise<{ exports?: any, errors?: string }> => {
47-
48-
49-
// Add error handling for compilation
50-
const result = ts.transpileModule(src, {
51-
compilerOptions: {
52-
module: ts.ModuleKind.CommonJS,
53-
target: ts.ScriptTarget.ES2022,
54-
strict: true,
55-
jsx: ts.JsxEmit.React,
56-
jsxFactory: 'h',
57-
jsxFragmentFactory: 'Fragment',
58-
esModuleInterop: true,
59-
},
60-
reportDiagnostics: true
61-
});
62-
63-
// Check for compilation errors
64-
if (result.diagnostics && result.diagnostics.length > 0) {
65-
const errors = result.diagnostics.map(diagnostic => {
66-
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
67-
let locationInfo = '';
68-
69-
if (diagnostic.file && diagnostic.start !== undefined) {
70-
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
71-
locationInfo = `[${line + 1}:${character + 1}] `; // +1 because TypeScript uses 0-based positions
72-
}
73-
74-
return `Compilation Error: ${locationInfo}${message}`;
75-
}).join('\n');
76-
return { errors };
77-
}
48+
}
49+
return localImports;
50+
};
7851

79-
const js = result.outputText;
52+
export const tsToExports = async (
53+
src: string,
54+
): Promise<{ exports?: any; errors?: string }> => {
55+
// Add error handling for compilation
56+
const result = ts.transpileModule(src, {
57+
compilerOptions: {
58+
module: ts.ModuleKind.CommonJS,
59+
target: ts.ScriptTarget.ES2022,
60+
strict: true,
61+
jsx: ts.JsxEmit.React,
62+
jsxFactory: "h",
63+
jsxFragmentFactory: "Fragment",
64+
esModuleInterop: true,
65+
},
66+
reportDiagnostics: true,
67+
});
68+
69+
// Check for compilation errors
70+
if (result.diagnostics && result.diagnostics.length > 0) {
71+
const errors = result.diagnostics
72+
.map(diagnostic => {
73+
const message = ts.flattenDiagnosticMessageText(
74+
diagnostic.messageText,
75+
"\n",
76+
);
77+
let locationInfo = "";
78+
79+
if (diagnostic.file && diagnostic.start !== undefined) {
80+
const { line, character } =
81+
diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
82+
locationInfo = `[${line + 1}:${character + 1}] `; // +1 because TypeScript uses 0-based positions
83+
}
8084

81-
let localImports: Record<string, any> | undefined;
82-
try {
83-
localImports = await ensureRequires(js);
84-
} catch (e) {
85-
return { errors: (e as Error).message }
85+
return `Compilation Error: ${locationInfo}${message}`;
86+
})
87+
.join("\n");
88+
return { errors };
89+
}
90+
91+
const js = result.outputText;
92+
93+
let localImports: Record<string, any> | undefined;
94+
try {
95+
localImports = await ensureRequires(js);
96+
} catch (e) {
97+
return { errors: (e as Error).message };
98+
}
99+
100+
// Custom module resolution
101+
const customRequire = (moduleName: string) => {
102+
if (localImports[moduleName]) {
103+
return localImports[moduleName];
86104
}
105+
switch (moduleName) {
106+
case "../sugar/build.js":
107+
return collectionSugar;
108+
case "../sugar/query.js":
109+
return querySugar;
110+
case "../sugar/event.js":
111+
return eventSugar;
112+
case "../sugar/zod.js":
113+
return zodSugar;
114+
case "../sugar.js":
115+
return sugar;
116+
case "./spell.jsx":
117+
return spellUtil;
118+
case "@commontools/common-html":
119+
return commonHtml;
120+
case "@commontools/common-builder":
121+
return commonBuilder;
122+
case "@commontools/common-system":
123+
return commonSystem;
124+
case "zod":
125+
return zod;
126+
case "merkle-reference":
127+
return merkleReference;
128+
case "zod-to-json-schema":
129+
return zodToJsonSchema;
130+
default:
131+
throw new Error(`Module not found: ${moduleName}`);
132+
}
133+
};
87134

88-
// Custom module resolution
89-
const customRequire = (moduleName: string) => {
90-
if (localImports[moduleName]) {
91-
return localImports[moduleName];
92-
}
93-
switch (moduleName) {
94-
case "../sugar/build.js":
95-
return collectionSugar;
96-
case "../sugar/query.js":
97-
return querySugar;
98-
case "../sugar/event.js":
99-
return eventSugar;
100-
case "../sugar.js":
101-
return sugar;
102-
case "@commontools/common-html":
103-
return commonHtml;
104-
case "@commontools/common-builder":
105-
return commonBuilder;
106-
case "@commontools/common-system":
107-
return commonSystem;
108-
case "zod":
109-
return zod;
110-
case "zod-to-json-schema":
111-
return zodToJsonSchema;
112-
default:
113-
throw new Error(`Module not found: ${moduleName}`);
114-
}
115-
};
116-
117-
const wrappedCode = `
135+
const wrappedCode = `
118136
(function(require) {
119137
const exports = {};
120138
${js}
121139
return exports;
122140
})(${customRequire.toString()})`;
123141

124-
try {
125-
const exports = eval(wrappedCode);
126-
return { exports };
127-
} catch (e) {
128-
return { errors: (e as Error).message }
129-
}
130-
}
131-
142+
try {
143+
const exports = eval(wrappedCode);
144+
return { exports };
145+
} catch (e) {
146+
return { errors: (e as Error).message };
147+
}
148+
};
132149

133-
export const buildRecipe = async (src: string): Promise<{ recipe?: commonBuilder.Recipe, errors?: string }> => {
134-
if (!src) {
135-
return { errors: "No source code provided" }
136-
}
150+
export const buildRecipe = async (
151+
src: string,
152+
): Promise<{ recipe?: commonBuilder.Recipe; errors?: string }> => {
153+
if (!src) {
154+
return { errors: "No source code provided" };
155+
}
137156

138-
const { exports, errors } = await tsToExports(src);
157+
const { exports, errors } = await tsToExports(src);
139158

140-
if (errors) {
141-
return { errors }
142-
}
159+
if (errors) {
160+
return { errors };
161+
}
143162

144-
return { recipe: exports.default }
163+
return { recipe: exports.default };
145164
};

0 commit comments

Comments
 (0)