/
cmd.ts
176 lines (156 loc) · 5.91 KB
/
cmd.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import * as child_process from "node:child_process"
import * as path from "node:path"
import * as graphstate from "@nothing-but/graphstate"
import { $ } from "bun"
import Watcher from "watcher"
const filename = new URL(import.meta.url).pathname
const root_path = path.dirname(filename)
const api_path = path.join(root_path, "api")
async function main() {
const args = Bun.argv
const command = args[2]
switch (command) {
// fully sets up LA for development (website, desktop, mobile, api, ..)
case "setup":
await setupEnvFiles()
await setupFloxWithDependencies()
await setupEdgeDb()
await setupCursor()
break
case "run":
await run()
break
case "grafbase":
await runGrafbase()
break
case "graphql":
generate_graphql_client()
break
case undefined:
// TODO: move to https://github.com/nikitavoloboev/ts/blob/main/cli/cli.ts
console.log("No command provided")
break
default:
console.log("Unknown command")
break
}
}
// creates necessary .env files and fills it with default values to run LA locally
async function setupEnvFiles() {
// TODO: check that `.env` files are already present
const currentFilePath = import.meta.path
const grafbaseEnvPath = `${currentFilePath.replace("cmd.ts", "grafbase/.env")}`
const grfabaseEnvfileExists = await Bun.file(grafbaseEnvPath).exists()
if (!grfabaseEnvfileExists) {
Bun.write(
grafbaseEnvPath,
`LOCAL=true
EDGEDB_DSN=
PUBLIC_HANKO_API_URL=https://e879ccc9-285e-49d3-b37e-b569f0db4035.hanko.io
INTERNAL_SECRET=secret`,
)
} else {
console.log(`File: ${grafbaseEnvPath} already exists`)
}
const grafbaseEdgedbEnvPath = `${currentFilePath.replace("cmd.ts", "grafbase/edgedb/.env")}`
const grafbaseEdgedbEnvFileExists = await Bun.file(grafbaseEdgedbEnvPath).exists()
if (!grafbaseEdgedbEnvFileExists) {
Bun.write(
grafbaseEdgedbEnvPath,
`LOCAL=true
GRAFBASE_URL=http://127.0.0.1:4000/graphql
GRAFBASE_INTERNAL_SECRET=secret
LOCAL_USER_HANKO_ID=
wikiFolderPath=
email=`,
)
} else {
console.log(`File: ${grafbaseEdgedbEnvPath} already exists`)
}
const websiteEnvFilePath = `${currentFilePath.replace("cmd.ts", "website/.env")}`
const websiteEnvFileExists = await Bun.file(websiteEnvFilePath).exists()
if (!websiteEnvFileExists) {
Bun.write(
websiteEnvFilePath,
`VITE_HANKO_API=https://e879ccc9-285e-49d3-b37e-b569f0db4035.hanko.io
VITE_GRAFBASE_API_URL=http://127.0.0.1:4000/graphql
VITE_GRAFBASE_INTERNAL_SECRET=secret`,
)
} else {
console.log(`File: ${websiteEnvFilePath} already exists`)
}
console.log(".env files created")
}
const graphql_client_header = `/*
This file is generated by \`bun graphql\` command. Do not edit it manually.
To regenerate this file, run \`bun graphql\`.
*/\n\n`
/**
* Generates a GraphQL client based on the schema from grafbase.
*/
async function generate_graphql_client() {
const schema = child_process
.execSync("grafbase introspect --dev", {cwd: api_path})
.toString()
Bun.write("shared/graphql_schema.gql", schema)
const queries = await graphstate.wasm_generate_queries(schema)
if (queries instanceof Error) {
console.error(queries)
return
}
Bun.write("shared/graphql_queries.js", graphql_client_header + queries)
}
async function runGrafbase() {
await generate_graphql_client()
// rerun graphql client generation on changes in grafbase folder
const currentFilePath = import.meta.url.replace("file://", "")
const grafbaseWatchPath = `${currentFilePath.replace("cmd.ts", "api/grafbase")}`
const watcher = new Watcher(grafbaseWatchPath, { recursive: true })
watcher.on("change", async (event) => {
if (event.includes("grafbase.config.ts")) {
await generate_graphql_client()
}
})
// doing > /dev/stdout to get colored output on linux/mac at least, context: https://discord.com/channels/876711213126520882/876711213126520885/1221521173813268581
const res = await $`cd api && grafbase dev > /dev/stdout`
console.log(res)
}
// TODO: maybe have a way to setup full learn-anything workspace in Cursor for users
// it would create `learn-anything` folder somewhere where user specifies
// then inside it would clone these repos into it:
// https://github.com/learn-anything/learn-anything.xyz
// https://github.com/learn-anything/tasks
// https://github.com/learn-anything/explore
// https://github.com/learn-anything/docs
// and then it would create a `learn-anything.code-workspace` file
// where it will include `learn-anything.xyz` folder by default with others commented out
// docs can say that users can add other repos to the workspace file if they want by uncommenting
// below command should automate all of the above
// error checking and proper logging of what happened with links to docs to be included
// async function getFullMonorepo() {
// await $`git clone https://github.com/learn-anything/tasks`
// await $`git clone https://github.com/learn-anything/docs`
// }
// check https://flox.dev is installed, if not, propose to install it, then rerun `bun run init`
// if not possible to automate installing `flox.dev` on behalf of user
// after flox is installed, setup env with all the dependencies with https://flox.dev
async function setupFloxWithDependencies() {
// TODO: check that flox is installed
// TODO: check that flox is setup correctly with all the deps
}
// fully automated way to setup EdgeDB locally with all the necessary data
// taken from files in https://github.com/learn-anything/docs/tree/main/data/seed
async function setupEdgeDb() {
// TODO: check that edgedb is installed, if not, ask user to setup https://flox.dev
// TODO: most likely need to run `getFullMonorepo` so docs repo is available
}
// reccomend to use Cursor as editor and setup it with necessary plugins (Biome) + set it as default formatter
async function setupCursor() {
// TODO:
}
async function run() {
// can use this function to quickly run/test out TS code in scope of project (quick experiments)
// can run it with `bun ts`
// only commit functions/commands that are useful to the project
}
main()