Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ Useful scripts:

| Script | What it does |
| --- | --- |
| `bun run test` | Run the unit test suite serially |
| `bun run test:coverage` | Run the serial test suite with a coverage report |
| `bun run test` | Run the unit test suite |
| `bun run test:coverage` | Run the test suite with a coverage report |
| `bun run lint` | ESLint over the repo |
| `bun run typecheck` | TypeScript `--noEmit` check |
| `bun run build` | Bundle `src/server.ts` into `dist/` |
Expand Down
27 changes: 14 additions & 13 deletions dist/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ function parseStateText(raw, file) {
function decodeState(value) {
return Schema.decodeUnknown(StateSchema)(value).pipe(Effect.map(mutableState), Effect.map(normalizeState), Effect.mapError((cause) => new StateDecodeError({ cause })));
}
function readStateEffect() {
const file = statePath();
function readStateEffect(file = statePath()) {
return Effect.tryPromise({
try: () => readFile(file, "utf8"),
catch: (cause) => new StateReadError({ cause })
Expand All @@ -252,10 +251,9 @@ function readStateEffect() {
catch: (cause) => new StateDecodeError({ cause })
})), Effect.flatMap(decodeState), Effect.catchAll((error) => error._tag === "StateReadError" && isMissingStateFile(error.cause) ? Effect.succeed(emptyState()) : Effect.fail(error)));
}
function writeStateEffect(state) {
function writeStateEffect(state, file = statePath()) {
return Effect.tryPromise({
try: async () => {
const file = statePath();
await mkdir(dirname2(file), { recursive: true, mode: 448 });
await atomicWriteFile(file, JSON.stringify(state, null, 2) + `
`);
Expand All @@ -277,15 +275,18 @@ function enqueueMutation(operation) {
return current;
}
async function mutate(fn) {
return enqueueMutation(() => Effect.runPromise(Effect.gen(function* () {
const state = yield* readStateEffect();
const result = yield* Effect.tryPromise({
try: () => Promise.resolve(fn(state)),
catch: (cause) => cause instanceof Error ? cause : new Error(String(cause))
});
yield* writeStateEffect(state);
return result;
})));
return enqueueMutation(() => {
const file = statePath();
return Effect.runPromise(Effect.gen(function* () {
const state = yield* readStateEffect(file);
const result = yield* Effect.tryPromise({
try: () => Promise.resolve(fn(state)),
catch: (cause) => cause instanceof Error ? cause : new Error(String(cause))
});
yield* writeStateEffect(state, file);
return result;
}));
});
}
function validateObjective(objective) {
const value = objective.trim();
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
"ci:version": "bun scripts/resolve-ci-version.ts",
"lint": "eslint .",
"pack:dry-run": "npm pack --dry-run",
"test": "bun test --concurrent --max-concurrency 1",
"test:coverage": "bun test --concurrent --max-concurrency 1 --coverage",
"test": "bun test",
"test:coverage": "bun test --coverage",
"typecheck": "tsc --noEmit",
"prepublishOnly": "bun run test && bun run build"
},
Expand Down
19 changes: 9 additions & 10 deletions src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,7 @@ function decodeState(value: unknown) {
)
}

function readStateEffect() {
const file = statePath()
function readStateEffect(file = statePath()) {
return Effect.tryPromise({
try: () => readFile(file, "utf8"),
catch: (cause) => new StateReadError({ cause }),
Expand All @@ -339,10 +338,9 @@ function readStateEffect() {
)
}

function writeStateEffect(state: State) {
function writeStateEffect(state: State, file = statePath()) {
return Effect.tryPromise({
try: async () => {
const file = statePath()
await mkdir(dirname(file), { recursive: true, mode: 0o700 })
// atomicWriteFile writes to a same-directory temp file, fsyncs it, then
// renames it into place: the final path is only ever replaced by a
Expand Down Expand Up @@ -387,19 +385,20 @@ function enqueueMutation<T>(operation: () => Promise<T>) {
}

async function mutate<T>(fn: (state: State) => T | Promise<T>) {
return enqueueMutation(() =>
Effect.runPromise(
return enqueueMutation(() => {
const file = statePath()
return Effect.runPromise(
Effect.gen(function* () {
const state = yield* readStateEffect()
const state = yield* readStateEffect(file)
const result = yield* Effect.tryPromise({
try: () => Promise.resolve(fn(state)),
catch: (cause) => (cause instanceof Error ? cause : new Error(String(cause))),
})
yield* writeStateEffect(state)
yield* writeStateEffect(state, file)
return result
}),
),
)
)
})
}

export function validateObjective(objective: string) {
Expand Down
Loading