@tscircuit/cli 0.0.394 → 0.1.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/.github/workflows/bun-formatcheck.yml +26 -0
- package/.github/workflows/bun-pver-release.yml +25 -0
- package/.github/workflows/{typecheck.yml → bun-typecheck.yml} +0 -3
- package/LICENSE +21 -0
- package/README.md +30 -36
- package/biome.json +9 -9
- package/bun.lockb +0 -0
- package/cli/CliContext.ts +8 -0
- package/cli/auth/login/register.ts +73 -0
- package/cli/auth/logout/register.ts +11 -0
- package/cli/auth/register.ts +5 -0
- package/cli/config/print/register.ts +12 -0
- package/cli/config/register.ts +5 -0
- package/cli/dev/register.ts +111 -0
- package/cli/main.ts +31 -0
- package/dist/main.js +473 -0
- package/docs/file-server-api-usage.md +57 -0
- package/docs/run-frame-usage.md +14 -0
- package/example-dir/manual-edits.json +1 -0
- package/example-dir/snippet.d.ts +13 -0
- package/example-dir/snippet.tsx +20 -0
- package/example-dir/types.d.ts +11 -0
- package/lib/cli-config/TypedConfigStore.ts +50 -0
- package/lib/cli-config/index.ts +16 -0
- package/lib/dependency-analysis/DependencyAnalyzer.ts +129 -0
- package/lib/dependency-analysis/getLocalFileDependencies.ts +101 -0
- package/lib/dependency-analysis/installNodeModuleTypes.ts +74 -0
- package/lib/index.ts +2 -0
- package/lib/project-config/index.ts +5 -0
- package/lib/registry-api/endpoint-types.ts +20 -0
- package/lib/registry-api/get-ky.ts +30 -0
- package/lib/server/EventsWatcher.ts +75 -0
- package/lib/server/createServer.ts +62 -0
- package/lib/site/getIndex.ts +18 -0
- package/package.json +27 -144
- package/tsconfig.json +25 -22
- package/.github/workflows/formatbot.yml +0 -63
- package/.github/workflows/release.yml +0 -40
- package/.github/workflows/test.yml +0 -32
- package/.github/workflows/windows-tests.yml +0 -32
- package/.prettierrc +0 -1
- package/DEVELOPMENT.md +0 -7
- package/api/README.md +0 -3
- package/api/db/generic-json-level.ts +0 -123
- package/api/db/get-db.ts +0 -26
- package/api/db/schema.ts +0 -65
- package/api/db/zod-level-db.ts +0 -148
- package/api/index.ts +0 -4
- package/api/lib/middlewares/with-db.ts +0 -18
- package/api/lib/middlewares/with-debug-request-logging.ts +0 -13
- package/api/lib/middlewares/with-error-response.ts +0 -37
- package/api/lib/with-winter-spec.ts +0 -9
- package/api/lib/zod/export_parameters.ts +0 -25
- package/api/routes/api/db/download.ts +0 -25
- package/api/routes/api/dev_package_examples/create.ts +0 -43
- package/api/routes/api/dev_package_examples/get.ts +0 -46
- package/api/routes/api/dev_package_examples/list.ts +0 -36
- package/api/routes/api/dev_package_examples/update.ts +0 -59
- package/api/routes/api/dev_server/reset.ts +0 -13
- package/api/routes/api/export_files/create.ts +0 -27
- package/api/routes/api/export_files/download.ts +0 -25
- package/api/routes/api/export_requests/create.ts +0 -30
- package/api/routes/api/export_requests/get.ts +0 -43
- package/api/routes/api/export_requests/list.ts +0 -26
- package/api/routes/api/export_requests/update.ts +0 -34
- package/api/routes/api/health.ts +0 -11
- package/api/routes/api/package_info/create.ts +0 -26
- package/api/routes/api/package_info/get.ts +0 -16
- package/api/routes/health.ts +0 -11
- package/api/routes/index.ts +0 -16
- package/api/server.ts +0 -20
- package/api/static-routes.ts +0 -24
- package/api/tests/fixtures/get-test-server.ts +0 -31
- package/api/tests/fixtures/start-server.ts +0 -41
- package/api/tests/routes/dev_package_examples/create.test.ts +0 -19
- package/api/tests/routes/dev_package_examples/get.test.ts +0 -25
- package/api/tests/routes/dev_package_examples/list.test.ts +0 -32
- package/api/tests/routes/dev_package_examples/update.test.ts +0 -38
- package/api/tests/routes/export_files/create.test.ts +0 -18
- package/api/tests/routes/export_files/download.test.ts +0 -29
- package/api/tests/routes/export_requests/create.test.ts +0 -24
- package/api/tests/routes/export_requests/get.test.ts +0 -41
- package/api/tests/routes/export_requests/list.test.ts +0 -35
- package/api/tests/routes/export_requests/update.test.ts +0 -50
- package/api/tests/routes/health.test.ts +0 -10
- package/bunfig.toml +0 -2
- package/cli/cli.ts +0 -13
- package/cli/lib/cmd-fns/add.ts +0 -34
- package/cli/lib/cmd-fns/auth-login.ts +0 -59
- package/cli/lib/cmd-fns/auth-logout.ts +0 -7
- package/cli/lib/cmd-fns/auth-sessions-create.ts +0 -3
- package/cli/lib/cmd-fns/auth-sessions-get.ts +0 -3
- package/cli/lib/cmd-fns/auth-sessions-list.ts +0 -5
- package/cli/lib/cmd-fns/config-clear.ts +0 -5
- package/cli/lib/cmd-fns/config-print-config.ts +0 -6
- package/cli/lib/cmd-fns/config-reveal-location.ts +0 -5
- package/cli/lib/cmd-fns/config-set-log-requests.ts +0 -7
- package/cli/lib/cmd-fns/config-set-registry.ts +0 -9
- package/cli/lib/cmd-fns/config-set-runtime.ts +0 -7
- package/cli/lib/cmd-fns/config-set-session.ts +0 -7
- package/cli/lib/cmd-fns/dev/check-if-initialized.ts +0 -22
- package/cli/lib/cmd-fns/dev/derive-selector-from-pcb-component-id.ts +0 -23
- package/cli/lib/cmd-fns/dev/dev-server-request-handler.ts +0 -61
- package/cli/lib/cmd-fns/dev/find-available-port.ts +0 -32
- package/cli/lib/cmd-fns/dev/fulfill-export-requests.ts +0 -162
- package/cli/lib/cmd-fns/dev/get-dev-server-axios.ts +0 -29
- package/cli/lib/cmd-fns/dev/index.ts +0 -168
- package/cli/lib/cmd-fns/dev/infer-export-name-from-source.ts +0 -17
- package/cli/lib/cmd-fns/dev/mark-all-examples-loading.ts +0 -18
- package/cli/lib/cmd-fns/dev/soupify-and-upload-example-file.ts +0 -62
- package/cli/lib/cmd-fns/dev/start-dev-server.ts +0 -34
- package/cli/lib/cmd-fns/dev/start-edit-event-watcher.ts +0 -347
- package/cli/lib/cmd-fns/dev/start-export-request-watcher.ts +0 -33
- package/cli/lib/cmd-fns/dev/start-fs-watcher.ts +0 -54
- package/cli/lib/cmd-fns/dev/upload-examples-from-directory.ts +0 -42
- package/cli/lib/cmd-fns/dev-server-fulfill-export-requests.ts +0 -43
- package/cli/lib/cmd-fns/dev-server-upload.ts +0 -56
- package/cli/lib/cmd-fns/export-gerbers.ts +0 -28
- package/cli/lib/cmd-fns/export-kicad-pcb.ts +0 -36
- package/cli/lib/cmd-fns/export-pnp-csv.ts +0 -32
- package/cli/lib/cmd-fns/gen-jlcpcb-component.ts +0 -64
- package/cli/lib/cmd-fns/go.ts +0 -14
- package/cli/lib/cmd-fns/index.ts +0 -46
- package/cli/lib/cmd-fns/init/create-or-modify-npmrc.ts +0 -21
- package/cli/lib/cmd-fns/init/get-generated-npmrc.ts +0 -8
- package/cli/lib/cmd-fns/init/get-generated-readme.ts +0 -41
- package/cli/lib/cmd-fns/init/get-generated-tsconfig.ts +0 -34
- package/cli/lib/cmd-fns/init/index.ts +0 -193
- package/cli/lib/cmd-fns/install.ts +0 -34
- package/cli/lib/cmd-fns/lint.ts +0 -43
- package/cli/lib/cmd-fns/open.ts +0 -19
- package/cli/lib/cmd-fns/package-examples-create.ts +0 -36
- package/cli/lib/cmd-fns/package-examples-get.ts +0 -20
- package/cli/lib/cmd-fns/package-examples-list.ts +0 -18
- package/cli/lib/cmd-fns/package-files-create.ts +0 -31
- package/cli/lib/cmd-fns/package-files-download.ts +0 -29
- package/cli/lib/cmd-fns/package-files-get.ts +0 -3
- package/cli/lib/cmd-fns/package-files-list.ts +0 -28
- package/cli/lib/cmd-fns/package-files-upload-directory.ts +0 -6
- package/cli/lib/cmd-fns/package-releases-create.ts +0 -35
- package/cli/lib/cmd-fns/package-releases-get.ts +0 -3
- package/cli/lib/cmd-fns/package-releases-list.ts +0 -32
- package/cli/lib/cmd-fns/package-releases-update.ts +0 -45
- package/cli/lib/cmd-fns/packages-create.ts +0 -16
- package/cli/lib/cmd-fns/packages-get.ts +0 -16
- package/cli/lib/cmd-fns/packages-list.ts +0 -16
- package/cli/lib/cmd-fns/publish/index.ts +0 -336
- package/cli/lib/cmd-fns/remove.ts +0 -31
- package/cli/lib/cmd-fns/render.ts +0 -45
- package/cli/lib/cmd-fns/soupify.ts +0 -31
- package/cli/lib/cmd-fns/uninstall.ts +0 -31
- package/cli/lib/cmd-fns/version.ts +0 -38
- package/cli/lib/create-config-manager.ts +0 -97
- package/cli/lib/export-fns/export-bom-csv.ts +0 -32
- package/cli/lib/export-fns/export-gerbers.ts +0 -108
- package/cli/lib/export-fns/export-kicad-pcb.ts +0 -32
- package/cli/lib/export-fns/export-pnp-csv.ts +0 -31
- package/cli/lib/get-program.ts +0 -387
- package/cli/lib/param-handlers/index.ts +0 -21
- package/cli/lib/param-handlers/interact-for-local-directory.ts +0 -58
- package/cli/lib/param-handlers/interact-for-local-file.ts +0 -59
- package/cli/lib/param-handlers/interact-for-package-example-id.ts +0 -25
- package/cli/lib/param-handlers/interact-for-package-name-with-version.ts +0 -63
- package/cli/lib/param-handlers/interact-for-package-name.ts +0 -45
- package/cli/lib/param-handlers/interact-for-package-release-id.ts +0 -15
- package/cli/lib/param-handlers/interact-for-registry-url.ts +0 -27
- package/cli/lib/param-handlers/interact-for-runtime.ts +0 -33
- package/cli/lib/param-handlers/param-handler-type.ts +0 -7
- package/cli/lib/posthog.ts +0 -23
- package/cli/lib/soupify/get-export-name-from-file.ts +0 -29
- package/cli/lib/soupify/get-tmp-entrpoint-filepath.ts +0 -15
- package/cli/lib/soupify/index.ts +0 -1
- package/cli/lib/soupify/run-entrypoint-file.ts +0 -59
- package/cli/lib/soupify/soupify-with-core.ts +0 -74
- package/cli/lib/soupify/soupify.ts +0 -6
- package/cli/lib/util/app-context.ts +0 -17
- package/cli/lib/util/create-context-and-run-program.ts +0 -168
- package/cli/lib/util/get-all-package-files.ts +0 -66
- package/cli/lib/util/lint-project.ts +0 -137
- package/cli/tests/export-gerber-keyboard.test.ts +0 -16
- package/cli/tests/export-gerber.test.ts +0 -49
- package/cli/tests/export-kicad-pcb.test.ts +0 -23
- package/cli/tests/export-pnp-csv.test.ts +0 -24
- package/cli/tests/fixtures/preload.ts +0 -54
- package/cli/tests/init.test.ts +0 -9
- package/cli/tests/open.test.ts +0 -9
- package/cli/tests/soupify-builder.test.ts +0 -9
- package/cli/tests/soupify-core.test.ts +0 -9
- package/dist/cli.js +0 -3676
- package/docs/EDIT_EVENT_PIPELINE.md +0 -34
- package/example-project/README.md +0 -18
- package/example-project/examples/basic-capacitor.tsx +0 -5
- package/example-project/examples/basic-chip.tsx +0 -26
- package/example-project/examples/basic-resistor.tsx +0 -3
- package/example-project/examples/macrokeypad.tsx +0 -59
- package/example-project/index.ts +0 -1
- package/example-project/package.json +0 -5
- package/example-project/src/ArduinoProMicroBreakout.tsx +0 -37
- package/example-project/src/Key.tsx +0 -46
- package/example-project/src/Keyswitch.tsx +0 -26
- package/example-project/src/KeyswitchSocket.tsx +0 -56
- package/example-project/src/MyCircuit.tsx +0 -38
- package/example-project/src/manual-edits.ts +0 -93
- package/frontend/README.md +0 -3
- package/frontend/bun.lockb +0 -0
- package/frontend/components/command-k.tsx +0 -86
- package/frontend/components/dialogs/generic-export-dialog.tsx +0 -189
- package/frontend/components/dialogs/gerber-export-dialog.tsx +0 -168
- package/frontend/components/global-context-providers.tsx +0 -11
- package/frontend/components/select-example-search.tsx +0 -118
- package/frontend/components/ui/alert-dialog.tsx +0 -139
- package/frontend/components/ui/alert.tsx +0 -59
- package/frontend/components/ui/breadcrumb.tsx +0 -115
- package/frontend/components/ui/button.tsx +0 -57
- package/frontend/components/ui/card.tsx +0 -76
- package/frontend/components/ui/command.tsx +0 -153
- package/frontend/components/ui/context-menu.tsx +0 -202
- package/frontend/components/ui/dialog.tsx +0 -120
- package/frontend/components/ui/menubar.tsx +0 -238
- package/frontend/components/ui/navigation-menu.tsx +0 -128
- package/frontend/components/ui/popover.tsx +0 -31
- package/frontend/components/ui/select.tsx +0 -162
- package/frontend/components/ui/tabs.tsx +0 -53
- package/frontend/components/ui/toggle-group.tsx +0 -59
- package/frontend/components/ui/toggle.tsx +0 -43
- package/frontend/components/ui/tooltip.tsx +0 -28
- package/frontend/components.json +0 -17
- package/frontend/hooks/toast-if-api-not-connected.ts +0 -23
- package/frontend/hooks/use-active-dev-package-example-lite.ts +0 -39
- package/frontend/hooks/use-dev-package-examples.tsx +0 -18
- package/frontend/hooks/use-global-store.ts +0 -42
- package/frontend/index.css +0 -76
- package/frontend/index.html +0 -13
- package/frontend/lib/utils.ts +0 -6
- package/frontend/main.tsx +0 -13
- package/frontend/tailwind.config.js +0 -74
- package/frontend/views/App.tsx +0 -22
- package/frontend/views/Header.tsx +0 -55
- package/frontend/views/HeaderMenu.tsx +0 -326
- package/frontend/views/MainContentView.tsx +0 -172
- package/frontend/vite-env.d.ts +0 -1
- package/frontend/vite.config.ts +0 -50
- package/renovate.json +0 -16
- package/scripts/build-cli.ts +0 -12
- package/tsup.config.ts +0 -7
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface TypedConfigstore<T extends Record<string, any>> {
|
|
2
|
+
/**
|
|
3
|
+
* Get the path to the config file. Can be used to show the user
|
|
4
|
+
* where it is, or better, open it for them.
|
|
5
|
+
*/
|
|
6
|
+
path: string
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get all items as an object or replace the current config with an object.
|
|
10
|
+
*/
|
|
11
|
+
all: any
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get the item count
|
|
15
|
+
*/
|
|
16
|
+
size: number
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get an item
|
|
20
|
+
* @param key The string key to get
|
|
21
|
+
* @return The contents of the config from key $key
|
|
22
|
+
*/
|
|
23
|
+
get(key: keyof T): any
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Set an item
|
|
27
|
+
* @param key The string key
|
|
28
|
+
* @param val The value to set
|
|
29
|
+
*/
|
|
30
|
+
set<K extends keyof T>(key: K, val: T[K]): void
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Determines if a key is present in the config
|
|
34
|
+
* @param key The string key to test for
|
|
35
|
+
* @return True if the key is present
|
|
36
|
+
*/
|
|
37
|
+
has(key: keyof T): boolean
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Delete an item.
|
|
41
|
+
* @param key The key to delete
|
|
42
|
+
*/
|
|
43
|
+
delete(key: keyof T): void
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Clear the config.
|
|
47
|
+
* Equivalent to <code>Configstore.all = {};</code>
|
|
48
|
+
*/
|
|
49
|
+
clear(): void
|
|
50
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Configstore from "configstore"
|
|
2
|
+
import type { TypedConfigstore } from "./TypedConfigStore"
|
|
3
|
+
|
|
4
|
+
export interface CliConfig {
|
|
5
|
+
sessionToken?: string
|
|
6
|
+
githubUsername?: string
|
|
7
|
+
registryApiUrl?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const cliConfig: TypedConfigstore<CliConfig> = new Configstore(
|
|
11
|
+
"tscircuit",
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
export const getRegistryApiUrl = (): string => {
|
|
15
|
+
return cliConfig.get("registryApiUrl") ?? "https://registry-api.tscircuit.com"
|
|
16
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import * as ts from "typescript"
|
|
2
|
+
import * as path from "path"
|
|
3
|
+
import * as fs from "fs"
|
|
4
|
+
|
|
5
|
+
interface DependencyAnalyzerOptions {
|
|
6
|
+
baseDir: string
|
|
7
|
+
includeNodeModules?: boolean
|
|
8
|
+
includeCssModules?: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class DependencyAnalyzer {
|
|
12
|
+
private readonly baseDir: string
|
|
13
|
+
private readonly includeNodeModules: boolean
|
|
14
|
+
private readonly includeCssModules: boolean
|
|
15
|
+
private readonly cache: Map<string, Set<string>> = new Map()
|
|
16
|
+
|
|
17
|
+
constructor(options: DependencyAnalyzerOptions) {
|
|
18
|
+
this.baseDir = options.baseDir
|
|
19
|
+
this.includeNodeModules = options.includeNodeModules ?? false
|
|
20
|
+
this.includeCssModules = options.includeCssModules ?? true
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public analyze(filePath: string): Set<string> {
|
|
24
|
+
if (this.cache.has(filePath)) {
|
|
25
|
+
return this.cache.get(filePath)!
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const dependencies = new Set<string>()
|
|
29
|
+
const sourceFile = this.createSourceFile(filePath)
|
|
30
|
+
|
|
31
|
+
if (!sourceFile) {
|
|
32
|
+
return dependencies
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.visitNode(sourceFile, dependencies)
|
|
36
|
+
this.cache.set(filePath, dependencies)
|
|
37
|
+
|
|
38
|
+
return dependencies
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private createSourceFile(filePath: string): ts.SourceFile | null {
|
|
42
|
+
try {
|
|
43
|
+
const content = fs.readFileSync(filePath, "utf-8")
|
|
44
|
+
return ts.createSourceFile(
|
|
45
|
+
filePath,
|
|
46
|
+
content,
|
|
47
|
+
ts.ScriptTarget.Latest,
|
|
48
|
+
true,
|
|
49
|
+
)
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error(`Error reading file ${filePath}:`, error)
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private visitNode(node: ts.Node, dependencies: Set<string>): void {
|
|
57
|
+
if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
|
|
58
|
+
const moduleSpecifier = node.moduleSpecifier
|
|
59
|
+
if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
|
|
60
|
+
const importPath = moduleSpecifier.text
|
|
61
|
+
this.addDependency(importPath, dependencies)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check for dynamic imports
|
|
66
|
+
if (
|
|
67
|
+
ts.isCallExpression(node) &&
|
|
68
|
+
node.expression.kind === ts.SyntaxKind.ImportKeyword
|
|
69
|
+
) {
|
|
70
|
+
const argument = node.arguments[0]
|
|
71
|
+
if (argument && ts.isStringLiteral(argument)) {
|
|
72
|
+
this.addDependency(argument.text, dependencies)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ts.forEachChild(node, (child) => this.visitNode(child, dependencies))
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private addDependency(importPath: string, dependencies: Set<string>): void {
|
|
80
|
+
// Skip node_modules unless explicitly included
|
|
81
|
+
if (!this.includeNodeModules && importPath.startsWith("node_modules")) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Handle CSS modules if enabled
|
|
86
|
+
if (this.includeCssModules && importPath.endsWith(".css")) {
|
|
87
|
+
const resolvedPath = this.resolvePath(importPath)
|
|
88
|
+
if (resolvedPath) {
|
|
89
|
+
dependencies.add(resolvedPath)
|
|
90
|
+
}
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Resolve relative imports
|
|
95
|
+
if (importPath.startsWith(".")) {
|
|
96
|
+
const resolvedPath = this.resolvePath(importPath)
|
|
97
|
+
if (resolvedPath) {
|
|
98
|
+
dependencies.add(resolvedPath)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private resolvePath(importPath: string): string | null {
|
|
104
|
+
try {
|
|
105
|
+
const extensions = [".tsx", ".ts", ".jsx", ".js", ".css"]
|
|
106
|
+
const resolvedPath = path.resolve(this.baseDir, importPath)
|
|
107
|
+
|
|
108
|
+
// Try exact path first
|
|
109
|
+
if (fs.existsSync(resolvedPath)) {
|
|
110
|
+
return resolvedPath
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Try with extensions
|
|
114
|
+
for (const ext of extensions) {
|
|
115
|
+
const pathWithExt = resolvedPath + ext
|
|
116
|
+
if (fs.existsSync(pathWithExt)) {
|
|
117
|
+
return pathWithExt
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return null
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error(`Error resolving path ${importPath}:`, error)
|
|
124
|
+
return null
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { DependencyAnalyzer, type DependencyAnalyzerOptions }
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as ts from "typescript"
|
|
2
|
+
import * as path from "path"
|
|
3
|
+
import * as fs from "fs"
|
|
4
|
+
|
|
5
|
+
function getLocalFileDependencies(pathToTsxFile: string): string[] {
|
|
6
|
+
// Ensure absolute path
|
|
7
|
+
const absolutePath = path.resolve(pathToTsxFile)
|
|
8
|
+
const baseDir = path.dirname(absolutePath)
|
|
9
|
+
|
|
10
|
+
// Read and parse the file
|
|
11
|
+
const content = fs.readFileSync(absolutePath, "utf-8")
|
|
12
|
+
const sourceFile = ts.createSourceFile(
|
|
13
|
+
absolutePath,
|
|
14
|
+
content,
|
|
15
|
+
ts.ScriptTarget.Latest,
|
|
16
|
+
true,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
const dependencies = new Set<string>()
|
|
20
|
+
|
|
21
|
+
// Recursively visit nodes to find imports
|
|
22
|
+
function visit(node: ts.Node) {
|
|
23
|
+
if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
|
|
24
|
+
const moduleSpecifier = node.moduleSpecifier
|
|
25
|
+
if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
|
|
26
|
+
const importPath = moduleSpecifier.text
|
|
27
|
+
// Only process local imports (starting with . or ..)
|
|
28
|
+
if (importPath.startsWith(".")) {
|
|
29
|
+
resolveAndAddDependency(importPath)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Handle dynamic imports
|
|
35
|
+
if (
|
|
36
|
+
ts.isCallExpression(node) &&
|
|
37
|
+
node.expression.kind === ts.SyntaxKind.ImportKeyword
|
|
38
|
+
) {
|
|
39
|
+
const argument = node.arguments[0]
|
|
40
|
+
if (argument && ts.isStringLiteral(argument)) {
|
|
41
|
+
const importPath = argument.text
|
|
42
|
+
if (importPath.startsWith(".")) {
|
|
43
|
+
resolveAndAddDependency(importPath)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
ts.forEachChild(node, visit)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Helper to resolve and add dependency paths
|
|
52
|
+
function resolveAndAddDependency(importPath: string) {
|
|
53
|
+
const extensions = [
|
|
54
|
+
".tsx",
|
|
55
|
+
".ts",
|
|
56
|
+
".jsx",
|
|
57
|
+
".js",
|
|
58
|
+
".css",
|
|
59
|
+
".scss",
|
|
60
|
+
".sass",
|
|
61
|
+
".less",
|
|
62
|
+
]
|
|
63
|
+
let resolvedPath = path.resolve(baseDir, importPath)
|
|
64
|
+
|
|
65
|
+
// Check if path exists as-is
|
|
66
|
+
if (fs.existsSync(resolvedPath)) {
|
|
67
|
+
dependencies.add(resolvedPath)
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Try with extensions
|
|
72
|
+
for (const ext of extensions) {
|
|
73
|
+
const pathWithExt = resolvedPath + ext
|
|
74
|
+
if (fs.existsSync(pathWithExt)) {
|
|
75
|
+
dependencies.add(pathWithExt)
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check for index files in directories
|
|
81
|
+
if (
|
|
82
|
+
fs.existsSync(resolvedPath) &&
|
|
83
|
+
fs.statSync(resolvedPath).isDirectory()
|
|
84
|
+
) {
|
|
85
|
+
for (const ext of extensions) {
|
|
86
|
+
const indexPath = path.join(resolvedPath, `index${ext}`)
|
|
87
|
+
if (fs.existsSync(indexPath)) {
|
|
88
|
+
dependencies.add(indexPath)
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Start the traversal
|
|
96
|
+
visit(sourceFile)
|
|
97
|
+
|
|
98
|
+
return Array.from(dependencies)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { getLocalFileDependencies }
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as fs from "node:fs"
|
|
2
|
+
import * as path from "node:path"
|
|
3
|
+
import * as ts from "typescript"
|
|
4
|
+
|
|
5
|
+
interface SnippetApiResponse {
|
|
6
|
+
snippet: {
|
|
7
|
+
dts: string
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function installTypes(snippetPath: string) {
|
|
12
|
+
const content = fs.readFileSync(snippetPath, "utf-8")
|
|
13
|
+
const sourceFile = ts.createSourceFile(
|
|
14
|
+
snippetPath,
|
|
15
|
+
content,
|
|
16
|
+
ts.ScriptTarget.Latest,
|
|
17
|
+
true,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
const imports: string[] = []
|
|
21
|
+
|
|
22
|
+
function visit(node: ts.Node) {
|
|
23
|
+
if (ts.isImportDeclaration(node)) {
|
|
24
|
+
const moduleSpecifier = node.moduleSpecifier
|
|
25
|
+
if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
|
|
26
|
+
const importPath = moduleSpecifier.text
|
|
27
|
+
if (importPath.startsWith("@tsci/")) {
|
|
28
|
+
imports.push(importPath)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
ts.forEachChild(node, visit)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
visit(sourceFile)
|
|
36
|
+
|
|
37
|
+
let projectRoot = path.dirname(snippetPath)
|
|
38
|
+
while (projectRoot !== path.parse(projectRoot).root) {
|
|
39
|
+
if (fs.existsSync(path.join(projectRoot, "package.json"))) {
|
|
40
|
+
break
|
|
41
|
+
}
|
|
42
|
+
projectRoot = path.dirname(projectRoot)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (const importPath of imports) {
|
|
46
|
+
const [owner, name] = importPath.replace("@tsci/", "").split(".")
|
|
47
|
+
try {
|
|
48
|
+
const response = await fetch(
|
|
49
|
+
`https://registry-api.tscircuit.com/snippets/get?owner_name=${owner}&unscoped_name=${name}`,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
console.warn(`Failed to fetch types for ${importPath}`)
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const data: SnippetApiResponse = await response.json()
|
|
58
|
+
|
|
59
|
+
if (data.snippet.dts) {
|
|
60
|
+
const packageDir = path.join(
|
|
61
|
+
projectRoot,
|
|
62
|
+
"node_modules",
|
|
63
|
+
"@tsci",
|
|
64
|
+
`${owner}.${name}`,
|
|
65
|
+
)
|
|
66
|
+
fs.mkdirSync(packageDir, { recursive: true })
|
|
67
|
+
|
|
68
|
+
fs.writeFileSync(path.join(packageDir, "index.d.ts"), data.snippet.dts)
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.warn(`Error fetching types for ${importPath}:`, error)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
package/lib/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface EndpointResponse {
|
|
2
|
+
"sessions/login_page/create": {
|
|
3
|
+
login_page: {
|
|
4
|
+
login_page_id: string
|
|
5
|
+
login_page_auth_token: string
|
|
6
|
+
url: string
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
"sessions/login_page/get": {
|
|
10
|
+
login_page: {
|
|
11
|
+
was_login_successful: boolean
|
|
12
|
+
is_expired: boolean
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
"sessions/login_page/exchange_for_cli_session": {
|
|
16
|
+
session: {
|
|
17
|
+
token: string
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getRegistryApiUrl } from "lib/cli-config"
|
|
2
|
+
import ky, { type AfterResponseHook } from "ky"
|
|
3
|
+
|
|
4
|
+
const prettyResponseErrorHook: AfterResponseHook = async (
|
|
5
|
+
_request,
|
|
6
|
+
_options,
|
|
7
|
+
response,
|
|
8
|
+
) => {
|
|
9
|
+
if (!response.ok) {
|
|
10
|
+
try {
|
|
11
|
+
const errorData = await response.json()
|
|
12
|
+
throw new Error(
|
|
13
|
+
`FAIL [${response.status}]: ${_request.method} ${
|
|
14
|
+
new URL(_request.url).pathname
|
|
15
|
+
} \n\n ${JSON.stringify(errorData, null, 2)}`,
|
|
16
|
+
)
|
|
17
|
+
} catch (e) {
|
|
18
|
+
//ignore, allow the error to be thrown
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const getKy = () => {
|
|
24
|
+
return ky.create({
|
|
25
|
+
prefixUrl: getRegistryApiUrl(),
|
|
26
|
+
hooks: {
|
|
27
|
+
afterResponse: [prettyResponseErrorHook],
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { EventEmitter } from "events"
|
|
2
|
+
|
|
3
|
+
interface Event {
|
|
4
|
+
event_id: string
|
|
5
|
+
created_at: string
|
|
6
|
+
event_type: string
|
|
7
|
+
[key: string]: any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface EventsResponse {
|
|
11
|
+
event_list: Event[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class EventsWatcher extends EventEmitter {
|
|
15
|
+
private lastPollTime: string
|
|
16
|
+
private pollInterval: number
|
|
17
|
+
private baseUrl: string
|
|
18
|
+
private polling = false
|
|
19
|
+
private timeoutId?: NodeJS.Timeout
|
|
20
|
+
|
|
21
|
+
constructor(baseUrl = "http://localhost:3000", pollInterval = 1000) {
|
|
22
|
+
super()
|
|
23
|
+
this.baseUrl = baseUrl
|
|
24
|
+
this.pollInterval = pollInterval
|
|
25
|
+
this.lastPollTime = new Date().toISOString()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async start() {
|
|
29
|
+
if (this.polling) return
|
|
30
|
+
this.polling = true
|
|
31
|
+
await this.poll()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
stop() {
|
|
35
|
+
this.polling = false
|
|
36
|
+
if (this.timeoutId) {
|
|
37
|
+
clearTimeout(this.timeoutId)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private async poll() {
|
|
42
|
+
if (!this.polling) return
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const response = await fetch(
|
|
46
|
+
`${this.baseUrl}/api/events/list?since=${encodeURIComponent(this.lastPollTime)}`,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const data: EventsResponse = await response.json()
|
|
54
|
+
|
|
55
|
+
// Update last poll time to latest event or current time
|
|
56
|
+
const latestEvent = data.event_list[data.event_list.length - 1]
|
|
57
|
+
this.lastPollTime = latestEvent
|
|
58
|
+
? latestEvent.created_at
|
|
59
|
+
: new Date().toISOString()
|
|
60
|
+
|
|
61
|
+
// Emit events in chronological order
|
|
62
|
+
data.event_list.forEach((event) => {
|
|
63
|
+
this.emit(event.event_type, event)
|
|
64
|
+
this.emit("*", event)
|
|
65
|
+
})
|
|
66
|
+
} catch (error) {
|
|
67
|
+
this.emit("error", error)
|
|
68
|
+
}
|
|
69
|
+
// Schedule next poll
|
|
70
|
+
this.timeoutId = globalThis.setTimeout(
|
|
71
|
+
() => this.poll(),
|
|
72
|
+
this.pollInterval,
|
|
73
|
+
) as unknown as NodeJS.Timeout
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as http from "node:http"
|
|
2
|
+
import * as fs from "node:fs"
|
|
3
|
+
import * as path from "node:path"
|
|
4
|
+
import { getNodeHandler } from "winterspec/adapters/node"
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
import winterspecBundle from "@tscircuit/file-server/dist/bundle.js"
|
|
7
|
+
import { getIndex } from "../site/getIndex"
|
|
8
|
+
|
|
9
|
+
export const createServer = async (port: number = 3000) => {
|
|
10
|
+
const fileServerHandler = getNodeHandler(winterspecBundle as any, {})
|
|
11
|
+
|
|
12
|
+
const server = http.createServer(async (req, res) => {
|
|
13
|
+
const url = new URL(req.url!, `http://${req.headers.host}`)
|
|
14
|
+
|
|
15
|
+
if (url.pathname === "/standalone.min.js") {
|
|
16
|
+
const standaloneFilePath =
|
|
17
|
+
process.env.RUNFRAME_STANDALONE_FILE_PATH ||
|
|
18
|
+
path.resolve(
|
|
19
|
+
process.cwd(),
|
|
20
|
+
"node_modules",
|
|
21
|
+
"@tscircuit/runframe/dist/standalone.min.js",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const content = fs.readFileSync(standaloneFilePath, "utf8")
|
|
26
|
+
res.writeHead(200, {
|
|
27
|
+
"Content-Type": "application/javascript; charset=utf-8",
|
|
28
|
+
})
|
|
29
|
+
res.end(content)
|
|
30
|
+
return
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error("Error serving standalone.min.js:", error)
|
|
33
|
+
res.writeHead(404)
|
|
34
|
+
res.end("File not found")
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (url.pathname === "/") {
|
|
40
|
+
const html = await getIndex()
|
|
41
|
+
res.writeHead(200, { "Content-Type": "text/html" })
|
|
42
|
+
res.end(html)
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (url.pathname.startsWith("/api/")) {
|
|
47
|
+
req.url = req.url!.replace("/api/", "/")
|
|
48
|
+
fileServerHandler(req, res)
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
res.writeHead(404)
|
|
53
|
+
res.end("Not found")
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
return new Promise<void>((resolve) => {
|
|
57
|
+
server.listen(port, () => {
|
|
58
|
+
console.log(`Server running at http://localhost:${port}`)
|
|
59
|
+
resolve()
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import pkg from "../../package.json"
|
|
2
|
+
|
|
3
|
+
export const getIndex = async () => {
|
|
4
|
+
return `<html>
|
|
5
|
+
<head>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
9
|
+
<div id="root">loading...</div>
|
|
10
|
+
<script>
|
|
11
|
+
globalThis.process = { env: { NODE_ENV: "production" } }
|
|
12
|
+
</script>
|
|
13
|
+
<script src="/standalone.min.js"></script>
|
|
14
|
+
</body>
|
|
15
|
+
</html>`
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// <script src="https://cdn.jsdelivr.net/npm/@tscircuit/runframe@${pkg.dependencies["@tscircuit/runframe"].replace(/^[^0-9]+/, "")}/dist/standalone.min.js"></script>
|