feat(sdk): add HttpApi clients and embedded host (#33445)
This commit is contained in:
parent
c45d1db9a0
commit
cdd67cf30f
59 changed files with 4629 additions and 316 deletions
160
packages/httpapi-codegen/test/write.test.ts
Normal file
160
packages/httpapi-codegen/test/write.test.ts
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
import { describe, expect } from "bun:test"
|
||||
import { Effect, FileSystem, Option } from "effect"
|
||||
import { write, type Output } from "../src"
|
||||
import { it } from "./effect"
|
||||
|
||||
describe("HttpApiCodegen.write", () => {
|
||||
it.effect("writes compiled files beneath the output directory", () => {
|
||||
const writes: Array<{ readonly path: string; readonly content: string }> = []
|
||||
const output: Output = {
|
||||
operations: [],
|
||||
files: [{ path: "session.ts", content: "export const session = {}" }],
|
||||
}
|
||||
|
||||
return Effect.gen(function* () {
|
||||
yield* write(output, "/generated")
|
||||
|
||||
expect(writes).toEqual([
|
||||
{ path: "/generated/session.ts", content: "export const session = {}\n" },
|
||||
{ path: "/generated/.httpapi-codegen.json", content: '[\n "session.ts"\n]\n' },
|
||||
])
|
||||
}).pipe(
|
||||
Effect.provideService(
|
||||
FileSystem.FileSystem,
|
||||
FileSystem.makeNoop({
|
||||
exists: () => Effect.succeed(false),
|
||||
makeDirectory: () => Effect.void,
|
||||
writeFileString: (path, content) => {
|
||||
writes.push({ path, content })
|
||||
return Effect.void
|
||||
},
|
||||
}),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
it.effect("removes only stale files owned by the previous manifest", () => {
|
||||
const removed: Array<string> = []
|
||||
return write(
|
||||
{
|
||||
operations: [],
|
||||
files: [{ path: "session.ts", content: "" }],
|
||||
},
|
||||
"/generated",
|
||||
).pipe(
|
||||
Effect.provideService(
|
||||
FileSystem.FileSystem,
|
||||
FileSystem.makeNoop({
|
||||
exists: (path) => Effect.succeed(path.endsWith(".httpapi-codegen.json")),
|
||||
makeDirectory: () => Effect.void,
|
||||
readFileString: () => Effect.succeed('["old.ts", "session.ts"]'),
|
||||
remove: (path) => {
|
||||
removed.push(path)
|
||||
return Effect.void
|
||||
},
|
||||
writeFileString: () => Effect.void,
|
||||
}),
|
||||
),
|
||||
Effect.tap(() => Effect.sync(() => expect(removed).toEqual(["/generated/old.ts"]))),
|
||||
)
|
||||
})
|
||||
|
||||
it.effect("rejects unsafe and duplicate output paths before writing", () => {
|
||||
const writes: Array<string> = []
|
||||
return Effect.gen(function* () {
|
||||
const error = yield* write(
|
||||
{
|
||||
operations: [],
|
||||
files: [
|
||||
{ path: "../outside.ts", content: "" },
|
||||
{ path: "client.ts", content: "" },
|
||||
{ path: "CLIENT.ts", content: "" },
|
||||
],
|
||||
},
|
||||
"/generated",
|
||||
).pipe(Effect.flip)
|
||||
|
||||
expect(error._tag).toBe("GenerationError")
|
||||
expect(writes).toEqual([])
|
||||
}).pipe(
|
||||
Effect.provideService(
|
||||
FileSystem.FileSystem,
|
||||
FileSystem.makeNoop({
|
||||
writeFileString: (path) => {
|
||||
writes.push(path)
|
||||
return Effect.void
|
||||
},
|
||||
}),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
it.effect("rejects case-insensitive duplicate output paths", () => {
|
||||
const writes: Array<string> = []
|
||||
return Effect.gen(function* () {
|
||||
const error = yield* write(
|
||||
{
|
||||
operations: [],
|
||||
files: [
|
||||
{ path: "client.ts", content: "" },
|
||||
{ path: "CLIENT.ts", content: "" },
|
||||
],
|
||||
},
|
||||
"/generated",
|
||||
).pipe(Effect.flip)
|
||||
|
||||
expect(error._tag).toBe("GenerationError")
|
||||
expect(error.reason).toBe("Duplicate output path: CLIENT.ts")
|
||||
expect(writes).toEqual([])
|
||||
}).pipe(
|
||||
Effect.provideService(
|
||||
FileSystem.FileSystem,
|
||||
FileSystem.makeNoop({
|
||||
writeFileString: (path) => {
|
||||
writes.push(path)
|
||||
return Effect.void
|
||||
},
|
||||
}),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
it.effect("reserves the private manifest path", () =>
|
||||
write({ operations: [], files: [{ path: ".httpapi-codegen.json", content: "" }] }, "/generated").pipe(
|
||||
Effect.flip,
|
||||
Effect.tap((error) => Effect.sync(() => expect(error.reason).toContain("Unsafe output path"))),
|
||||
Effect.provideService(FileSystem.FileSystem, FileSystem.makeNoop({})),
|
||||
),
|
||||
)
|
||||
|
||||
it.effect("rejects existing symbolic-link output targets", () =>
|
||||
write({ operations: [], files: [{ path: "session.ts", content: "" }] }, "/generated").pipe(
|
||||
Effect.flip,
|
||||
Effect.tap((error) => Effect.sync(() => expect(error.reason).toBe("Unsafe output path: session.ts"))),
|
||||
Effect.provideService(
|
||||
FileSystem.FileSystem,
|
||||
FileSystem.makeNoop({
|
||||
exists: (path) => Effect.succeed(path.endsWith("session.ts")),
|
||||
makeDirectory: () => Effect.void,
|
||||
stat: () =>
|
||||
Effect.succeed({
|
||||
type: "SymbolicLink",
|
||||
mtime: Option.none(),
|
||||
atime: Option.none(),
|
||||
birthtime: Option.none(),
|
||||
dev: 0,
|
||||
ino: Option.none(),
|
||||
mode: 0,
|
||||
nlink: Option.none(),
|
||||
uid: Option.none(),
|
||||
gid: Option.none(),
|
||||
rdev: Option.none(),
|
||||
size: FileSystem.Size(0),
|
||||
blksize: Option.none(),
|
||||
blocks: Option.none(),
|
||||
}),
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue