@ttsc/playground 0.14.0-dev.20250530.1
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 +21 -0
- package/README.md +191 -0
- package/lib/src/compiler/DEFAULT_ENTRY_FILE.d.ts +2 -0
- package/lib/src/compiler/DEFAULT_ENTRY_FILE.js +6 -0
- package/lib/src/compiler/DEFAULT_ENTRY_FILE.js.map +1 -0
- package/lib/src/compiler/DEFAULT_LINT_PLUGIN_NAME.d.ts +5 -0
- package/lib/src/compiler/DEFAULT_LINT_PLUGIN_NAME.js +9 -0
- package/lib/src/compiler/DEFAULT_LINT_PLUGIN_NAME.js.map +1 -0
- package/lib/src/compiler/DEFAULT_PLAYGROUND_COMPILER_OPTIONS.d.ts +19 -0
- package/lib/src/compiler/DEFAULT_PLAYGROUND_COMPILER_OPTIONS.js +23 -0
- package/lib/src/compiler/DEFAULT_PLAYGROUND_COMPILER_OPTIONS.js.map +1 -0
- package/lib/src/compiler/DEFAULT_TSCONFIG_PATH.d.ts +2 -0
- package/lib/src/compiler/DEFAULT_TSCONFIG_PATH.js +6 -0
- package/lib/src/compiler/DEFAULT_TSCONFIG_PATH.js.map +1 -0
- package/lib/src/compiler/DEFAULT_TYPIA_PLUGIN_NAME.d.ts +6 -0
- package/lib/src/compiler/DEFAULT_TYPIA_PLUGIN_NAME.js +10 -0
- package/lib/src/compiler/DEFAULT_TYPIA_PLUGIN_NAME.js.map +1 -0
- package/lib/src/compiler/DEFAULT_WORK_DIR.d.ts +2 -0
- package/lib/src/compiler/DEFAULT_WORK_DIR.js +6 -0
- package/lib/src/compiler/DEFAULT_WORK_DIR.js.map +1 -0
- package/lib/src/compiler/buildTsconfigJSON.d.ts +9 -0
- package/lib/src/compiler/buildTsconfigJSON.js +24 -0
- package/lib/src/compiler/buildTsconfigJSON.js.map +1 -0
- package/lib/src/compiler/createTypiaSourcePackMount.d.ts +11 -0
- package/lib/src/compiler/createTypiaSourcePackMount.js +29 -0
- package/lib/src/compiler/createTypiaSourcePackMount.js.map +1 -0
- package/lib/src/compiler/createWorkerCompiler.d.ts +25 -0
- package/lib/src/compiler/createWorkerCompiler.js +227 -0
- package/lib/src/compiler/createWorkerCompiler.js.map +1 -0
- package/lib/src/compiler/installDependenciesIntoMemFS.d.ts +12 -0
- package/lib/src/compiler/installDependenciesIntoMemFS.js +25 -0
- package/lib/src/compiler/installDependenciesIntoMemFS.js.map +1 -0
- package/lib/src/compiler/installTypiaSourcePack.d.ts +11 -0
- package/lib/src/compiler/installTypiaSourcePack.js +21 -0
- package/lib/src/compiler/installTypiaSourcePack.js.map +1 -0
- package/lib/src/compiler/internal/joinUnder.d.ts +5 -0
- package/lib/src/compiler/internal/joinUnder.js +13 -0
- package/lib/src/compiler/internal/joinUnder.js.map +1 -0
- package/lib/src/compiler/internal/parseLintDiagnostics.d.ts +6 -0
- package/lib/src/compiler/internal/parseLintDiagnostics.js +57 -0
- package/lib/src/compiler/internal/parseLintDiagnostics.js.map +1 -0
- package/lib/src/compiler/internal/safeParseTypiaTransform.d.ts +11 -0
- package/lib/src/compiler/internal/safeParseTypiaTransform.js +21 -0
- package/lib/src/compiler/internal/safeParseTypiaTransform.js.map +1 -0
- package/lib/src/compiler/lineColumnOf.d.ts +5 -0
- package/lib/src/compiler/lineColumnOf.js +15 -0
- package/lib/src/compiler/lineColumnOf.js.map +1 -0
- package/lib/src/compiler/loadTypiaSourcePack.d.ts +8 -0
- package/lib/src/compiler/loadTypiaSourcePack.js +33 -0
- package/lib/src/compiler/loadTypiaSourcePack.js.map +1 -0
- package/lib/src/compiler/mapDiagnostic.d.ts +9 -0
- package/lib/src/compiler/mapDiagnostic.js +22 -0
- package/lib/src/compiler/mapDiagnostic.js.map +1 -0
- package/lib/src/compiler/normalizeError.d.ts +2 -0
- package/lib/src/compiler/normalizeError.js +14 -0
- package/lib/src/compiler/normalizeError.js.map +1 -0
- package/lib/src/compiler/normalizeNodeModulePath.d.ts +8 -0
- package/lib/src/compiler/normalizeNodeModulePath.js +19 -0
- package/lib/src/compiler/normalizeNodeModulePath.js.map +1 -0
- package/lib/src/compiler/pickEmittedJS.d.ts +6 -0
- package/lib/src/compiler/pickEmittedJS.js +21 -0
- package/lib/src/compiler/pickEmittedJS.js.map +1 -0
- package/lib/src/index.d.ts +47 -0
- package/lib/src/index.js +104 -0
- package/lib/src/index.js.map +1 -0
- package/lib/src/npm/BUILT_IN_PLAYGROUND_PACKAGES.d.ts +6 -0
- package/lib/src/npm/BUILT_IN_PLAYGROUND_PACKAGES.js +15 -0
- package/lib/src/npm/BUILT_IN_PLAYGROUND_PACKAGES.js.map +1 -0
- package/lib/src/npm/collectExternalPackageNames.d.ts +5 -0
- package/lib/src/npm/collectExternalPackageNames.js +34 -0
- package/lib/src/npm/collectExternalPackageNames.js.map +1 -0
- package/lib/src/npm/installPlaygroundDependencies.d.ts +13 -0
- package/lib/src/npm/installPlaygroundDependencies.js +121 -0
- package/lib/src/npm/installPlaygroundDependencies.js.map +1 -0
- package/lib/src/npm/internal/npmRegistry.d.ts +57 -0
- package/lib/src/npm/internal/npmRegistry.js +216 -0
- package/lib/src/npm/internal/npmRegistry.js.map +1 -0
- package/lib/src/npm/packageNameFromSpecifier.d.ts +7 -0
- package/lib/src/npm/packageNameFromSpecifier.js +66 -0
- package/lib/src/npm/packageNameFromSpecifier.js.map +1 -0
- package/lib/src/react/ConsoleViewer.d.ts +7 -0
- package/lib/src/react/ConsoleViewer.js +57 -0
- package/lib/src/react/ConsoleViewer.js.map +1 -0
- package/lib/src/react/DEFAULT_OPTION_TOGGLES.d.ts +3 -0
- package/lib/src/react/DEFAULT_OPTION_TOGGLES.js +17 -0
- package/lib/src/react/DEFAULT_OPTION_TOGGLES.js.map +1 -0
- package/lib/src/react/DependencyProgressModal.d.ts +7 -0
- package/lib/src/react/DependencyProgressModal.js +16 -0
- package/lib/src/react/DependencyProgressModal.js.map +1 -0
- package/lib/src/react/DiagnosticsPanel.d.ts +4 -0
- package/lib/src/react/DiagnosticsPanel.js +15 -0
- package/lib/src/react/DiagnosticsPanel.js.map +1 -0
- package/lib/src/react/ExamplePicker.d.ts +9 -0
- package/lib/src/react/ExamplePicker.js +43 -0
- package/lib/src/react/ExamplePicker.js.map +1 -0
- package/lib/src/react/LintPane.d.ts +9 -0
- package/lib/src/react/LintPane.js +17 -0
- package/lib/src/react/LintPane.js.map +1 -0
- package/lib/src/react/OptionsPanel.d.ts +13 -0
- package/lib/src/react/OptionsPanel.js +43 -0
- package/lib/src/react/OptionsPanel.js.map +1 -0
- package/lib/src/react/PlaygroundShell.d.ts +2 -0
- package/lib/src/react/PlaygroundShell.js +609 -0
- package/lib/src/react/PlaygroundShell.js.map +1 -0
- package/lib/src/react/ResultViewer.d.ts +10 -0
- package/lib/src/react/ResultViewer.js +49 -0
- package/lib/src/react/ResultViewer.js.map +1 -0
- package/lib/src/react/SourceEditor.d.ts +2 -0
- package/lib/src/react/SourceEditor.js +74 -0
- package/lib/src/react/SourceEditor.js.map +1 -0
- package/lib/src/react/createCompilerClient.d.ts +14 -0
- package/lib/src/react/createCompilerClient.js +77 -0
- package/lib/src/react/createCompilerClient.js.map +1 -0
- package/lib/src/sandbox/createSandboxRequire.d.ts +11 -0
- package/lib/src/sandbox/createSandboxRequire.js +211 -0
- package/lib/src/sandbox/createSandboxRequire.js.map +1 -0
- package/lib/src/sandbox/loadTypiaRuntimePack.d.ts +7 -0
- package/lib/src/sandbox/loadTypiaRuntimePack.js +35 -0
- package/lib/src/sandbox/loadTypiaRuntimePack.js.map +1 -0
- package/lib/src/structures/IBuildTsconfigOptions.d.ts +19 -0
- package/lib/src/structures/IBuildTsconfigOptions.js +3 -0
- package/lib/src/structures/IBuildTsconfigOptions.js.map +1 -0
- package/lib/src/structures/ICompilerService.d.ts +84 -0
- package/lib/src/structures/ICompilerService.js +3 -0
- package/lib/src/structures/ICompilerService.js.map +1 -0
- package/lib/src/structures/IConsoleMessage.d.ts +10 -0
- package/lib/src/structures/IConsoleMessage.js +3 -0
- package/lib/src/structures/IConsoleMessage.js.map +1 -0
- package/lib/src/structures/ICreateCompilerClientOptions.d.ts +13 -0
- package/lib/src/structures/ICreateCompilerClientOptions.js +3 -0
- package/lib/src/structures/ICreateCompilerClientOptions.js.map +1 -0
- package/lib/src/structures/ICreateWorkerCompilerOptions.d.ts +35 -0
- package/lib/src/structures/ICreateWorkerCompilerOptions.js +3 -0
- package/lib/src/structures/ICreateWorkerCompilerOptions.js.map +1 -0
- package/lib/src/structures/IInstallTypiaSourcePackOptions.d.ts +18 -0
- package/lib/src/structures/IInstallTypiaSourcePackOptions.js +3 -0
- package/lib/src/structures/IInstallTypiaSourcePackOptions.js.map +1 -0
- package/lib/src/structures/ILintPluginConfig.d.ts +5 -0
- package/lib/src/structures/ILintPluginConfig.js +3 -0
- package/lib/src/structures/ILintPluginConfig.js.map +1 -0
- package/lib/src/structures/IOptionToggle.d.ts +12 -0
- package/lib/src/structures/IOptionToggle.js +3 -0
- package/lib/src/structures/IOptionToggle.js.map +1 -0
- package/lib/src/structures/IPlaygroundDependencyInstallOptions.d.ts +16 -0
- package/lib/src/structures/IPlaygroundDependencyInstallOptions.js +3 -0
- package/lib/src/structures/IPlaygroundDependencyInstallOptions.js.map +1 -0
- package/lib/src/structures/IPlaygroundDependencyInstallResult.d.ts +20 -0
- package/lib/src/structures/IPlaygroundDependencyInstallResult.js +3 -0
- package/lib/src/structures/IPlaygroundDependencyInstallResult.js.map +1 -0
- package/lib/src/structures/IPlaygroundDependencyPackage.d.ts +8 -0
- package/lib/src/structures/IPlaygroundDependencyPackage.js +3 -0
- package/lib/src/structures/IPlaygroundDependencyPackage.js.map +1 -0
- package/lib/src/structures/IPlaygroundDependencyProgress.d.ts +10 -0
- package/lib/src/structures/IPlaygroundDependencyProgress.js +3 -0
- package/lib/src/structures/IPlaygroundDependencyProgress.js.map +1 -0
- package/lib/src/structures/IPlaygroundDependencyProgressPhase.d.ts +5 -0
- package/lib/src/structures/IPlaygroundDependencyProgressPhase.js +3 -0
- package/lib/src/structures/IPlaygroundDependencyProgressPhase.js.map +1 -0
- package/lib/src/structures/IPlaygroundExample.d.ts +16 -0
- package/lib/src/structures/IPlaygroundExample.js +3 -0
- package/lib/src/structures/IPlaygroundExample.js.map +1 -0
- package/lib/src/structures/IPlaygroundShellProps.d.ts +70 -0
- package/lib/src/structures/IPlaygroundShellProps.js +3 -0
- package/lib/src/structures/IPlaygroundShellProps.js.map +1 -0
- package/lib/src/structures/ISourceEditorProps.d.ts +18 -0
- package/lib/src/structures/ISourceEditorProps.js +3 -0
- package/lib/src/structures/ISourceEditorProps.js.map +1 -0
- package/lib/src/structures/ITransformOptions.d.ts +15 -0
- package/lib/src/structures/ITransformOptions.js +3 -0
- package/lib/src/structures/ITransformOptions.js.map +1 -0
- package/lib/src/structures/ITypiaPluginConfig.d.ts +19 -0
- package/lib/src/structures/ITypiaPluginConfig.js +3 -0
- package/lib/src/structures/ITypiaPluginConfig.js.map +1 -0
- package/lib/src/structures/index.d.ts +18 -0
- package/lib/src/structures/index.js +35 -0
- package/lib/src/structures/index.js.map +1 -0
- package/package.json +66 -0
- package/src/compiler/DEFAULT_ENTRY_FILE.ts +2 -0
- package/src/compiler/DEFAULT_LINT_PLUGIN_NAME.ts +5 -0
- package/src/compiler/DEFAULT_PLAYGROUND_COMPILER_OPTIONS.ts +19 -0
- package/src/compiler/DEFAULT_TSCONFIG_PATH.ts +2 -0
- package/src/compiler/DEFAULT_TYPIA_PLUGIN_NAME.ts +6 -0
- package/src/compiler/DEFAULT_WORK_DIR.ts +2 -0
- package/src/compiler/buildTsconfigJSON.ts +22 -0
- package/src/compiler/createTypiaSourcePackMount.ts +32 -0
- package/src/compiler/createWorkerCompiler.ts +273 -0
- package/src/compiler/installDependenciesIntoMemFS.ts +28 -0
- package/src/compiler/installTypiaSourcePack.ts +24 -0
- package/src/compiler/internal/joinUnder.ts +8 -0
- package/src/compiler/internal/parseLintDiagnostics.ts +61 -0
- package/src/compiler/internal/safeParseTypiaTransform.ts +24 -0
- package/src/compiler/lineColumnOf.ts +14 -0
- package/src/compiler/loadTypiaSourcePack.ts +37 -0
- package/src/compiler/mapDiagnostic.ts +26 -0
- package/src/compiler/normalizeError.ts +12 -0
- package/src/compiler/normalizeNodeModulePath.ts +13 -0
- package/src/compiler/pickEmittedJS.ts +18 -0
- package/src/index.ts +57 -0
- package/src/npm/BUILT_IN_PLAYGROUND_PACKAGES.ts +11 -0
- package/src/npm/collectExternalPackageNames.ts +34 -0
- package/src/npm/installPlaygroundDependencies.ts +163 -0
- package/src/npm/internal/npmRegistry.ts +292 -0
- package/src/npm/packageNameFromSpecifier.ts +61 -0
- package/src/react/ConsoleViewer.tsx +121 -0
- package/src/react/DEFAULT_OPTION_TOGGLES.ts +15 -0
- package/src/react/DependencyProgressModal.tsx +73 -0
- package/src/react/DiagnosticsPanel.tsx +74 -0
- package/src/react/ExamplePicker.tsx +93 -0
- package/src/react/LintPane.tsx +58 -0
- package/src/react/OptionsPanel.tsx +132 -0
- package/src/react/PlaygroundShell.tsx +864 -0
- package/src/react/ResultViewer.tsx +75 -0
- package/src/react/SourceEditor.tsx +96 -0
- package/src/react/createCompilerClient.ts +80 -0
- package/src/sandbox/createSandboxRequire.ts +275 -0
- package/src/sandbox/loadTypiaRuntimePack.ts +36 -0
- package/src/structures/IBuildTsconfigOptions.ts +19 -0
- package/src/structures/ICompilerService.ts +96 -0
- package/src/structures/IConsoleMessage.ts +10 -0
- package/src/structures/ICreateCompilerClientOptions.ts +13 -0
- package/src/structures/ICreateWorkerCompilerOptions.ts +40 -0
- package/src/structures/IInstallTypiaSourcePackOptions.ts +18 -0
- package/src/structures/ILintPluginConfig.ts +5 -0
- package/src/structures/IOptionToggle.ts +12 -0
- package/src/structures/IPlaygroundDependencyInstallOptions.ts +17 -0
- package/src/structures/IPlaygroundDependencyInstallResult.ts +21 -0
- package/src/structures/IPlaygroundDependencyPackage.ts +8 -0
- package/src/structures/IPlaygroundDependencyProgress.ts +11 -0
- package/src/structures/IPlaygroundDependencyProgressPhase.ts +12 -0
- package/src/structures/IPlaygroundExample.ts +16 -0
- package/src/structures/IPlaygroundShellProps.ts +83 -0
- package/src/structures/ISourceEditorProps.ts +18 -0
- package/src/structures/ITransformOptions.ts +15 -0
- package/src/structures/ITypiaPluginConfig.ts +20 -0
- package/src/structures/index.ts +18 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Editor from "@monaco-editor/react";
|
|
4
|
+
import { useEffect, useRef, useState } from "react";
|
|
5
|
+
|
|
6
|
+
interface ResultViewerProps {
|
|
7
|
+
language: "typescript" | "javascript" | "json";
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Read-only Monaco pane used to render the compiled / transformed output
|
|
13
|
+
* with a copy button. Wraps `<Editor readOnly>` and adds the toast UI.
|
|
14
|
+
*/
|
|
15
|
+
export function ResultViewer({ language, value }: ResultViewerProps) {
|
|
16
|
+
const [copied, setCopied] = useState(false);
|
|
17
|
+
const copiedTimer = useRef<number | null>(null);
|
|
18
|
+
|
|
19
|
+
useEffect(
|
|
20
|
+
() => () => {
|
|
21
|
+
if (copiedTimer.current !== null)
|
|
22
|
+
window.clearTimeout(copiedTimer.current);
|
|
23
|
+
},
|
|
24
|
+
[],
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const onCopy = () => {
|
|
28
|
+
void navigator.clipboard.writeText(value);
|
|
29
|
+
setCopied(true);
|
|
30
|
+
if (copiedTimer.current !== null) window.clearTimeout(copiedTimer.current);
|
|
31
|
+
copiedTimer.current = window.setTimeout(() => {
|
|
32
|
+
setCopied(false);
|
|
33
|
+
copiedTimer.current = null;
|
|
34
|
+
}, 1500);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div className="relative h-full w-full">
|
|
39
|
+
{value && (
|
|
40
|
+
<button
|
|
41
|
+
onClick={onCopy}
|
|
42
|
+
className="absolute top-2 right-3 z-10 px-2 py-1 text-[10px] font-mono text-neutral-300 bg-neutral-900/80 border border-neutral-700 rounded-md hover:bg-neutral-800 transition-colors"
|
|
43
|
+
>
|
|
44
|
+
{copied ? "Copied ✓" : "Copy"}
|
|
45
|
+
</button>
|
|
46
|
+
)}
|
|
47
|
+
<Editor
|
|
48
|
+
height="100%"
|
|
49
|
+
language={language}
|
|
50
|
+
theme="vs-dark"
|
|
51
|
+
value={value}
|
|
52
|
+
path={`output.${
|
|
53
|
+
language === "typescript"
|
|
54
|
+
? "ts"
|
|
55
|
+
: language === "javascript"
|
|
56
|
+
? "js"
|
|
57
|
+
: "json"
|
|
58
|
+
}`}
|
|
59
|
+
options={{
|
|
60
|
+
readOnly: true,
|
|
61
|
+
tabSize: 2,
|
|
62
|
+
minimap: { enabled: false },
|
|
63
|
+
padding: { top: 12, bottom: 12 },
|
|
64
|
+
fontSize: 13,
|
|
65
|
+
fontFamily:
|
|
66
|
+
"ui-monospace, SFMono-Regular, 'JetBrains Mono', 'Fira Code', Consolas, monospace",
|
|
67
|
+
smoothScrolling: true,
|
|
68
|
+
scrollBeyondLastLine: false,
|
|
69
|
+
renderLineHighlight: "none",
|
|
70
|
+
wordWrap: "on",
|
|
71
|
+
}}
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Editor, { type Monaco } from "@monaco-editor/react";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
5
|
+
|
|
6
|
+
import { DEFAULT_PLAYGROUND_COMPILER_OPTIONS } from "../compiler/DEFAULT_PLAYGROUND_COMPILER_OPTIONS";
|
|
7
|
+
import type { ISourceEditorProps } from "../structures/ISourceEditorProps";
|
|
8
|
+
|
|
9
|
+
export function SourceEditor({
|
|
10
|
+
value,
|
|
11
|
+
onChange,
|
|
12
|
+
extraLibs,
|
|
13
|
+
path = "file:///src/playground.ts",
|
|
14
|
+
}: ISourceEditorProps) {
|
|
15
|
+
const monacoRef = useRef<Monaco | null>(null);
|
|
16
|
+
const libDisposables = useRef<{ dispose(): void }[]>([]);
|
|
17
|
+
const allExtraLibs = useMemo(
|
|
18
|
+
() => (extraLibs ? Object.entries(extraLibs) : []),
|
|
19
|
+
[extraLibs],
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const installExtraLibs = useCallback(
|
|
23
|
+
(monaco: Monaco) => {
|
|
24
|
+
for (const disposable of libDisposables.current) disposable.dispose();
|
|
25
|
+
libDisposables.current = [];
|
|
26
|
+
const tsd = monaco.languages.typescript.typescriptDefaults;
|
|
27
|
+
for (const [file, content] of allExtraLibs) {
|
|
28
|
+
libDisposables.current.push(tsd.addExtraLib(content, file));
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
[allExtraLibs],
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (monacoRef.current) installExtraLibs(monacoRef.current);
|
|
36
|
+
return () => {
|
|
37
|
+
for (const disposable of libDisposables.current) disposable.dispose();
|
|
38
|
+
libDisposables.current = [];
|
|
39
|
+
};
|
|
40
|
+
}, [installExtraLibs]);
|
|
41
|
+
|
|
42
|
+
const handleMount = (_editor: unknown, monaco: Monaco) => {
|
|
43
|
+
monacoRef.current = monaco;
|
|
44
|
+
const tsd = monaco.languages.typescript.typescriptDefaults;
|
|
45
|
+
tsd.setCompilerOptions({
|
|
46
|
+
target: monaco.languages.typescript.ScriptTarget.ESNext,
|
|
47
|
+
module: monaco.languages.typescript.ModuleKind.ESNext,
|
|
48
|
+
moduleResolution:
|
|
49
|
+
monaco.languages.typescript.ModuleResolutionKind.NodeJs,
|
|
50
|
+
esModuleInterop: DEFAULT_PLAYGROUND_COMPILER_OPTIONS.esModuleInterop,
|
|
51
|
+
strict: DEFAULT_PLAYGROUND_COMPILER_OPTIONS.strict,
|
|
52
|
+
experimentalDecorators:
|
|
53
|
+
DEFAULT_PLAYGROUND_COMPILER_OPTIONS.experimentalDecorators,
|
|
54
|
+
allowNonTsExtensions: true,
|
|
55
|
+
// External .d.ts packs (typia, etc.) routinely reference transitive types
|
|
56
|
+
// Monaco cannot reach (deep paths in JSDoc, optional peers). skipLibCheck
|
|
57
|
+
// keeps the editor lean by not type-checking the lib pack.
|
|
58
|
+
skipLibCheck: true,
|
|
59
|
+
});
|
|
60
|
+
tsd.setDiagnosticsOptions({
|
|
61
|
+
noSemanticValidation: false,
|
|
62
|
+
noSyntaxValidation: false,
|
|
63
|
+
diagnosticCodesToIgnore: [
|
|
64
|
+
// 2307: Cannot find module — JSDoc-only stubbed deps still occasionally
|
|
65
|
+
// leak through Monaco's module resolution.
|
|
66
|
+
2307,
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
installExtraLibs(monaco);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Editor
|
|
74
|
+
height="100%"
|
|
75
|
+
defaultLanguage="typescript"
|
|
76
|
+
theme="vs-dark"
|
|
77
|
+
value={value}
|
|
78
|
+
onChange={(v) => onChange(v ?? "")}
|
|
79
|
+
onMount={handleMount}
|
|
80
|
+
path={path}
|
|
81
|
+
options={{
|
|
82
|
+
tabSize: 2,
|
|
83
|
+
minimap: { enabled: false },
|
|
84
|
+
padding: { top: 12, bottom: 12 },
|
|
85
|
+
fontSize: 13,
|
|
86
|
+
fontFamily:
|
|
87
|
+
"ui-monospace, SFMono-Regular, 'JetBrains Mono', 'Fira Code', Consolas, monospace",
|
|
88
|
+
smoothScrolling: true,
|
|
89
|
+
cursorBlinking: "smooth",
|
|
90
|
+
scrollBeyondLastLine: false,
|
|
91
|
+
renderLineHighlight: "line",
|
|
92
|
+
wordWrap: "on",
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { WorkerConnector } from "tgrid";
|
|
4
|
+
|
|
5
|
+
import type { ICompilerService } from "../structures/ICompilerService";
|
|
6
|
+
import type { ICreateCompilerClientOptions } from "../structures/ICreateCompilerClientOptions";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* UI-side singleton: connect to the playground worker over tgrid and return the
|
|
10
|
+
* typed `ICompilerService` driver.
|
|
11
|
+
*
|
|
12
|
+
* The promise is cached; the first call boots, every subsequent call shares the
|
|
13
|
+
* same connection. If the boot rejects the cache is cleared so the next call
|
|
14
|
+
* retries — otherwise every retry would resolve to the same rejection.
|
|
15
|
+
*/
|
|
16
|
+
export function createCompilerClient(options: ICreateCompilerClientOptions): {
|
|
17
|
+
connect(): Promise<ICompilerService>;
|
|
18
|
+
reset(): Promise<void>;
|
|
19
|
+
} {
|
|
20
|
+
let connectionPromise: Promise<ICompilerService> | null = null;
|
|
21
|
+
// Track the active connector AND the in-flight connector promise so
|
|
22
|
+
// reset() can dispose either one — disposing only the resolved
|
|
23
|
+
// `activeConnector` leaks the connector when reset() is called during
|
|
24
|
+
// an in-flight `await connector.connect(...)` (the connector reference
|
|
25
|
+
// exists but isn't yet assigned to activeConnector).
|
|
26
|
+
let activeConnector: WorkerConnector<null, null, null> | null = null;
|
|
27
|
+
let pendingConnector: Promise<WorkerConnector<null, null, null>> | null =
|
|
28
|
+
null;
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
connect(): Promise<ICompilerService> {
|
|
32
|
+
if (connectionPromise) return connectionPromise;
|
|
33
|
+
const connector: WorkerConnector<null, null, null> = new WorkerConnector(
|
|
34
|
+
null,
|
|
35
|
+
null,
|
|
36
|
+
);
|
|
37
|
+
const connectPromise = connector
|
|
38
|
+
.connect(options.workerUrl)
|
|
39
|
+
.then(() => connector);
|
|
40
|
+
pendingConnector = connectPromise;
|
|
41
|
+
connectionPromise = (async () => {
|
|
42
|
+
try {
|
|
43
|
+
await connectPromise;
|
|
44
|
+
} catch (err) {
|
|
45
|
+
connectionPromise = null;
|
|
46
|
+
if (pendingConnector === connectPromise) pendingConnector = null;
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
if (pendingConnector === connectPromise) pendingConnector = null;
|
|
50
|
+
activeConnector = connector;
|
|
51
|
+
return connector.getDriver() as unknown as ICompilerService;
|
|
52
|
+
})();
|
|
53
|
+
return connectionPromise;
|
|
54
|
+
},
|
|
55
|
+
async reset(): Promise<void> {
|
|
56
|
+
const inflight = pendingConnector;
|
|
57
|
+
const active = activeConnector;
|
|
58
|
+
connectionPromise = null;
|
|
59
|
+
pendingConnector = null;
|
|
60
|
+
activeConnector = null;
|
|
61
|
+
// Swallow close errors: the worker is already being torn down,
|
|
62
|
+
// and a Retry that fails to close cleanly should not block the
|
|
63
|
+
// next connect attempt. Cover both code paths — the in-flight
|
|
64
|
+
// connector (await it first, then close) and the resolved active
|
|
65
|
+
// connector. Either may be null; both may be the same instance
|
|
66
|
+
// after a successful connect().
|
|
67
|
+
if (inflight) {
|
|
68
|
+
try {
|
|
69
|
+
const c = await inflight;
|
|
70
|
+
if (c !== active) await c.close().catch(() => {});
|
|
71
|
+
} catch {
|
|
72
|
+
// connect() rejected — nothing to close.
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (active) {
|
|
76
|
+
await active.close().catch(() => {});
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
// CJS-flavored sandbox `require` over an in-memory pack of `.js` / `.json`
|
|
2
|
+
// modules. Used by the playground Execute lane to run compiled JS in the
|
|
3
|
+
// browser without round-tripping through a CDN.
|
|
4
|
+
//
|
|
5
|
+
// Resolution algorithm (minimal):
|
|
6
|
+
// - Bare specifier `typia/lib/X`:
|
|
7
|
+
// try `typia/lib/X.js`, then `typia/lib/X/index.js`, then honor the
|
|
8
|
+
// package's `exports` / `main` (read from <pkg>/package.json) before
|
|
9
|
+
// giving up.
|
|
10
|
+
// - Relative `./Y` / `../Y` (encountered when one pack module requires a
|
|
11
|
+
// sibling): resolved against the caller's pack key.
|
|
12
|
+
// - Bare `name` (no subpath): honors the package `main` field, falling back
|
|
13
|
+
// to `name/index.js`.
|
|
14
|
+
//
|
|
15
|
+
// Every successful load is cached so cyclic graphs settle. Module evaluation
|
|
16
|
+
// wraps the source text in the standard CJS wrapper:
|
|
17
|
+
// (function(require, module, exports, __dirname, __filename, console) {...})
|
|
18
|
+
|
|
19
|
+
interface IPackJson {
|
|
20
|
+
name?: string;
|
|
21
|
+
main?: string;
|
|
22
|
+
exports?: unknown;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface ISandboxRequireOptions {
|
|
26
|
+
/** Console replacement injected into every sandbox module. */
|
|
27
|
+
console:
|
|
28
|
+
| Console
|
|
29
|
+
| typeof globalThis.console
|
|
30
|
+
| Record<string, (...args: unknown[]) => void>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Build a sandboxed `require` function over a runtime pack. Resolves typia /
|
|
35
|
+
* `@typia/*` / randexp specifiers from the pack; throws on anything else so the
|
|
36
|
+
* caller sees the unsupported dependency.
|
|
37
|
+
*/
|
|
38
|
+
export function createSandboxRequire(
|
|
39
|
+
pack: Record<string, string>,
|
|
40
|
+
opts: ISandboxRequireOptions,
|
|
41
|
+
): (specifier: string) => unknown {
|
|
42
|
+
type ModuleObj = { exports: unknown };
|
|
43
|
+
const cache = new Map<string, ModuleObj>();
|
|
44
|
+
|
|
45
|
+
const has = (key: string): boolean =>
|
|
46
|
+
Object.prototype.hasOwnProperty.call(pack, key);
|
|
47
|
+
|
|
48
|
+
const tryPaths = (...candidates: string[]): string | null => {
|
|
49
|
+
for (const c of candidates) if (has(c)) return c;
|
|
50
|
+
return null;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Read package.json from pack and resolve via main/exports.
|
|
54
|
+
const resolvePackageEntry = (
|
|
55
|
+
pkg: string,
|
|
56
|
+
subpath: string | null,
|
|
57
|
+
): string | null => {
|
|
58
|
+
const pjKey = `${pkg}/package.json`;
|
|
59
|
+
if (!has(pjKey)) return null;
|
|
60
|
+
let pj: IPackJson;
|
|
61
|
+
try {
|
|
62
|
+
pj = JSON.parse(pack[pjKey]!) as IPackJson;
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
if (subpath === null) {
|
|
67
|
+
// bare "name": honor exports["."] → string, else main, else index.
|
|
68
|
+
const exportsAny = pj.exports;
|
|
69
|
+
if (typeof exportsAny === "object" && exportsAny !== null) {
|
|
70
|
+
const root = (exportsAny as Record<string, unknown>)["."];
|
|
71
|
+
const r = pickConditionalExport(root);
|
|
72
|
+
if (r) {
|
|
73
|
+
const resolved = `${pkg}/${stripDotSlash(r)}`;
|
|
74
|
+
return has(resolved) ? resolved : null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (typeof pj.main === "string") {
|
|
78
|
+
return tryPaths(
|
|
79
|
+
`${pkg}/${stripDotSlash(pj.main)}`,
|
|
80
|
+
`${pkg}/${stripDotSlash(pj.main)}.js`,
|
|
81
|
+
`${pkg}/${stripDotSlash(pj.main)}.cjs`,
|
|
82
|
+
`${pkg}/${stripDotSlash(pj.main)}.mjs`,
|
|
83
|
+
`${pkg}/${stripDotSlash(pj.main)}.json`,
|
|
84
|
+
`${pkg}/${stripDotSlash(pj.main)}/index.js`,
|
|
85
|
+
`${pkg}/${stripDotSlash(pj.main)}/index.cjs`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return tryPaths(`${pkg}/index.js`, `${pkg}/index.cjs`);
|
|
89
|
+
}
|
|
90
|
+
// Subpath: honor exports["./subpath"] or exports["./subpath/*"] patterns.
|
|
91
|
+
const exportsAny = pj.exports;
|
|
92
|
+
if (typeof exportsAny === "object" && exportsAny !== null) {
|
|
93
|
+
const entries = exportsAny as Record<string, unknown>;
|
|
94
|
+
// Exact match first.
|
|
95
|
+
const exact = entries[`./${subpath}`];
|
|
96
|
+
const ex = pickConditionalExport(exact);
|
|
97
|
+
if (ex) {
|
|
98
|
+
const resolved = `${pkg}/${stripDotSlash(ex)}`;
|
|
99
|
+
if (has(resolved)) return resolved;
|
|
100
|
+
}
|
|
101
|
+
// Wildcard match.
|
|
102
|
+
for (const [pattern, target] of Object.entries(entries)) {
|
|
103
|
+
if (!pattern.endsWith("/*")) continue;
|
|
104
|
+
const prefix = pattern.slice(2, -1); // strip "./" and trailing "*"
|
|
105
|
+
if (!subpath.startsWith(prefix)) continue;
|
|
106
|
+
const rest = subpath.slice(prefix.length);
|
|
107
|
+
const targetStr = pickConditionalExport(target);
|
|
108
|
+
if (!targetStr) continue;
|
|
109
|
+
const resolved = `${pkg}/${stripDotSlash(targetStr.replace("*", rest))}`;
|
|
110
|
+
if (has(resolved)) return resolved;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Resolve a specifier (with optional `fromKey` for relative imports) to a
|
|
117
|
+
// pack key, or null if unknown.
|
|
118
|
+
const resolveSpecifier = (
|
|
119
|
+
specifier: string,
|
|
120
|
+
fromKey: string | null,
|
|
121
|
+
): string | null => {
|
|
122
|
+
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
123
|
+
if (!fromKey) return null;
|
|
124
|
+
const baseDir = dirname(fromKey);
|
|
125
|
+
const joined = posixJoin(baseDir, specifier);
|
|
126
|
+
return tryPaths(
|
|
127
|
+
joined,
|
|
128
|
+
`${joined}.js`,
|
|
129
|
+
`${joined}.cjs`,
|
|
130
|
+
`${joined}.mjs`,
|
|
131
|
+
`${joined}.json`,
|
|
132
|
+
`${joined}/index.js`,
|
|
133
|
+
`${joined}/index.cjs`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
// Bare specifier. Split into package name + subpath.
|
|
137
|
+
const { pkg, subpath } = splitBareSpecifier(specifier);
|
|
138
|
+
if (subpath === null) {
|
|
139
|
+
return resolvePackageEntry(pkg, null);
|
|
140
|
+
}
|
|
141
|
+
// First try direct paths (covers the common typia/lib/internal/X case).
|
|
142
|
+
const direct = tryPaths(
|
|
143
|
+
`${pkg}/${subpath}`,
|
|
144
|
+
`${pkg}/${subpath}.js`,
|
|
145
|
+
`${pkg}/${subpath}.cjs`,
|
|
146
|
+
`${pkg}/${subpath}.mjs`,
|
|
147
|
+
`${pkg}/${subpath}.json`,
|
|
148
|
+
`${pkg}/${subpath}/index.js`,
|
|
149
|
+
`${pkg}/${subpath}/index.cjs`,
|
|
150
|
+
);
|
|
151
|
+
if (direct) return direct;
|
|
152
|
+
// Fall back to package.json exports map.
|
|
153
|
+
return resolvePackageEntry(pkg, subpath);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const evaluate = (key: string): ModuleObj => {
|
|
157
|
+
const cached = cache.get(key);
|
|
158
|
+
if (cached) return cached;
|
|
159
|
+
const code = pack[key]!;
|
|
160
|
+
const mod: ModuleObj = { exports: {} };
|
|
161
|
+
// Cache before evaluation so cyclic requires see the partial exports.
|
|
162
|
+
cache.set(key, mod);
|
|
163
|
+
if (key.endsWith(".json")) {
|
|
164
|
+
mod.exports = JSON.parse(code) as unknown;
|
|
165
|
+
return mod;
|
|
166
|
+
}
|
|
167
|
+
const localRequire = (specifier: string): unknown => {
|
|
168
|
+
const resolved = resolveSpecifier(specifier, key);
|
|
169
|
+
if (!resolved) {
|
|
170
|
+
throw new Error(
|
|
171
|
+
`require("${specifier}") is not available in the playground sandbox (from ${key})`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
return evaluate(resolved).exports;
|
|
175
|
+
};
|
|
176
|
+
const filename = "/sandbox/" + key;
|
|
177
|
+
const dir = "/sandbox/" + dirname(key);
|
|
178
|
+
try {
|
|
179
|
+
const factory = new Function(
|
|
180
|
+
"require",
|
|
181
|
+
"module",
|
|
182
|
+
"exports",
|
|
183
|
+
"__dirname",
|
|
184
|
+
"__filename",
|
|
185
|
+
"console",
|
|
186
|
+
code,
|
|
187
|
+
) as (
|
|
188
|
+
req: (s: string) => unknown,
|
|
189
|
+
m: ModuleObj,
|
|
190
|
+
e: Record<string, unknown>,
|
|
191
|
+
d: string,
|
|
192
|
+
f: string,
|
|
193
|
+
c: unknown,
|
|
194
|
+
) => void;
|
|
195
|
+
factory(
|
|
196
|
+
localRequire,
|
|
197
|
+
mod,
|
|
198
|
+
mod.exports as Record<string, unknown>,
|
|
199
|
+
dir,
|
|
200
|
+
filename,
|
|
201
|
+
opts.console,
|
|
202
|
+
);
|
|
203
|
+
} catch (err) {
|
|
204
|
+
// Surface eval-time errors with context so debugging the sandbox is
|
|
205
|
+
// easier when typia ships a module that depends on something missing.
|
|
206
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
207
|
+
throw new Error(`evaluating ${key}: ${message}`);
|
|
208
|
+
}
|
|
209
|
+
return mod;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
return (specifier: string): unknown => {
|
|
213
|
+
const resolved = resolveSpecifier(specifier, null);
|
|
214
|
+
if (!resolved) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
`require("${specifier}") is not available in the playground sandbox`,
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
return evaluate(resolved).exports;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function pickConditionalExport(value: unknown): string | null {
|
|
224
|
+
if (typeof value === "string") return value;
|
|
225
|
+
if (value && typeof value === "object") {
|
|
226
|
+
const obj = value as Record<string, unknown>;
|
|
227
|
+
// Prefer require (CJS) > default > node.
|
|
228
|
+
const pick = obj.require ?? obj.default ?? obj.node;
|
|
229
|
+
if (typeof pick === "string") return pick;
|
|
230
|
+
if (pick && typeof pick === "object") return pickConditionalExport(pick);
|
|
231
|
+
}
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function stripDotSlash(p: string): string {
|
|
236
|
+
return p.startsWith("./") ? p.slice(2) : p;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function dirname(p: string): string {
|
|
240
|
+
const i = p.lastIndexOf("/");
|
|
241
|
+
return i < 0 ? "" : p.slice(0, i);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function posixJoin(base: string, rel: string): string {
|
|
245
|
+
const baseParts = base.split("/").filter(Boolean);
|
|
246
|
+
for (const seg of rel.split("/")) {
|
|
247
|
+
if (seg === "" || seg === ".") continue;
|
|
248
|
+
if (seg === "..") baseParts.pop();
|
|
249
|
+
else baseParts.push(seg);
|
|
250
|
+
}
|
|
251
|
+
return baseParts.join("/");
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function splitBareSpecifier(specifier: string): {
|
|
255
|
+
pkg: string;
|
|
256
|
+
subpath: string | null;
|
|
257
|
+
} {
|
|
258
|
+
// Handle @scope/name[/subpath]
|
|
259
|
+
if (specifier.startsWith("@")) {
|
|
260
|
+
const slash1 = specifier.indexOf("/");
|
|
261
|
+
if (slash1 < 0) return { pkg: specifier, subpath: null };
|
|
262
|
+
const slash2 = specifier.indexOf("/", slash1 + 1);
|
|
263
|
+
if (slash2 < 0) return { pkg: specifier, subpath: null };
|
|
264
|
+
return {
|
|
265
|
+
pkg: specifier.slice(0, slash2),
|
|
266
|
+
subpath: specifier.slice(slash2 + 1),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
const slash = specifier.indexOf("/");
|
|
270
|
+
if (slash < 0) return { pkg: specifier, subpath: null };
|
|
271
|
+
return {
|
|
272
|
+
pkg: specifier.slice(0, slash),
|
|
273
|
+
subpath: specifier.slice(slash + 1),
|
|
274
|
+
};
|
|
275
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Loads a CommonJS-style runtime pack for the playground's Execute sandbox.
|
|
2
|
+
//
|
|
3
|
+
// The pack JSON itself is built by the site (e.g. `pack-typia-runtime.cjs`
|
|
4
|
+
// in the ttsc website) and served at a site-chosen URL. It mirrors the
|
|
5
|
+
// layout the typia transform's emit references — `typia/lib/internal/*`,
|
|
6
|
+
// `@typia/utils/lib/*`, etc. — so a bundle's `require("typia/lib/internal/X")`
|
|
7
|
+
// resolves to the matching pack entry.
|
|
8
|
+
|
|
9
|
+
const packCache = new Map<string, Promise<Record<string, string>>>();
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Fetches the prebuilt runtime pack once per URL. Re-entrant on the same
|
|
13
|
+
* in-flight promise. On rejection the cache entry is cleared so the next call
|
|
14
|
+
* retries — otherwise a transient fetch failure (CDN blip, offline at first
|
|
15
|
+
* Execute) would permanently break every later Execute attempt.
|
|
16
|
+
*/
|
|
17
|
+
export async function loadTypiaRuntimePack(
|
|
18
|
+
url: string,
|
|
19
|
+
): Promise<Record<string, string>> {
|
|
20
|
+
const cached = packCache.get(url);
|
|
21
|
+
if (cached) return cached;
|
|
22
|
+
const promise = (async () => {
|
|
23
|
+
const response = await fetch(url);
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
`loadTypiaRuntimePack: failed to fetch ${url}: ${response.status}`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return (await response.json()) as Record<string, string>;
|
|
30
|
+
})().catch((err) => {
|
|
31
|
+
packCache.delete(url);
|
|
32
|
+
throw err;
|
|
33
|
+
});
|
|
34
|
+
packCache.set(url, promise);
|
|
35
|
+
return promise;
|
|
36
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Options accepted by {@link buildTsconfigJSON}. */
|
|
2
|
+
export interface IBuildTsconfigOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Module emit shape. Sites preview-render ESM, then re-run as CommonJS for
|
|
5
|
+
* the in-page `new Function` sandbox.
|
|
6
|
+
*/
|
|
7
|
+
module: "ESNext" | "CommonJS";
|
|
8
|
+
/** Output directory relative to project root. Defaults to `"dist"`. */
|
|
9
|
+
outDir?: string;
|
|
10
|
+
/** Source root relative to project root. Defaults to `"src"`. */
|
|
11
|
+
rootDir?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Extra entries spliced into `compilerOptions`. Use for plugins, paths, lib
|
|
14
|
+
* overrides, etc.
|
|
15
|
+
*/
|
|
16
|
+
compilerOptions?: Record<string, unknown>;
|
|
17
|
+
/** Project `include` globs. Defaults to `["src"]`. */
|
|
18
|
+
include?: readonly string[];
|
|
19
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { ITransformOptions } from "./ITransformOptions";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Worker ↔ UI RPC contract for the playground compiler service.
|
|
5
|
+
*
|
|
6
|
+
* `createWorkerCompiler` (worker side) implements this. `createCompilerClient`
|
|
7
|
+
* (UI side) returns a tgrid Driver bound to this shape. Sites that need an
|
|
8
|
+
* `extraTabs` lane should layer additional verbs over this base interface in
|
|
9
|
+
* their own ICompilerService subtype.
|
|
10
|
+
*/
|
|
11
|
+
export interface ICompilerService {
|
|
12
|
+
/**
|
|
13
|
+
* Mount external npm package files into the worker's MemFS under
|
|
14
|
+
* `node_modules/`. Driven by the dependency installer in
|
|
15
|
+
* `@ttsc/playground/npm`.
|
|
16
|
+
*/
|
|
17
|
+
installDependencies(
|
|
18
|
+
props: ICompilerService.IInstallDependenciesProps,
|
|
19
|
+
): Promise<ICompilerService.IInstallDependenciesResult>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Compile the user's source into JavaScript with diagnostics. Plugin
|
|
23
|
+
* transforms (typia, when enabled in options) run first; the result is the
|
|
24
|
+
* post-transform emit.
|
|
25
|
+
*/
|
|
26
|
+
compile(props: ICompilerService.IProps): Promise<ICompilerService.IResult>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Same pipeline as `compile`, but using the bundle-flavored tsconfig
|
|
30
|
+
* (typically `module: "CommonJS"` for in-page `new Function` sandboxing).
|
|
31
|
+
* Sites that don't run user code may treat this identically to `compile`.
|
|
32
|
+
*/
|
|
33
|
+
bundle(props: ICompilerService.IProps): Promise<ICompilerService.IResult>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Run the lint plugin and parse its findings into the same diagnostic shape
|
|
37
|
+
* as `compile`. Returns an empty list when no lint plugin is wired into the
|
|
38
|
+
* worker.
|
|
39
|
+
*/
|
|
40
|
+
lint(props: ICompilerService.IProps): Promise<ICompilerService.ILintResult>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export namespace ICompilerService {
|
|
44
|
+
export interface IProps {
|
|
45
|
+
source: string;
|
|
46
|
+
options?: ITransformOptions;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface IInstallDependenciesProps {
|
|
50
|
+
/** Node_modules-relative paths to text content. */
|
|
51
|
+
files: Record<string, string>;
|
|
52
|
+
/** Metadata for the packages whose files are in `files`. */
|
|
53
|
+
packages: IInstalledPackage[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface IInstalledPackage {
|
|
57
|
+
name: string;
|
|
58
|
+
version: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface IInstallDependenciesResult {
|
|
62
|
+
installed: IInstalledPackage[];
|
|
63
|
+
fileCount: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type IResult = ISuccess | IFailure | IError;
|
|
67
|
+
|
|
68
|
+
export interface ISuccess extends IBase<"success", string> {}
|
|
69
|
+
export interface IFailure extends IBase<"failure", string> {
|
|
70
|
+
diagnostics: IDiagnostic[];
|
|
71
|
+
}
|
|
72
|
+
export interface IError extends IBase<"error", unknown> {}
|
|
73
|
+
|
|
74
|
+
interface IBase<Type extends string, Value> {
|
|
75
|
+
type: Type;
|
|
76
|
+
target: "javascript";
|
|
77
|
+
value: Value;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface IDiagnostic {
|
|
81
|
+
/** 1-based line number. */
|
|
82
|
+
line: number;
|
|
83
|
+
/** 1-based column number. */
|
|
84
|
+
column: number;
|
|
85
|
+
/** Length of the span in source characters; at least 1. */
|
|
86
|
+
length: number;
|
|
87
|
+
severity: "error" | "warning";
|
|
88
|
+
message: string;
|
|
89
|
+
/** Diagnostic code, e.g. `"TS2322"` or a lint rule id. */
|
|
90
|
+
code?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface ILintResult {
|
|
94
|
+
diagnostics: IDiagnostic[];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One captured `console.*` invocation. `value` is the argv (the spread of
|
|
3
|
+
* `console.log(...args)`), so `console.log("user:", user)` shows up as a single
|
|
4
|
+
* row with both pieces rendered inline, separated by a space — same as a real
|
|
5
|
+
* DevTools console.
|
|
6
|
+
*/
|
|
7
|
+
export interface IConsoleMessage {
|
|
8
|
+
type: "debug" | "dir" | "error" | "info" | "log" | "table" | "warn";
|
|
9
|
+
value: unknown[];
|
|
10
|
+
}
|