@usehyper/cli 0.1.0
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 +31 -0
- package/package.json +40 -0
- package/registry-sources/agent-rules/README.md +12 -0
- package/registry-sources/agent-rules/files/.cursor/rules/hyper.md +178 -0
- package/registry-sources/agent-rules/files/AGENTS.md +64 -0
- package/registry-sources/agent-rules/manifest.json +15 -0
- package/src/__tests__/add.test.ts +125 -0
- package/src/__tests__/cli.test.ts +50 -0
- package/src/__tests__/security.test.ts +101 -0
- package/src/args.ts +38 -0
- package/src/bin.ts +77 -0
- package/src/commands/add.ts +232 -0
- package/src/commands/bench.ts +185 -0
- package/src/commands/build.ts +146 -0
- package/src/commands/client.ts +78 -0
- package/src/commands/dev.ts +53 -0
- package/src/commands/diff.ts +80 -0
- package/src/commands/env.ts +92 -0
- package/src/commands/help.ts +42 -0
- package/src/commands/init.ts +119 -0
- package/src/commands/list.ts +46 -0
- package/src/commands/mcp.ts +51 -0
- package/src/commands/openapi.ts +50 -0
- package/src/commands/routes.ts +45 -0
- package/src/commands/security.ts +233 -0
- package/src/commands/test.ts +191 -0
- package/src/commands/typecheck.ts +19 -0
- package/src/commands/update.ts +91 -0
- package/src/commands/version.ts +16 -0
- package/src/config/index.ts +30 -0
- package/src/config/io.ts +112 -0
- package/src/config/tsconfig.ts +138 -0
- package/src/config/types.ts +63 -0
- package/src/entry.ts +42 -0
- package/src/index.ts +57 -0
- package/src/load-app.ts +89 -0
- package/src/registry/__tests__/env-writer.test.ts +83 -0
- package/src/registry/apply.ts +268 -0
- package/src/registry/client.ts +127 -0
- package/src/registry/env-writer.ts +135 -0
- package/src/registry/index.ts +18 -0
- package/src/registry/rewrite.ts +177 -0
- package/src/registry/snapshot.ts +1018 -0
- package/src/registry/types.ts +62 -0
- package/src/templates.ts +141 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire-format types for the Hyper registry. Mirrors `tools/registry-types.ts`
|
|
3
|
+
* one-to-one — kept here so the CLI has zero workspace deps on `tools/`.
|
|
4
|
+
*
|
|
5
|
+
* Anyone can host their own registry by serving JSON in this shape at:
|
|
6
|
+
* GET <registryUrl>/r/index.json
|
|
7
|
+
* GET <registryUrl>/r/<name>.json
|
|
8
|
+
* GET <registryUrl>/r/<name>@<version>.json
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface RegistryFile {
|
|
12
|
+
readonly path: string
|
|
13
|
+
readonly contents: string
|
|
14
|
+
readonly sha256: string
|
|
15
|
+
/**
|
|
16
|
+
* Optional override for where this file lands in the user's project.
|
|
17
|
+
* Placeholders: `@base/...`, `@root/...`, `@cursor/...`, `~/...`.
|
|
18
|
+
* See `tools/registry-types.ts` for full semantics.
|
|
19
|
+
*/
|
|
20
|
+
readonly target?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface RegistryComponent {
|
|
24
|
+
/** JSON Schema URL emitted by the registry — present in HTTP responses. */
|
|
25
|
+
readonly $schema?: string
|
|
26
|
+
readonly name: string
|
|
27
|
+
readonly version: string
|
|
28
|
+
readonly title?: string
|
|
29
|
+
readonly description: string
|
|
30
|
+
readonly readme: string
|
|
31
|
+
readonly registryDeps: readonly string[]
|
|
32
|
+
readonly peerDeps: Readonly<Record<string, string>>
|
|
33
|
+
readonly optionalPeerDeps: Readonly<Record<string, string>>
|
|
34
|
+
readonly files: readonly RegistryFile[]
|
|
35
|
+
readonly subpaths: Readonly<Record<string, string>>
|
|
36
|
+
/**
|
|
37
|
+
* Env vars the component needs at runtime. The CLI appends them to
|
|
38
|
+
* `.env.local` (existing keys preserved). `${random:hex:N}` and
|
|
39
|
+
* `${random:base64:N}` are resolved locally with `crypto.randomBytes`.
|
|
40
|
+
*/
|
|
41
|
+
readonly envVars?: Readonly<Record<string, string>>
|
|
42
|
+
/** Markdown blurb printed after `hyper add`. */
|
|
43
|
+
readonly docs?: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface RegistryIndexEntry {
|
|
47
|
+
readonly name: string
|
|
48
|
+
readonly version: string
|
|
49
|
+
readonly title?: string
|
|
50
|
+
readonly description: string
|
|
51
|
+
readonly registryDeps: readonly string[]
|
|
52
|
+
readonly fileCount: number
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface RegistryIndex {
|
|
56
|
+
/** JSON Schema URL emitted by the registry — present in HTTP responses. */
|
|
57
|
+
readonly $schema?: string
|
|
58
|
+
readonly schema: 1
|
|
59
|
+
readonly generatedAt: string
|
|
60
|
+
readonly source: string
|
|
61
|
+
readonly components: readonly RegistryIndexEntry[]
|
|
62
|
+
}
|
package/src/templates.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in scaffolding templates.
|
|
3
|
+
*
|
|
4
|
+
* After `hyper init`, the CLI runs `hyper add core` to copy the framework
|
|
5
|
+
* source into `<baseDir>/core/`. Templates therefore have NO `@usehyper/*`
|
|
6
|
+
* runtime deps — imports use `@hyper/core` and resolve via tsconfig paths.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface Template {
|
|
10
|
+
readonly name: string
|
|
11
|
+
/** Files emitted by `hyper init`. Paths are relative to the project root. */
|
|
12
|
+
readonly files: Readonly<Record<string, string>>
|
|
13
|
+
/** Components installed via `hyper add` after the files are written. */
|
|
14
|
+
readonly components: readonly string[]
|
|
15
|
+
/**
|
|
16
|
+
* Peer deps that should land in `package.json` immediately. The CLI prints
|
|
17
|
+
* a one-liner suggesting `bun add` for these.
|
|
18
|
+
*/
|
|
19
|
+
readonly extraPeerDeps?: Readonly<Record<string, string>>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const MINIMAL_APP = `import { Hyper, ok } from "@hyper/core"
|
|
23
|
+
|
|
24
|
+
export default new Hyper()
|
|
25
|
+
.get("/health", () => ok({ ok: true }))
|
|
26
|
+
.get("/hello/:name", ({ params }) => ok({ hello: params.name }))
|
|
27
|
+
.listen(Number(process.env.PORT ?? 3000))
|
|
28
|
+
`
|
|
29
|
+
|
|
30
|
+
const MINIMAL_TSCONFIG = `{
|
|
31
|
+
"compilerOptions": {
|
|
32
|
+
"target": "ES2024",
|
|
33
|
+
"lib": ["ES2024"],
|
|
34
|
+
"module": "preserve",
|
|
35
|
+
"moduleResolution": "bundler",
|
|
36
|
+
"strict": true,
|
|
37
|
+
"noUncheckedIndexedAccess": true,
|
|
38
|
+
"exactOptionalPropertyTypes": true,
|
|
39
|
+
"verbatimModuleSyntax": true,
|
|
40
|
+
"allowImportingTsExtensions": true,
|
|
41
|
+
"noEmit": true,
|
|
42
|
+
"skipLibCheck": true,
|
|
43
|
+
"types": ["@types/bun"],
|
|
44
|
+
"paths": {
|
|
45
|
+
"@hyper/*": ["./src/hyper/*", "./src/hyper/*/index.ts"]
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"include": ["src/**/*.ts", "test/**/*.ts"]
|
|
49
|
+
}
|
|
50
|
+
`
|
|
51
|
+
|
|
52
|
+
const MINIMAL_PKG = `{
|
|
53
|
+
"name": "my-hyper-app",
|
|
54
|
+
"type": "module",
|
|
55
|
+
"private": true,
|
|
56
|
+
"scripts": {
|
|
57
|
+
"dev": "bun --hot src/app.ts",
|
|
58
|
+
"start": "bun src/app.ts",
|
|
59
|
+
"test": "bun test",
|
|
60
|
+
"typecheck": "tsc --noEmit"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/bun": "latest",
|
|
64
|
+
"typescript": "^5.6.0"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`
|
|
68
|
+
|
|
69
|
+
const API_APP = `import { Hyper, ok, route } from "@hyper/core"
|
|
70
|
+
import { hyperLog } from "@hyper/log"
|
|
71
|
+
|
|
72
|
+
const health = route.get("/health").handle(() => ok({ ok: true }))
|
|
73
|
+
const listUsers = route.get("/users").handle(() => ok([{ id: "u1", name: "Ada" }]))
|
|
74
|
+
const getUser = route
|
|
75
|
+
.get("/users/:id")
|
|
76
|
+
.handle(({ params }) => ok({ id: params.id, name: "Ada" }))
|
|
77
|
+
|
|
78
|
+
export default new Hyper()
|
|
79
|
+
.use(hyperLog({ service: "my-hyper-app" }))
|
|
80
|
+
.use([health, listUsers, getUser])
|
|
81
|
+
.listen(Number(process.env.PORT ?? 3000))
|
|
82
|
+
`
|
|
83
|
+
|
|
84
|
+
const HEALTH_TEST = `import { describe, expect, test } from "bun:test"
|
|
85
|
+
import app from "../src/app.ts"
|
|
86
|
+
|
|
87
|
+
describe("app", () => {
|
|
88
|
+
test("GET /health returns ok", async () => {
|
|
89
|
+
const res = await app.fetch(new Request("http://localhost/health"))
|
|
90
|
+
expect(res.status).toBe(200)
|
|
91
|
+
expect(await res.json()).toEqual({ ok: true })
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
`
|
|
95
|
+
|
|
96
|
+
const README = `# my-hyper-app
|
|
97
|
+
|
|
98
|
+
A Hyper app. The framework source lives under \`src/hyper/<component>/\` —
|
|
99
|
+
managed by the \`hyper\` CLI.
|
|
100
|
+
|
|
101
|
+
## Develop
|
|
102
|
+
|
|
103
|
+
\`\`\`bash
|
|
104
|
+
bun install
|
|
105
|
+
bun run dev
|
|
106
|
+
\`\`\`
|
|
107
|
+
|
|
108
|
+
## Manage components
|
|
109
|
+
|
|
110
|
+
\`\`\`bash
|
|
111
|
+
hyper list # browse the registry
|
|
112
|
+
hyper add cors # add a component
|
|
113
|
+
hyper diff log # inspect drift on an installed component
|
|
114
|
+
hyper update # pull the latest registry versions
|
|
115
|
+
\`\`\`
|
|
116
|
+
`
|
|
117
|
+
|
|
118
|
+
export const TEMPLATES: Record<string, Template> = {
|
|
119
|
+
minimal: {
|
|
120
|
+
name: "minimal",
|
|
121
|
+
files: {
|
|
122
|
+
"src/app.ts": MINIMAL_APP,
|
|
123
|
+
"tsconfig.json": MINIMAL_TSCONFIG,
|
|
124
|
+
"package.json": MINIMAL_PKG,
|
|
125
|
+
"test/app.test.ts": HEALTH_TEST,
|
|
126
|
+
"README.md": README,
|
|
127
|
+
},
|
|
128
|
+
components: ["core"],
|
|
129
|
+
},
|
|
130
|
+
api: {
|
|
131
|
+
name: "api",
|
|
132
|
+
files: {
|
|
133
|
+
"src/app.ts": API_APP,
|
|
134
|
+
"tsconfig.json": MINIMAL_TSCONFIG,
|
|
135
|
+
"package.json": MINIMAL_PKG,
|
|
136
|
+
"test/app.test.ts": HEALTH_TEST,
|
|
137
|
+
"README.md": README,
|
|
138
|
+
},
|
|
139
|
+
components: ["core", "log"],
|
|
140
|
+
},
|
|
141
|
+
}
|