asphodelos 0.0.1 → 0.2.1
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/README.md
CHANGED
|
@@ -250,10 +250,6 @@ export default defineConfig({
|
|
|
250
250
|
})
|
|
251
251
|
```
|
|
252
252
|
|
|
253
|
-
TanStack-family mutations also get a `<operation>MutationOptions()` factory, and SWR queries a
|
|
254
|
-
`useImmutable<Operation>` hook. The generated hooks are compiled and run against the real
|
|
255
|
-
libraries in [`test/`](test/README.md).
|
|
256
|
-
|
|
257
253
|
### Infinite Query (`x-pagination`)
|
|
258
254
|
|
|
259
255
|
Set `x-pagination: true` on a GET operation to generate infinite query hooks.
|
|
@@ -511,7 +507,7 @@ name:
|
|
|
511
507
|
| String | `x-minLength-message`, `x-maxLength-message`, `x-pattern-message`, `x-length-message` |
|
|
512
508
|
| Array | `x-minItems-message`, `x-maxItems-message`, `x-uniqueItems-message`, `x-contains-message`, `x-minContains-message`, `x-maxContains-message`, `x-prefixItems-message`, `x-items-message` |
|
|
513
509
|
| Object | `x-minProperties-message`, `x-maxProperties-message`, `x-additionalProperties-message`†, `x-propertyNames-message`, `x-patternProperties-message`†, `x-dependentRequired-message`, `x-dependentSchemas-message`, `x-properties-message`†, `x-unevaluatedProperties-message`†, `x-unevaluatedItems-message`† |
|
|
514
|
-
|
|
|
510
|
+
| Composition | `x-allOf-message`‡, `x-anyOf-message`, `x-oneOf-message`, `x-not-message`, `x-implication-message` |
|
|
515
511
|
| Conditional | `x-if-message`†, `x-then-message`†, `x-else-message`† |
|
|
516
512
|
|
|
517
513
|
- † Kept on the schema, but Elysia 1.4 cannot route a 422 to it.
|
|
@@ -586,7 +582,7 @@ bun run test:clients # build, then compile and run the generated hooks under t
|
|
|
586
582
|
bun run test:pack # build, pack, and install the tarball with npm into an empty project
|
|
587
583
|
```
|
|
588
584
|
|
|
589
|
-
Coding agents: start with [AGENTS.md](AGENTS.md).
|
|
585
|
+
Coding agents: start with [AGENTS.md](https://github.com/nakita628/asphodelos/blob/main/AGENTS.md).
|
|
590
586
|
|
|
591
587
|
## License
|
|
592
588
|
|
package/dist/cli.mjs
CHANGED
|
@@ -45,7 +45,7 @@ function runConfigPass(configPath, reload) {
|
|
|
45
45
|
import("./index.mjs"),
|
|
46
46
|
import("./openapi-B4aAnx4P.mjs").then((n) => n.t),
|
|
47
47
|
import("./format-B0W7HIAg.mjs").then((n) => n.r),
|
|
48
|
-
import("./shared-
|
|
48
|
+
import("./shared-B-ADz5ww.mjs").then((n) => n.a)
|
|
49
49
|
]));
|
|
50
50
|
const config = yield* readConfig(configPath, reload);
|
|
51
51
|
const jobs = makeJob(yield* parseOpenAPI(config.input), config);
|
|
@@ -102,7 +102,7 @@ function awaitChange(configPath, inputDirectory) {
|
|
|
102
102
|
* not take the watcher down with it.
|
|
103
103
|
*
|
|
104
104
|
* Recursive rather than a loop because the directory to watch comes from the config, and the
|
|
105
|
-
* config is re-read every round: an edit that
|
|
105
|
+
* config is re-read every round: an edit that points `input` somewhere else has to move the watcher
|
|
106
106
|
* with it, which means new streams rather than new values.
|
|
107
107
|
*/
|
|
108
108
|
function watchConfig(configPath, inputDirectory) {
|
|
@@ -140,7 +140,7 @@ function generate(args) {
|
|
|
140
140
|
if (output !== void 0 && input === void 0) return yield* reject("-o <output.ts> requires an <input> document.");
|
|
141
141
|
if (args.watch && (input !== void 0 || output !== void 0)) return yield* reject("--watch runs a config file, so it cannot be combined with <input> or --output.");
|
|
142
142
|
if (input !== void 0 && output !== void 0) {
|
|
143
|
-
const [{ parseOpenAPI }, { elysia }] = yield* Effect.promise(() => Promise.all([import("./openapi-B4aAnx4P.mjs").then((n) => n.t), import("./core-
|
|
143
|
+
const [{ parseOpenAPI }, { elysia }] = yield* Effect.promise(() => Promise.all([import("./openapi-B4aAnx4P.mjs").then((n) => n.t), import("./core-C1NqA5VJ.mjs").then((n) => n.t)]));
|
|
144
144
|
return yield* Console.log(yield* elysia(yield* parseOpenAPI(input), { output }));
|
|
145
145
|
}
|
|
146
146
|
const resolvedConfig = configPath ?? DEFAULT_CONFIG_FILE;
|
|
@@ -385,7 +385,7 @@ function sccSchemas(schemas) {
|
|
|
385
385
|
const lowlink = /* @__PURE__ */ new Map();
|
|
386
386
|
const onStack = /* @__PURE__ */ new Set();
|
|
387
387
|
const stack = [];
|
|
388
|
-
const
|
|
388
|
+
const groups = [];
|
|
389
389
|
const counter = { value: 0 };
|
|
390
390
|
const strongconnect = (v) => {
|
|
391
391
|
index.set(v, counter.value);
|
|
@@ -407,11 +407,11 @@ function sccSchemas(schemas) {
|
|
|
407
407
|
if (def) group.push(def);
|
|
408
408
|
if (w === v) break;
|
|
409
409
|
}
|
|
410
|
-
|
|
410
|
+
groups.push(group);
|
|
411
411
|
}
|
|
412
412
|
};
|
|
413
413
|
for (const { name } of schemas) if (!index.has(name)) strongconnect(name);
|
|
414
|
-
return
|
|
414
|
+
return groups;
|
|
415
415
|
}
|
|
416
416
|
const REF_SUFFIX = {
|
|
417
417
|
schemas: "Schema",
|
|
@@ -1666,12 +1666,12 @@ function fileNameOf(group) {
|
|
|
1666
1666
|
return uncapitalize(group.map((g) => g.name).toSorted()[0] ?? "schema");
|
|
1667
1667
|
}
|
|
1668
1668
|
function splitSchemaFiles(section, readonly, exportTypes) {
|
|
1669
|
-
const
|
|
1669
|
+
const groups = sccSchemas(Object.entries(section).map(([name, schema]) => ({
|
|
1670
1670
|
name,
|
|
1671
1671
|
schema
|
|
1672
1672
|
})));
|
|
1673
|
-
const nameToFile = new Map(
|
|
1674
|
-
return
|
|
1673
|
+
const nameToFile = new Map(groups.flatMap((g) => g.map((s) => [s.name, fileNameOf(g)])));
|
|
1674
|
+
return groups.map((group) => {
|
|
1675
1675
|
const fileName = fileNameOf(group);
|
|
1676
1676
|
const body = schemasCode(Object.fromEntries(group.map((g) => [g.name, g.schema])), readonly, exportTypes);
|
|
1677
1677
|
if (body === "") return {
|
|
@@ -2248,8 +2248,9 @@ function optionsObjectType(config, optionsType) {
|
|
|
2248
2248
|
}
|
|
2249
2249
|
const QUERY_OMIT_KEYS = `'queryKey' | 'queryFn'`;
|
|
2250
2250
|
const INFINITE_OMIT_KEYS = `'queryKey' | 'queryFn' | 'initialPageParam' | 'getNextPageParam'`;
|
|
2251
|
-
|
|
2252
|
-
|
|
2251
|
+
const MUTATION_OMIT_KEYS = `'mutationKey' | 'mutationFn'`;
|
|
2252
|
+
function omitInjectedKeys(config, optionsType, keys, marker = "{ queryKey: unknown }") {
|
|
2253
|
+
return `Omit<${config.maybeRefOptions ? `Extract<${optionsType}, ${marker}>` : optionsObjectType(config, optionsType)}, ${keys}>`;
|
|
2253
2254
|
}
|
|
2254
2255
|
function makeGetQueryOptionsParam(config, dataT, keyName) {
|
|
2255
2256
|
const optType = config.queryOptionsType;
|
|
@@ -2260,8 +2261,8 @@ function makeGetQueryOptionsParam(config, dataT, keyName) {
|
|
|
2260
2261
|
return `queryOptions?: ${omit(`${optType}<${dataT}, TError, TData>`)}`;
|
|
2261
2262
|
}
|
|
2262
2263
|
function makeMutationOptionsParam(config, dataT, errorT, variablesType) {
|
|
2263
|
-
const optType = `${config.mutationOptionsType}<${dataT}, ${errorT}, ${variablesType}
|
|
2264
|
-
return config.thunkOptionsCall ? `mutationOptions?: () => ${
|
|
2264
|
+
const optType = omitInjectedKeys(config, `${config.mutationOptionsType}<${dataT}, ${errorT}, ${variablesType}>`, MUTATION_OMIT_KEYS, "{ mutationKey?: unknown }");
|
|
2265
|
+
return config.thunkOptionsCall ? `mutationOptions?: () => ${optType}` : `mutationOptions?: ${optType}`;
|
|
2265
2266
|
}
|
|
2266
2267
|
function makeGetHookBody(config, dataT, keyCall, queryFnBlock) {
|
|
2267
2268
|
const inner = `${config.thunkOptionsCall ? "...queryOptions?.()" : "...queryOptions"},queryKey:${keyCall},${queryFnBlock}`;
|
|
@@ -3427,7 +3428,7 @@ function delayMiddleware(delay) {
|
|
|
3427
3428
|
* test) starts no server.
|
|
3428
3429
|
*
|
|
3429
3430
|
* A secured operation that declares a 401 checks for the credential first, and a path parameter
|
|
3430
|
-
* with a
|
|
3431
|
+
* with a recognizable "missing" value answers 404 — so a client can drive the unhappy paths the
|
|
3431
3432
|
* document promises, not just the happy one.
|
|
3432
3433
|
*/
|
|
3433
3434
|
function makeMock(spec, options = {}) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs";
|
|
2
|
-
import { S as unlink, _ as responses, a as hooks, c as mediaTypes, d as links, f as securitySchemes, g as parameters, h as examples, i as mock, l as pathItems, m as requestBodies, n as types, o as elysia, p as headers, r as test, s as eden, u as callbacks, v as schemas, x as readdir, y as components } from "./core-
|
|
2
|
+
import { S as unlink, _ as responses, a as hooks, c as mediaTypes, d as links, f as securitySchemes, g as parameters, h as examples, i as mock, l as pathItems, m as requestBodies, n as types, o as elysia, p as headers, r as test, s as eden, u as callbacks, v as schemas, x as readdir, y as components } from "./core-C1NqA5VJ.mjs";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
import path, { posix } from "node:path";
|
|
5
5
|
//#region src/shared/index.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { parseConfig } from "../index.mjs";
|
|
2
2
|
import { t as FormatOptions } from "../format-B0W7HIAg.mjs";
|
|
3
|
-
import { b as fileSystemLayer } from "../core-
|
|
3
|
+
import { b as fileSystemLayer } from "../core-C1NqA5VJ.mjs";
|
|
4
4
|
import { n as parseOpenAPI } from "../openapi-B4aAnx4P.mjs";
|
|
5
|
-
import { i as makeJob, n as isUserCodeJob, r as jobTargets, t as cleanSplitOutputs } from "../shared-
|
|
5
|
+
import { i as makeJob, n as isUserCodeJob, r as jobTargets, t as cleanSplitOutputs } from "../shared-B-ADz5ww.mjs";
|
|
6
6
|
import { Effect, FileSystem, Result } from "effect";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import crypto from "node:crypto";
|
|
@@ -42,7 +42,7 @@ function messageOf(error) {
|
|
|
42
42
|
/**
|
|
43
43
|
* Loads and validates the config through Vite's own module loader.
|
|
44
44
|
*
|
|
45
|
-
* `ssrLoadModule` rather than the CLI's `readConfig`: Vite already
|
|
45
|
+
* `ssrLoadModule` rather than the CLI's `readConfig`: Vite already compiles TypeScript and
|
|
46
46
|
* resolves the config's imports the way the rest of the project sees them, and invalidating the
|
|
47
47
|
* module is how an edit is picked up. Every failure comes back as the sentence to print.
|
|
48
48
|
*/
|
|
@@ -178,7 +178,7 @@ function removeStaleOutput(output, keep) {
|
|
|
178
178
|
/**
|
|
179
179
|
* Removes what the previous pass generated and this one no longer does, answering with what went.
|
|
180
180
|
*
|
|
181
|
-
* A config edit that
|
|
181
|
+
* A config edit that moves or drops an output, or a document that no longer has a section,
|
|
182
182
|
* would otherwise leave the old file behind, still importing names that are gone. Deliberately
|
|
183
183
|
* narrower than a recursive delete, because a path the config used to name may be shared with the
|
|
184
184
|
* user:
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asphodelos",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Asphodelos is a code generator from OpenAPI to Elysia",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"elysia",
|
|
7
7
|
"openapi"
|
|
@@ -36,22 +36,17 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
|
-
"dev": "bun run src/index.ts",
|
|
40
39
|
"build": "tsdown",
|
|
41
40
|
"lint": "oxlint",
|
|
42
|
-
"lint:fix": "oxlint --fix",
|
|
43
41
|
"test": "bun test",
|
|
44
|
-
"typecheck": "tsc --noEmit"
|
|
45
|
-
"prepublishOnly": "bun run build",
|
|
46
|
-
"prepack": "cp ../../README.md ../../LICENSE .",
|
|
47
|
-
"postpack": "rm -f README.md LICENSE"
|
|
42
|
+
"typecheck": "tsc --noEmit"
|
|
48
43
|
},
|
|
49
44
|
"dependencies": {
|
|
50
45
|
"@apidevtools/swagger-parser": "^12.1.0",
|
|
51
46
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
52
47
|
"@effect/platform-node-shared": "4.0.0-rc.112",
|
|
53
|
-
"@typespec/compiler": "^1.
|
|
54
|
-
"@typespec/openapi3": "^1.
|
|
48
|
+
"@typespec/compiler": "^1.16.0",
|
|
49
|
+
"@typespec/openapi3": "^1.16.0",
|
|
55
50
|
"effect": "4.0.0-rc.112",
|
|
56
51
|
"oxfmt": "^0.67.0",
|
|
57
52
|
"ts-morph": "^28.0.0"
|
|
@@ -60,9 +55,9 @@
|
|
|
60
55
|
"@faker-js/faker": "^10.6.0",
|
|
61
56
|
"@sinclair/typebox": "^0.34.49",
|
|
62
57
|
"@types/bun": "latest",
|
|
63
|
-
"@typespec/http": "^1.
|
|
64
|
-
"@typespec/rest": "^0.
|
|
65
|
-
"@typespec/versioning": "^0.
|
|
58
|
+
"@typespec/http": "^1.16.0",
|
|
59
|
+
"@typespec/rest": "^0.86.0",
|
|
60
|
+
"@typespec/versioning": "^0.86.0",
|
|
66
61
|
"elysia": "^1.4.28",
|
|
67
62
|
"oxlint": "^1.82.0",
|
|
68
63
|
"oxlint-tsgolint": "^7.0.2001",
|