@tscircuit/cli 0.0.6 → 0.0.9

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.
@@ -1,3 +1,7 @@
1
+ import kleur from "kleur"
1
2
  import { AppContext } from "../util/app-context"
2
3
 
3
- export const authLogout = async (ctx: AppContext, args: any) => {}
4
+ export const authLogout = async (ctx: AppContext, args: any) => {
5
+ ctx.profile_config.delete("session_token")
6
+ console.log(kleur.green("Logged out!"))
7
+ }
@@ -0,0 +1,5 @@
1
+ import { AppContext } from "../util/app-context"
2
+
3
+ export const configClear = async (ctx: AppContext, args: any) => {
4
+ ctx.global_config.clear()
5
+ }
@@ -11,6 +11,7 @@ import * as Path from "path"
11
11
  import { startWatcher } from "./start-watcher"
12
12
  import { createOrModifyNpmrc } from "../init/create-or-modify-npmrc"
13
13
  import { checkIfInitialized } from "./check-if-initialized"
14
+ import { initCmd } from "../init"
14
15
 
15
16
  export const devCmd = async (ctx: AppContext, args: any) => {
16
17
  const params = z
@@ -27,12 +28,18 @@ export const devCmd = async (ctx: AppContext, args: any) => {
27
28
  const isInitialized = await checkIfInitialized(ctx)
28
29
 
29
30
  if (!isInitialized) {
30
- console.log(
31
- kleur.red(
32
- `This project is not properly initialized. Please run "tsci init" first, or follow the manual installation steps here:\n\nhttps://github.com/tscircuit/tscircuit/blob/main/docs/manual-installation.md`
33
- )
34
- )
35
- process.exit(1)
31
+ const { confirmInitialize } = await prompts({
32
+ type: "confirm",
33
+ name: "confirmInitialize",
34
+ message: "Would you like to initialize this project now?",
35
+ initial: true,
36
+ })
37
+
38
+ if (confirmInitialize) {
39
+ return initCmd(ctx, {})
40
+ } else {
41
+ process.exit(1)
42
+ }
36
43
  }
37
44
 
38
45
  await createOrModifyNpmrc({ quiet: false }, ctx)
@@ -1,7 +1,7 @@
1
1
  import { AppContext } from "../util/app-context"
2
2
  import { z } from "zod"
3
- import { getDevServerAxios } from "./get-dev-server-axios"
4
- import { uploadExamplesFromDirectory } from "./upload-examples-from-directory"
3
+ import { getDevServerAxios } from "./dev/get-dev-server-axios"
4
+ import { uploadExamplesFromDirectory } from "./dev/upload-examples-from-directory"
5
5
  import { startWatcher } from "./dev/start-watcher"
6
6
 
7
7
  export const devServerUpload = async (ctx: AppContext, args: any) => {
@@ -31,3 +31,5 @@ export { removeCmd as remove } from "./remove"
31
31
  export { installCmd as install } from "./install"
32
32
  export { uninstallCmd as uninstall } from "./uninstall"
33
33
  export { devServerUpload } from "./dev-server-upload"
34
+ export { configClear } from "./config-clear"
35
+ export { openCmd as open } from "./open"
@@ -30,6 +30,17 @@ export const initCmd = async (ctx: AppContext, args: any) => {
30
30
  params.dir = `.`
31
31
  }
32
32
 
33
+ if (!params.name) {
34
+ try {
35
+ const myAccount = await ctx.axios
36
+ .get("/accounts/get")
37
+ .then((r) => r.data.account)
38
+ params.name = `@${myAccount.github_username}/${Path.basename(params.dir)}`
39
+ } catch (e) {
40
+ params.name = Path.basename(params.dir ?? ctx.cwd)
41
+ }
42
+ }
43
+
33
44
  let runtime = params.runtime
34
45
  if (!runtime) {
35
46
  const bunExists = $.commandExistsSync("bun")
@@ -0,0 +1,19 @@
1
+ import { existsSync, readFileSync } from "fs"
2
+ import kleur from "kleur"
3
+ import { AppContext } from "lib/util/app-context"
4
+ import * as Path from "path"
5
+ import open from "open"
6
+
7
+ export const openCmd = async (ctx: AppContext, args: any) => {
8
+ const packageJsonPath = Path.join(ctx.cwd, "package.json")
9
+ if (!existsSync(packageJsonPath)) {
10
+ console.log(kleur.red("No package.json found in current directory"))
11
+ process.exit(1)
12
+ }
13
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"))
14
+
15
+ const registryUrl = `${ctx.registry_url}/${packageJson.name.replace("@", "")}`
16
+
17
+ console.log(`Opening ${registryUrl} in your browser...`)
18
+ await open(registryUrl)
19
+ }
@@ -12,6 +12,7 @@ import { inferExportNameFromSource } from "../dev/infer-export-name-from-source"
12
12
  import $ from "dax-sh"
13
13
  import semver from "semver"
14
14
  import { unlink } from "fs/promises"
15
+ import esbuild from "esbuild"
15
16
 
16
17
  export const publish = async (ctx: AppContext, args: any) => {
17
18
  const params = z
@@ -42,24 +43,31 @@ export const publish = async (ctx: AppContext, args: any) => {
42
43
  )
43
44
 
44
45
  // TODO possibly use esbuild here, it's got stuff like packages: "external"
45
- await Bun.build({
46
- root: ctx.cwd,
47
- // TODO determine entrypoint in a more clever way e.g.
48
- // - package.json "main"
49
- entrypoints: ["index.ts"],
46
+ // await Bun.build({
47
+ // root: ctx.cwd,
48
+ // // TODO determine entrypoint in a more clever way e.g.
49
+ // // - package.json "main"
50
+ // entrypoints: ["index.ts"],
50
51
 
51
- // Everything should be external since it's a node module, esbuild has a
52
- // packages: "external" option for this
53
- external: [
54
- ...Object.keys(packageJson.dependencies || {}),
55
- ...Object.keys(packageJson.devDependencies || {}),
56
- ...Object.keys(packageJson.peerDependencies || {}),
57
- ...Object.keys(packageJson.trustedDependencies || {}),
58
- ],
52
+ // // Everything should be external since it's a node module, esbuild has a
53
+ // // packages: "external" option for this
54
+ // external: [
55
+ // ...Object.keys(packageJson.dependencies || {}),
56
+ // ...Object.keys(packageJson.devDependencies || {}),
57
+ // ...Object.keys(packageJson.peerDependencies || {}),
58
+ // ...Object.keys(packageJson.trustedDependencies || {}),
59
+ // ],
59
60
 
60
- outdir: "dist",
61
+ // outdir: "dist",
61
62
 
62
- target: "node",
63
+ // target: "node",
64
+ // })
65
+ await esbuild.build({
66
+ entryPoints: ["index.ts"], // TODO dynamically determine entrypoint
67
+ bundle: true,
68
+ platform: "node",
69
+ packages: "external",
70
+ outdir: "dist",
63
71
  })
64
72
 
65
73
  // Publish to npm??
@@ -0,0 +1,89 @@
1
+ import Configstore from "configstore"
2
+
3
+ interface ProfileConfigProps {
4
+ session_token?: string
5
+ registry_url?: string
6
+ }
7
+
8
+ interface GlobalConfigProps {
9
+ current_profile?: string
10
+ log_requests?: boolean
11
+ }
12
+
13
+ interface TypedConfigstore<T extends Record<string, any>> {
14
+ /**
15
+ * Get the path to the config file. Can be used to show the user
16
+ * where it is, or better, open it for them.
17
+ */
18
+ path: string
19
+
20
+ /**
21
+ * Get all items as an object or replace the current config with an object.
22
+ */
23
+ all: any
24
+
25
+ /**
26
+ * Get the item count
27
+ */
28
+ size: number
29
+
30
+ /**
31
+ * Get an item
32
+ * @param key The string key to get
33
+ * @return The contents of the config from key $key
34
+ */
35
+ get(key: keyof T): any
36
+
37
+ /**
38
+ * Set an item
39
+ * @param key The string key
40
+ * @param val The value to set
41
+ */
42
+ set<K extends keyof T>(key: K, val: T[K]): void
43
+
44
+ /**
45
+ * Determines if a key is present in the config
46
+ * @param key The string key to test for
47
+ * @return True if the key is present
48
+ */
49
+ has(key: keyof T): boolean
50
+
51
+ /**
52
+ * Delete an item.
53
+ * @param key The key to delete
54
+ */
55
+ delete(key: keyof T): void
56
+
57
+ /**
58
+ * Clear the config.
59
+ * Equivalent to <code>Configstore.all = {};</code>
60
+ */
61
+ clear(): void
62
+ }
63
+
64
+ export interface ContextConfigProps {
65
+ profile_config: TypedConfigstore<ProfileConfigProps>
66
+ global_config: TypedConfigstore<GlobalConfigProps>
67
+ current_profile: string
68
+ }
69
+
70
+ export const createConfigHandler = ({
71
+ profile,
72
+ }: {
73
+ profile?: string
74
+ }): ContextConfigProps => {
75
+ const global_config: TypedConfigstore<GlobalConfigProps> = new Configstore(
76
+ "tsci"
77
+ )
78
+ const current_profile =
79
+ profile ?? global_config.get("current_profile") ?? "default"
80
+
81
+ const profile_config: TypedConfigstore<ProfileConfigProps> = {
82
+ get: (key: string) =>
83
+ (global_config as any).get(`profiles.${current_profile}.${key}`),
84
+ set: (key: string, value: any) =>
85
+ (global_config as any).set(`profiles.${current_profile}.${key}`, value),
86
+ } as any
87
+
88
+ return { profile_config, global_config, current_profile }
89
+ }
@@ -241,5 +241,7 @@ export const getProgram = (ctx: AppContext) => {
241
241
  .option("-p, --port", "Port dev server is running on (default: 3020)")
242
242
  .action((args) => CMDFN.devServerUpload(ctx, args))
243
243
 
244
+ cmd.command("open").action((args) => CMDFN.open(ctx, args))
245
+
244
246
  return cmd
245
247
  }
@@ -1,5 +1,6 @@
1
1
  import { AxiosInstance } from "axios"
2
2
  import Configstore from "configstore"
3
+ import { ContextConfigProps } from "lib/create-config-manager"
3
4
 
4
5
  export type AppContext = {
5
6
  args: any
@@ -8,7 +9,5 @@ export type AppContext = {
8
9
  params: Record<string, any>
9
10
  registry_url: string
10
11
  axios: AxiosInstance
11
- profile: string
12
- profile_config: Configstore
13
- global_config: Configstore
14
- }
12
+ current_profile: string
13
+ } & ContextConfigProps
@@ -8,6 +8,8 @@ import { getProgram } from "../get-program"
8
8
  import defaultAxios from "axios"
9
9
  import kleur from "kleur"
10
10
  import { PARAM_HANDLERS_BY_PARAM_NAME } from "lib/param-handlers"
11
+ import { createConfigHandler } from "lib/create-config-manager"
12
+ import dargs from "dargs"
11
13
 
12
14
  export type CliArgs = {
13
15
  cmd: string[]
@@ -18,15 +20,10 @@ export type CliArgs = {
18
20
  export const createContextAndRunProgram = async (process_args: any) => {
19
21
  const args = minimist(process_args)
20
22
 
21
- const global_config = new Configstore("tsci")
22
- const current_profile =
23
- args.profile ?? global_config.get("current_profile") ?? "default"
24
- const profile_config: typeof global_config = {
25
- get: (key: string) =>
26
- global_config.get(`profiles.${current_profile}.${key}`),
27
- set: (key: string, value: any) =>
28
- global_config.set(`profiles.${current_profile}.${key}`, value),
29
- } as any
23
+ const { global_config, profile_config, current_profile } =
24
+ createConfigHandler({
25
+ profile: args.profile,
26
+ })
30
27
 
31
28
  // Load registry commands
32
29
  const registry_url =
@@ -71,6 +68,15 @@ export const createContextAndRunProgram = async (process_args: any) => {
71
68
  axios.interceptors.response.use(
72
69
  (res) => res,
73
70
  (err) => {
71
+ // ---- IGNORE LOGGING *_not_found --------
72
+ if (
73
+ err.config.data?.error?.error_code === "package_not_found" ||
74
+ err.config.data?.error?.error_code === "package_release_not_found"
75
+ ) {
76
+ return Promise.reject(err)
77
+ }
78
+ // end ignores ---
79
+
74
80
  console.log(
75
81
  kleur.red(
76
82
  `[ERR] ${err.response?.status} ${err.config.method?.toUpperCase()} ${
@@ -88,7 +94,7 @@ export const createContextAndRunProgram = async (process_args: any) => {
88
94
  const ctx: AppContext = {
89
95
  cmd: args._,
90
96
  cwd: args.cwd ?? process.cwd(),
91
- profile: current_profile,
97
+ current_profile,
92
98
  registry_url,
93
99
  axios,
94
100
  global_config,
@@ -101,7 +107,12 @@ export const createContextAndRunProgram = async (process_args: any) => {
101
107
  params: args,
102
108
  }
103
109
 
104
- await perfectCli(getProgram(ctx), process.argv, {
110
+ delete args["cwd"]
111
+
112
+ const { _: positional, ...flagsAndParams } = args
113
+ const args_without_globals = positional.concat(dargs(flagsAndParams))
114
+
115
+ await perfectCli(getProgram(ctx), args_without_globals, {
105
116
  async customParamHandler({ commandPath, optionName }, { prompts }) {
106
117
  const optionNameHandler =
107
118
  PARAM_HANDLERS_BY_PARAM_NAME[_.snakeCase(optionName)]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/cli",
3
- "version": "0.0.6",
3
+ "version": "0.0.9",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Command line tool for developing, publishing and installing tscircuit circuits",
@@ -32,9 +32,11 @@
32
32
  "chokidar": "^3.6.0",
33
33
  "commander": "^12.0.0",
34
34
  "configstore": "^6.0.0",
35
+ "dargs": "^8.1.0",
35
36
  "dax-sh": "^0.39.2",
36
37
  "delay": "^6.0.0",
37
38
  "edgespec": "^0.0.69",
39
+ "esbuild": "^0.20.2",
38
40
  "glob": "^10.3.10",
39
41
  "hono": "^4.1.0",
40
42
  "ignore": "^5.3.1",
@@ -0,0 +1,9 @@
1
+ import { test, expect } from "bun:test"
2
+ import { $ } from "bun"
3
+
4
+ test("tsci open", async () => {
5
+ const result =
6
+ await $`bun cli.ts open -y --cwd ./tests/assets/example-project`.text()
7
+ expect(result).toContain("http")
8
+ expect(result).toContain("example-project")
9
+ })