adorn-api 1.0.3 → 1.0.5
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 +766 -51
- package/dist/adapter/express/bootstrap.d.ts +24 -0
- package/dist/adapter/express/bootstrap.d.ts.map +1 -0
- package/dist/adapter/express/index.d.ts +41 -0
- package/dist/adapter/express/index.d.ts.map +1 -0
- package/dist/adapter/express/merge.d.ts +28 -0
- package/dist/adapter/express/merge.d.ts.map +1 -0
- package/dist/cli.cjs +1571 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1552 -2
- package/dist/cli.js.map +1 -1
- package/dist/compiler/analyze/scanControllers.d.ts +35 -0
- package/dist/compiler/analyze/scanControllers.d.ts.map +1 -0
- package/dist/compiler/cache/isStale.d.ts +20 -0
- package/dist/compiler/cache/isStale.d.ts.map +1 -0
- package/dist/compiler/cache/loadArtifacts.d.ts +113 -0
- package/dist/compiler/cache/loadArtifacts.d.ts.map +1 -0
- package/dist/compiler/cache/schema.d.ts +18 -0
- package/dist/compiler/cache/schema.d.ts.map +1 -0
- package/dist/compiler/cache/writeCache.d.ts +8 -0
- package/dist/compiler/cache/writeCache.d.ts.map +1 -0
- package/dist/compiler/manifest/emit.d.ts +7 -0
- package/dist/compiler/manifest/emit.d.ts.map +1 -0
- package/dist/compiler/manifest/format.d.ts +76 -0
- package/dist/compiler/manifest/format.d.ts.map +1 -0
- package/dist/compiler/runner/createProgram.d.ts +8 -0
- package/dist/compiler/runner/createProgram.d.ts.map +1 -0
- package/dist/compiler/schema/extractAnnotations.d.ts +10 -0
- package/dist/compiler/schema/extractAnnotations.d.ts.map +1 -0
- package/dist/compiler/schema/openapi.d.ts +19 -0
- package/dist/compiler/schema/openapi.d.ts.map +1 -0
- package/dist/compiler/schema/typeToJsonSchema.d.ts +49 -0
- package/dist/compiler/schema/typeToJsonSchema.d.ts.map +1 -0
- package/dist/compiler/validation/emitPrecompiledValidators.d.ts +46 -0
- package/dist/compiler/validation/emitPrecompiledValidators.d.ts.map +1 -0
- package/dist/decorators/Auth.d.ts +5 -0
- package/dist/decorators/Auth.d.ts.map +1 -0
- package/dist/decorators/Controller.d.ts +2 -0
- package/dist/decorators/Controller.d.ts.map +1 -0
- package/dist/decorators/Public.d.ts +2 -0
- package/dist/decorators/Public.d.ts.map +1 -0
- package/dist/decorators/Use.d.ts +5 -0
- package/dist/decorators/Use.d.ts.map +1 -0
- package/dist/decorators/index.d.ts +5 -6
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/methods.d.ts +5 -145
- package/dist/decorators/methods.d.ts.map +1 -1
- package/dist/express.cjs +775 -0
- package/dist/express.cjs.map +1 -0
- package/dist/express.d.ts +6 -1
- package/dist/express.d.ts.map +1 -1
- package/dist/express.js +738 -1
- package/dist/express.js.map +1 -1
- package/dist/http.d.ts +29 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/index.cjs +573 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +12 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +490 -26
- package/dist/index.js.map +1 -1
- package/dist/metal/index.cjs +219 -0
- package/dist/metal/index.cjs.map +1 -0
- package/dist/metal/index.d.ts +6 -0
- package/dist/metal/index.d.ts.map +1 -0
- package/dist/metal/index.js +188 -0
- package/dist/metal/index.js.map +1 -0
- package/dist/metal/readMetalBag.d.ts +33 -0
- package/dist/metal/readMetalBag.d.ts.map +1 -0
- package/dist/metal/registerMetalEntities.d.ts +6 -0
- package/dist/metal/registerMetalEntities.d.ts.map +1 -0
- package/dist/metal/schemaFromEntity.d.ts +11 -0
- package/dist/metal/schemaFromEntity.d.ts.map +1 -0
- package/dist/metal/symbolMetadata.d.ts +2 -0
- package/dist/metal/symbolMetadata.d.ts.map +1 -0
- package/dist/runtime/auth/runtime.d.ts +34 -0
- package/dist/runtime/auth/runtime.d.ts.map +1 -0
- package/dist/runtime/metadata/bucket.d.ts +3 -0
- package/dist/runtime/metadata/bucket.d.ts.map +1 -0
- package/dist/runtime/metadata/key.d.ts +2 -0
- package/dist/runtime/metadata/key.d.ts.map +1 -0
- package/dist/runtime/metadata/read.d.ts +3 -0
- package/dist/runtime/metadata/read.d.ts.map +1 -0
- package/dist/runtime/metadata/types.d.ts +21 -0
- package/dist/runtime/metadata/types.d.ts.map +1 -0
- package/dist/runtime/polyfill.d.ts +2 -0
- package/dist/runtime/polyfill.d.ts.map +1 -0
- package/dist/runtime/upload.d.ts +7 -0
- package/dist/runtime/upload.d.ts.map +1 -0
- package/dist/runtime/validation/ajv.d.ts +20 -0
- package/dist/runtime/validation/ajv.d.ts.map +1 -0
- package/dist/runtime/validation/index.d.ts +2 -0
- package/dist/runtime/validation/index.d.ts.map +1 -0
- package/dist/schema/decorators.d.ts +37 -0
- package/dist/schema/decorators.d.ts.map +1 -0
- package/dist/schema/index.cjs +214 -0
- package/dist/schema/index.cjs.map +1 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +163 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/scripts/adorn-example.cjs +148 -0
- package/dist/scripts/adorn-example.cjs.map +1 -0
- package/dist/utils/operationId.d.ts +2 -0
- package/dist/utils/operationId.d.ts.map +1 -0
- package/dist/utils/path.d.ts +2 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/package.json +92 -57
- package/dist/adapters/express/createApp.d.ts +0 -158
- package/dist/adapters/express/createApp.d.ts.map +0 -1
- package/dist/adapters/express/createApp.js +0 -141
- package/dist/adapters/express/createApp.js.map +0 -1
- package/dist/adapters/express/index.d.ts +0 -7
- package/dist/adapters/express/index.d.ts.map +0 -1
- package/dist/adapters/express/index.js +0 -7
- package/dist/adapters/express/index.js.map +0 -1
- package/dist/adapters/express/middleware/errorHandler.d.ts +0 -194
- package/dist/adapters/express/middleware/errorHandler.d.ts.map +0 -1
- package/dist/adapters/express/middleware/errorHandler.js +0 -167
- package/dist/adapters/express/middleware/errorHandler.js.map +0 -1
- package/dist/adapters/express/middleware/requestContext.d.ts +0 -2
- package/dist/adapters/express/middleware/requestContext.d.ts.map +0 -1
- package/dist/adapters/express/middleware/requestContext.js +0 -3
- package/dist/adapters/express/middleware/requestContext.js.map +0 -1
- package/dist/adapters/express/router.d.ts +0 -10
- package/dist/adapters/express/router.d.ts.map +0 -1
- package/dist/adapters/express/router.js +0 -105
- package/dist/adapters/express/router.js.map +0 -1
- package/dist/adapters/express/swagger/index.d.ts +0 -2
- package/dist/adapters/express/swagger/index.d.ts.map +0 -1
- package/dist/adapters/express/swagger/index.js +0 -2
- package/dist/adapters/express/swagger/index.js.map +0 -1
- package/dist/adapters/express/swagger/serve.d.ts +0 -12
- package/dist/adapters/express/swagger/serve.d.ts.map +0 -1
- package/dist/adapters/express/swagger/serve.js +0 -72
- package/dist/adapters/express/swagger/serve.js.map +0 -1
- package/dist/adapters/express/transport/request.d.ts +0 -4
- package/dist/adapters/express/transport/request.d.ts.map +0 -1
- package/dist/adapters/express/transport/request.js +0 -12
- package/dist/adapters/express/transport/request.js.map +0 -1
- package/dist/adapters/express/transport/response.d.ts +0 -5
- package/dist/adapters/express/transport/response.d.ts.map +0 -1
- package/dist/adapters/express/transport/response.js +0 -36
- package/dist/adapters/express/transport/response.js.map +0 -1
- package/dist/cli/commands/dev.d.ts +0 -2
- package/dist/cli/commands/dev.d.ts.map +0 -1
- package/dist/cli/commands/dev.js +0 -3
- package/dist/cli/commands/dev.js.map +0 -1
- package/dist/cli/commands/gen.d.ts +0 -2
- package/dist/cli/commands/gen.d.ts.map +0 -1
- package/dist/cli/commands/gen.js +0 -3
- package/dist/cli/commands/gen.js.map +0 -1
- package/dist/cli/main.d.ts +0 -2
- package/dist/cli/main.d.ts.map +0 -1
- package/dist/cli/main.js +0 -3
- package/dist/cli/main.js.map +0 -1
- package/dist/compiler/config/defaults.d.ts +0 -2
- package/dist/compiler/config/defaults.d.ts.map +0 -1
- package/dist/compiler/config/defaults.js +0 -3
- package/dist/compiler/config/defaults.js.map +0 -1
- package/dist/compiler/config/loadConfig.d.ts +0 -2
- package/dist/compiler/config/loadConfig.d.ts.map +0 -1
- package/dist/compiler/config/loadConfig.js +0 -3
- package/dist/compiler/config/loadConfig.js.map +0 -1
- package/dist/compiler/diagnostics/errors.d.ts +0 -2
- package/dist/compiler/diagnostics/errors.d.ts.map +0 -1
- package/dist/compiler/diagnostics/errors.js +0 -3
- package/dist/compiler/diagnostics/errors.js.map +0 -1
- package/dist/compiler/emit/openapi.d.ts +0 -2
- package/dist/compiler/emit/openapi.d.ts.map +0 -1
- package/dist/compiler/emit/openapi.js +0 -3
- package/dist/compiler/emit/openapi.js.map +0 -1
- package/dist/compiler/emit/routes.d.ts +0 -2
- package/dist/compiler/emit/routes.d.ts.map +0 -1
- package/dist/compiler/emit/routes.js +0 -3
- package/dist/compiler/emit/routes.js.map +0 -1
- package/dist/compiler/program/loadTsProgram.d.ts +0 -2
- package/dist/compiler/program/loadTsProgram.d.ts.map +0 -1
- package/dist/compiler/program/loadTsProgram.js +0 -3
- package/dist/compiler/program/loadTsProgram.js.map +0 -1
- package/dist/compiler/scan/actions.d.ts +0 -2
- package/dist/compiler/scan/actions.d.ts.map +0 -1
- package/dist/compiler/scan/actions.js +0 -3
- package/dist/compiler/scan/actions.js.map +0 -1
- package/dist/compiler/scan/controllers.d.ts +0 -2
- package/dist/compiler/scan/controllers.d.ts.map +0 -1
- package/dist/compiler/scan/controllers.js +0 -3
- package/dist/compiler/scan/controllers.js.map +0 -1
- package/dist/compiler/scan/types.d.ts +0 -2
- package/dist/compiler/scan/types.d.ts.map +0 -1
- package/dist/compiler/scan/types.js +0 -3
- package/dist/compiler/scan/types.js.map +0 -1
- package/dist/contracts/context.d.ts +0 -10
- package/dist/contracts/context.d.ts.map +0 -1
- package/dist/contracts/context.js +0 -2
- package/dist/contracts/context.js.map +0 -1
- package/dist/contracts/errors.d.ts +0 -22
- package/dist/contracts/errors.d.ts.map +0 -1
- package/dist/contracts/errors.js +0 -2
- package/dist/contracts/errors.js.map +0 -1
- package/dist/contracts/http.d.ts +0 -2
- package/dist/contracts/http.d.ts.map +0 -1
- package/dist/contracts/http.js +0 -3
- package/dist/contracts/http.js.map +0 -1
- package/dist/contracts/middleware.d.ts +0 -2
- package/dist/contracts/middleware.d.ts.map +0 -1
- package/dist/contracts/middleware.js +0 -3
- package/dist/contracts/middleware.js.map +0 -1
- package/dist/contracts/openapi-v3.d.ts +0 -538
- package/dist/contracts/openapi-v3.d.ts.map +0 -1
- package/dist/contracts/openapi-v3.js +0 -2
- package/dist/contracts/openapi-v3.js.map +0 -1
- package/dist/contracts/openapi.d.ts +0 -2
- package/dist/contracts/openapi.d.ts.map +0 -1
- package/dist/contracts/openapi.js +0 -2
- package/dist/contracts/openapi.js.map +0 -1
- package/dist/contracts/reply.d.ts +0 -119
- package/dist/contracts/reply.d.ts.map +0 -1
- package/dist/contracts/reply.js +0 -43
- package/dist/contracts/reply.js.map +0 -1
- package/dist/contracts/response-types.d.ts +0 -40
- package/dist/contracts/response-types.d.ts.map +0 -1
- package/dist/contracts/response-types.js +0 -2
- package/dist/contracts/response-types.js.map +0 -1
- package/dist/contracts/responses.d.ts +0 -98
- package/dist/contracts/responses.d.ts.map +0 -1
- package/dist/contracts/responses.js +0 -2
- package/dist/contracts/responses.js.map +0 -1
- package/dist/contracts/route-options.d.ts +0 -155
- package/dist/contracts/route-options.d.ts.map +0 -1
- package/dist/contracts/route-options.js +0 -2
- package/dist/contracts/route-options.js.map +0 -1
- package/dist/contracts/route-typing.d.ts +0 -25
- package/dist/contracts/route-typing.d.ts.map +0 -1
- package/dist/contracts/route-typing.js +0 -2
- package/dist/contracts/route-typing.js.map +0 -1
- package/dist/contracts/validator.d.ts +0 -146
- package/dist/contracts/validator.d.ts.map +0 -1
- package/dist/contracts/validator.js +0 -2
- package/dist/contracts/validator.js.map +0 -1
- package/dist/core/binding/binder.d.ts +0 -74
- package/dist/core/binding/binder.d.ts.map +0 -1
- package/dist/core/binding/binder.js +0 -161
- package/dist/core/binding/binder.js.map +0 -1
- package/dist/core/binding/coerce/arrays.d.ts +0 -7
- package/dist/core/binding/coerce/arrays.d.ts.map +0 -1
- package/dist/core/binding/coerce/arrays.js +0 -28
- package/dist/core/binding/coerce/arrays.js.map +0 -1
- package/dist/core/binding/coerce/csv.d.ts +0 -2
- package/dist/core/binding/coerce/csv.d.ts.map +0 -1
- package/dist/core/binding/coerce/csv.js +0 -7
- package/dist/core/binding/coerce/csv.js.map +0 -1
- package/dist/core/binding/coerce/objects.d.ts +0 -2
- package/dist/core/binding/coerce/objects.d.ts.map +0 -1
- package/dist/core/binding/coerce/objects.js +0 -3
- package/dist/core/binding/coerce/objects.js.map +0 -1
- package/dist/core/binding/coerce/primitives.d.ts +0 -70
- package/dist/core/binding/coerce/primitives.d.ts.map +0 -1
- package/dist/core/binding/coerce/primitives.js +0 -88
- package/dist/core/binding/coerce/primitives.js.map +0 -1
- package/dist/core/binding/index.d.ts +0 -2
- package/dist/core/binding/index.d.ts.map +0 -1
- package/dist/core/binding/index.js +0 -2
- package/dist/core/binding/index.js.map +0 -1
- package/dist/core/binding/rules/inferFromHttpMethod.d.ts +0 -6
- package/dist/core/binding/rules/inferFromHttpMethod.d.ts.map +0 -1
- package/dist/core/binding/rules/inferFromHttpMethod.js +0 -11
- package/dist/core/binding/rules/inferFromHttpMethod.js.map +0 -1
- package/dist/core/binding/rules/inferFromPath.d.ts +0 -2
- package/dist/core/binding/rules/inferFromPath.d.ts.map +0 -1
- package/dist/core/binding/rules/inferFromPath.js +0 -9
- package/dist/core/binding/rules/inferFromPath.js.map +0 -1
- package/dist/core/binding/rules/wrappers.d.ts +0 -2
- package/dist/core/binding/rules/wrappers.d.ts.map +0 -1
- package/dist/core/binding/rules/wrappers.js +0 -3
- package/dist/core/binding/rules/wrappers.js.map +0 -1
- package/dist/core/errors/http-error.d.ts +0 -63
- package/dist/core/errors/http-error.d.ts.map +0 -1
- package/dist/core/errors/http-error.js +0 -71
- package/dist/core/errors/http-error.js.map +0 -1
- package/dist/core/errors/index.d.ts +0 -4
- package/dist/core/errors/index.d.ts.map +0 -1
- package/dist/core/errors/index.js +0 -4
- package/dist/core/errors/index.js.map +0 -1
- package/dist/core/errors/problem.d.ts +0 -3
- package/dist/core/errors/problem.d.ts.map +0 -1
- package/dist/core/errors/problem.js +0 -33
- package/dist/core/errors/problem.js.map +0 -1
- package/dist/core/errors/validation-error.d.ts +0 -73
- package/dist/core/errors/validation-error.d.ts.map +0 -1
- package/dist/core/errors/validation-error.js +0 -82
- package/dist/core/errors/validation-error.js.map +0 -1
- package/dist/core/openapi/buildOpenApi.d.ts +0 -79
- package/dist/core/openapi/buildOpenApi.d.ts.map +0 -1
- package/dist/core/openapi/buildOpenApi.js +0 -196
- package/dist/core/openapi/buildOpenApi.js.map +0 -1
- package/dist/core/openapi/index.d.ts +0 -2
- package/dist/core/openapi/index.d.ts.map +0 -1
- package/dist/core/openapi/index.js +0 -2
- package/dist/core/openapi/index.js.map +0 -1
- package/dist/core/openapi/schema/formats.d.ts +0 -2
- package/dist/core/openapi/schema/formats.d.ts.map +0 -1
- package/dist/core/openapi/schema/formats.js +0 -3
- package/dist/core/openapi/schema/formats.js.map +0 -1
- package/dist/core/openapi/schema/registry.d.ts +0 -9
- package/dist/core/openapi/schema/registry.d.ts.map +0 -1
- package/dist/core/openapi/schema/registry.js +0 -21
- package/dist/core/openapi/schema/registry.js.map +0 -1
- package/dist/core/openapi/schema/schemaModel.d.ts +0 -2
- package/dist/core/openapi/schema/schemaModel.d.ts.map +0 -1
- package/dist/core/openapi/schema/schemaModel.js +0 -3
- package/dist/core/openapi/schema/schemaModel.js.map +0 -1
- package/dist/core/openapi/schema/schemaRegistry.d.ts +0 -2
- package/dist/core/openapi/schema/schemaRegistry.d.ts.map +0 -1
- package/dist/core/openapi/schema/schemaRegistry.js +0 -3
- package/dist/core/openapi/schema/schemaRegistry.js.map +0 -1
- package/dist/core/openapi/schema/toOpenApi.d.ts +0 -4
- package/dist/core/openapi/schema/toOpenApi.d.ts.map +0 -1
- package/dist/core/openapi/schema/toOpenApi.js +0 -82
- package/dist/core/openapi/schema/toOpenApi.js.map +0 -1
- package/dist/core/pipeline/compose.d.ts +0 -2
- package/dist/core/pipeline/compose.d.ts.map +0 -1
- package/dist/core/pipeline/compose.js +0 -3
- package/dist/core/pipeline/compose.js.map +0 -1
- package/dist/core/pipeline/errorMap.d.ts +0 -2
- package/dist/core/pipeline/errorMap.d.ts.map +0 -1
- package/dist/core/pipeline/errorMap.js +0 -3
- package/dist/core/pipeline/errorMap.js.map +0 -1
- package/dist/core/pipeline/invoke.d.ts +0 -2
- package/dist/core/pipeline/invoke.d.ts.map +0 -1
- package/dist/core/pipeline/invoke.js +0 -3
- package/dist/core/pipeline/invoke.js.map +0 -1
- package/dist/core/pipeline/result.d.ts +0 -2
- package/dist/core/pipeline/result.d.ts.map +0 -1
- package/dist/core/pipeline/result.js +0 -3
- package/dist/core/pipeline/result.js.map +0 -1
- package/dist/core/registry/buildRegistry.d.ts +0 -3
- package/dist/core/registry/buildRegistry.d.ts.map +0 -1
- package/dist/core/registry/buildRegistry.js +0 -105
- package/dist/core/registry/buildRegistry.js.map +0 -1
- package/dist/core/registry/conflicts.d.ts +0 -6
- package/dist/core/registry/conflicts.d.ts.map +0 -1
- package/dist/core/registry/conflicts.js +0 -21
- package/dist/core/registry/conflicts.js.map +0 -1
- package/dist/core/registry/index.d.ts +0 -5
- package/dist/core/registry/index.d.ts.map +0 -1
- package/dist/core/registry/index.js +0 -5
- package/dist/core/registry/index.js.map +0 -1
- package/dist/core/registry/normalize.d.ts +0 -3
- package/dist/core/registry/normalize.d.ts.map +0 -1
- package/dist/core/registry/normalize.js +0 -24
- package/dist/core/registry/normalize.js.map +0 -1
- package/dist/core/registry/types.d.ts +0 -225
- package/dist/core/registry/types.d.ts.map +0 -1
- package/dist/core/registry/types.js +0 -2
- package/dist/core/registry/types.js.map +0 -1
- package/dist/core/reply/index.d.ts +0 -3
- package/dist/core/reply/index.d.ts.map +0 -1
- package/dist/core/reply/index.js +0 -3
- package/dist/core/reply/index.js.map +0 -1
- package/dist/core/reply/reply.d.ts +0 -102
- package/dist/core/reply/reply.d.ts.map +0 -1
- package/dist/core/reply/reply.js +0 -105
- package/dist/core/reply/reply.js.map +0 -1
- package/dist/core/reply/typed.d.ts +0 -161
- package/dist/core/reply/typed.d.ts.map +0 -1
- package/dist/core/reply/typed.js +0 -154
- package/dist/core/reply/typed.js.map +0 -1
- package/dist/core/responses/helpers.d.ts +0 -10
- package/dist/core/responses/helpers.d.ts.map +0 -1
- package/dist/core/responses/helpers.js +0 -8
- package/dist/core/responses/helpers.js.map +0 -1
- package/dist/core/responses/index.d.ts +0 -4
- package/dist/core/responses/index.d.ts.map +0 -1
- package/dist/core/responses/index.js +0 -4
- package/dist/core/responses/index.js.map +0 -1
- package/dist/core/responses/normalize.d.ts +0 -3
- package/dist/core/responses/normalize.d.ts.map +0 -1
- package/dist/core/responses/normalize.js +0 -33
- package/dist/core/responses/normalize.js.map +0 -1
- package/dist/core/responses/pickStatus.d.ts +0 -3
- package/dist/core/responses/pickStatus.d.ts.map +0 -1
- package/dist/core/responses/pickStatus.js +0 -27
- package/dist/core/responses/pickStatus.js.map +0 -1
- package/dist/core/route/defineRoute.d.ts +0 -74
- package/dist/core/route/defineRoute.d.ts.map +0 -1
- package/dist/core/route/defineRoute.js +0 -59
- package/dist/core/route/defineRoute.js.map +0 -1
- package/dist/core/route/index.d.ts +0 -2
- package/dist/core/route/index.d.ts.map +0 -1
- package/dist/core/route/index.js +0 -2
- package/dist/core/route/index.js.map +0 -1
- package/dist/core/serialization/json.d.ts +0 -2
- package/dist/core/serialization/json.d.ts.map +0 -1
- package/dist/core/serialization/json.js +0 -3
- package/dist/core/serialization/json.js.map +0 -1
- package/dist/core/typing/path-params.d.ts +0 -2
- package/dist/core/typing/path-params.d.ts.map +0 -1
- package/dist/core/typing/path-params.js +0 -2
- package/dist/core/typing/path-params.js.map +0 -1
- package/dist/decorators/binding.d.ts +0 -9
- package/dist/decorators/binding.d.ts.map +0 -1
- package/dist/decorators/binding.js +0 -18
- package/dist/decorators/binding.js.map +0 -1
- package/dist/decorators/controller.d.ts +0 -6
- package/dist/decorators/controller.d.ts.map +0 -1
- package/dist/decorators/controller.js +0 -26
- package/dist/decorators/controller.js.map +0 -1
- package/dist/decorators/db.d.ts +0 -2
- package/dist/decorators/db.d.ts.map +0 -1
- package/dist/decorators/db.js +0 -3
- package/dist/decorators/db.js.map +0 -1
- package/dist/decorators/docs.d.ts +0 -8
- package/dist/decorators/docs.d.ts.map +0 -1
- package/dist/decorators/docs.js +0 -46
- package/dist/decorators/docs.js.map +0 -1
- package/dist/decorators/index.js +0 -7
- package/dist/decorators/index.js.map +0 -1
- package/dist/decorators/methods.js +0 -170
- package/dist/decorators/methods.js.map +0 -1
- package/dist/decorators/middleware.d.ts +0 -2
- package/dist/decorators/middleware.d.ts.map +0 -1
- package/dist/decorators/middleware.js +0 -3
- package/dist/decorators/middleware.js.map +0 -1
- package/dist/decorators/responses.d.ts +0 -7
- package/dist/decorators/responses.d.ts.map +0 -1
- package/dist/decorators/responses.js +0 -44
- package/dist/decorators/responses.js.map +0 -1
- package/dist/decorators/security.d.ts +0 -8
- package/dist/decorators/security.d.ts.map +0 -1
- package/dist/decorators/security.js +0 -39
- package/dist/decorators/security.js.map +0 -1
- package/dist/integrations/metal-orm/index.d.ts +0 -2
- package/dist/integrations/metal-orm/index.d.ts.map +0 -1
- package/dist/integrations/metal-orm/index.js +0 -2
- package/dist/integrations/metal-orm/index.js.map +0 -1
- package/dist/integrations/metal-orm/pagination/executePaged.d.ts +0 -2
- package/dist/integrations/metal-orm/pagination/executePaged.d.ts.map +0 -1
- package/dist/integrations/metal-orm/pagination/executePaged.js +0 -3
- package/dist/integrations/metal-orm/pagination/executePaged.js.map +0 -1
- package/dist/integrations/metal-orm/pagination/page.d.ts +0 -2
- package/dist/integrations/metal-orm/pagination/page.d.ts.map +0 -1
- package/dist/integrations/metal-orm/pagination/page.js +0 -3
- package/dist/integrations/metal-orm/pagination/page.js.map +0 -1
- package/dist/integrations/metal-orm/query/filters.d.ts +0 -2
- package/dist/integrations/metal-orm/query/filters.d.ts.map +0 -1
- package/dist/integrations/metal-orm/query/filters.js +0 -3
- package/dist/integrations/metal-orm/query/filters.js.map +0 -1
- package/dist/integrations/metal-orm/query/search.d.ts +0 -2
- package/dist/integrations/metal-orm/query/search.d.ts.map +0 -1
- package/dist/integrations/metal-orm/query/search.js +0 -3
- package/dist/integrations/metal-orm/query/search.js.map +0 -1
- package/dist/integrations/metal-orm/query/sort.d.ts +0 -2
- package/dist/integrations/metal-orm/query/sort.d.ts.map +0 -1
- package/dist/integrations/metal-orm/query/sort.js +0 -3
- package/dist/integrations/metal-orm/query/sort.js.map +0 -1
- package/dist/integrations/metal-orm/save-graph/helpers.d.ts +0 -2
- package/dist/integrations/metal-orm/save-graph/helpers.d.ts.map +0 -1
- package/dist/integrations/metal-orm/save-graph/helpers.js +0 -3
- package/dist/integrations/metal-orm/save-graph/helpers.js.map +0 -1
- package/dist/integrations/metal-orm/save-graph/types.d.ts +0 -2
- package/dist/integrations/metal-orm/save-graph/types.d.ts.map +0 -1
- package/dist/integrations/metal-orm/save-graph/types.js +0 -3
- package/dist/integrations/metal-orm/save-graph/types.js.map +0 -1
- package/dist/integrations/metal-orm/schema/column-map.d.ts +0 -96
- package/dist/integrations/metal-orm/schema/column-map.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/column-map.js +0 -207
- package/dist/integrations/metal-orm/schema/column-map.js.map +0 -1
- package/dist/integrations/metal-orm/schema/ddl.d.ts +0 -2
- package/dist/integrations/metal-orm/schema/ddl.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/ddl.js +0 -3
- package/dist/integrations/metal-orm/schema/ddl.js.map +0 -1
- package/dist/integrations/metal-orm/schema/dto.d.ts +0 -7
- package/dist/integrations/metal-orm/schema/dto.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/dto.js +0 -34
- package/dist/integrations/metal-orm/schema/dto.js.map +0 -1
- package/dist/integrations/metal-orm/schema/entity.d.ts +0 -99
- package/dist/integrations/metal-orm/schema/entity.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/entity.js +0 -99
- package/dist/integrations/metal-orm/schema/entity.js.map +0 -1
- package/dist/integrations/metal-orm/schema/filters.d.ts +0 -11
- package/dist/integrations/metal-orm/schema/filters.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/filters.js +0 -21
- package/dist/integrations/metal-orm/schema/filters.js.map +0 -1
- package/dist/integrations/metal-orm/schema/index.d.ts +0 -5
- package/dist/integrations/metal-orm/schema/index.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/index.js +0 -5
- package/dist/integrations/metal-orm/schema/index.js.map +0 -1
- package/dist/integrations/metal-orm/schema/openapi/entityToSchema.d.ts +0 -2
- package/dist/integrations/metal-orm/schema/openapi/entityToSchema.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/openapi/entityToSchema.js +0 -3
- package/dist/integrations/metal-orm/schema/openapi/entityToSchema.js.map +0 -1
- package/dist/integrations/metal-orm/schema/openapi/tableDefToSchema.d.ts +0 -2
- package/dist/integrations/metal-orm/schema/openapi/tableDefToSchema.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/openapi/tableDefToSchema.js +0 -3
- package/dist/integrations/metal-orm/schema/openapi/tableDefToSchema.js.map +0 -1
- package/dist/integrations/metal-orm/schema/sqlite.d.ts +0 -2
- package/dist/integrations/metal-orm/schema/sqlite.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/sqlite.js +0 -3
- package/dist/integrations/metal-orm/schema/sqlite.js.map +0 -1
- package/dist/integrations/metal-orm/schema/tabledef.d.ts +0 -4
- package/dist/integrations/metal-orm/schema/tabledef.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/tabledef.js +0 -10
- package/dist/integrations/metal-orm/schema/tabledef.js.map +0 -1
- package/dist/integrations/metal-orm/schema/types.d.ts +0 -7
- package/dist/integrations/metal-orm/schema/types.d.ts.map +0 -1
- package/dist/integrations/metal-orm/schema/types.js +0 -2
- package/dist/integrations/metal-orm/schema/types.js.map +0 -1
- package/dist/integrations/metal-orm/serialization/entitySerializer.d.ts +0 -2
- package/dist/integrations/metal-orm/serialization/entitySerializer.d.ts.map +0 -1
- package/dist/integrations/metal-orm/serialization/entitySerializer.js +0 -3
- package/dist/integrations/metal-orm/serialization/entitySerializer.js.map +0 -1
- package/dist/integrations/metal-orm/serialization/relationPolicy.d.ts +0 -2
- package/dist/integrations/metal-orm/serialization/relationPolicy.d.ts.map +0 -1
- package/dist/integrations/metal-orm/serialization/relationPolicy.js +0 -3
- package/dist/integrations/metal-orm/serialization/relationPolicy.js.map +0 -1
- package/dist/integrations/metal-orm/session/context.d.ts +0 -2
- package/dist/integrations/metal-orm/session/context.d.ts.map +0 -1
- package/dist/integrations/metal-orm/session/context.js +0 -3
- package/dist/integrations/metal-orm/session/context.js.map +0 -1
- package/dist/integrations/metal-orm/session/middleware.d.ts +0 -2
- package/dist/integrations/metal-orm/session/middleware.d.ts.map +0 -1
- package/dist/integrations/metal-orm/session/middleware.js +0 -3
- package/dist/integrations/metal-orm/session/middleware.js.map +0 -1
- package/dist/integrations/metal-orm/session/transaction.d.ts +0 -2
- package/dist/integrations/metal-orm/session/transaction.d.ts.map +0 -1
- package/dist/integrations/metal-orm/session/transaction.js +0 -3
- package/dist/integrations/metal-orm/session/transaction.js.map +0 -1
- package/dist/integrations/metal-orm/testing/setupSchema.d.ts +0 -2
- package/dist/integrations/metal-orm/testing/setupSchema.d.ts.map +0 -1
- package/dist/integrations/metal-orm/testing/setupSchema.js +0 -3
- package/dist/integrations/metal-orm/testing/setupSchema.js.map +0 -1
- package/dist/integrations/metal-orm/testing/sqliteMemory.d.ts +0 -2
- package/dist/integrations/metal-orm/testing/sqliteMemory.d.ts.map +0 -1
- package/dist/integrations/metal-orm/testing/sqliteMemory.js +0 -3
- package/dist/integrations/metal-orm/testing/sqliteMemory.js.map +0 -1
- package/dist/metadata/bag.d.ts +0 -18
- package/dist/metadata/bag.d.ts.map +0 -1
- package/dist/metadata/bag.js +0 -39
- package/dist/metadata/bag.js.map +0 -1
- package/dist/metadata/index.d.ts +0 -4
- package/dist/metadata/index.d.ts.map +0 -1
- package/dist/metadata/index.js +0 -4
- package/dist/metadata/index.js.map +0 -1
- package/dist/metadata/keys.d.ts +0 -254
- package/dist/metadata/keys.d.ts.map +0 -1
- package/dist/metadata/keys.js +0 -23
- package/dist/metadata/keys.js.map +0 -1
- package/dist/metadata/merge.d.ts +0 -9
- package/dist/metadata/merge.d.ts.map +0 -1
- package/dist/metadata/merge.js +0 -30
- package/dist/metadata/merge.js.map +0 -1
- package/dist/metal-orm.d.ts +0 -2
- package/dist/metal-orm.d.ts.map +0 -1
- package/dist/metal-orm.js +0 -2
- package/dist/metal-orm.js.map +0 -1
- package/dist/validation/native/index.d.ts +0 -3
- package/dist/validation/native/index.d.ts.map +0 -1
- package/dist/validation/native/index.js +0 -3
- package/dist/validation/native/index.js.map +0 -1
- package/dist/validation/native/ir.d.ts +0 -38
- package/dist/validation/native/ir.d.ts.map +0 -1
- package/dist/validation/native/ir.js +0 -2
- package/dist/validation/native/ir.js.map +0 -1
- package/dist/validation/native/schema.d.ts +0 -63
- package/dist/validation/native/schema.d.ts.map +0 -1
- package/dist/validation/native/schema.js +0 -271
- package/dist/validation/native/schema.js.map +0 -1
- package/dist/validation/native/validator.d.ts +0 -21
- package/dist/validation/native/validator.d.ts.map +0 -1
- package/dist/validation/native/validator.js +0 -48
- package/dist/validation/native/validator.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,54 +1,769 @@
|
|
|
1
|
-
# Adorn
|
|
2
|
-
Adorn API turns TypeScript classes into HTTP controllers with Stage-3 decorators, then wires Express routes, validation, and OpenAPI docs from the same metadata. It stays small and focused while still supporting MetalORM-backed persistence when you want it.
|
|
1
|
+
# Adorn-API
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Stage-3 decorator-first OpenAPI + routing toolkit for TypeScript.
|
|
4
|
+
|
|
5
|
+
Build type-safe REST APIs with decorators. Get automatic OpenAPI 3.1 documentation, runtime validation, and authentication out of the box.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install adorn-api
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Create a controller:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { Controller, Get, Post } from "adorn-api";
|
|
17
|
+
|
|
18
|
+
interface User {
|
|
19
|
+
id: number;
|
|
20
|
+
name: string;
|
|
21
|
+
email: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const users: User[] = [
|
|
25
|
+
{ id: 1, name: "Alice", email: "alice@example.com" },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
@Controller("/users")
|
|
29
|
+
export class UserController {
|
|
30
|
+
@Get("/")
|
|
31
|
+
async getUsers(): Promise<User[]> {
|
|
32
|
+
return users;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@Get("/:id")
|
|
36
|
+
async getUser(id: number): Promise<User | null> {
|
|
37
|
+
return users.find(u => u.id === id) || null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Post("/")
|
|
41
|
+
async createUser(body: { name: string; email: string }): Promise<User> {
|
|
42
|
+
const user: User = {
|
|
43
|
+
id: users.length + 1,
|
|
44
|
+
name: body.name,
|
|
45
|
+
email: body.email,
|
|
46
|
+
};
|
|
47
|
+
users.push(user);
|
|
48
|
+
return user;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Start your server:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { bootstrap } from "adorn-api/express";
|
|
57
|
+
import { UserController } from "./controller.js";
|
|
58
|
+
|
|
59
|
+
await bootstrap({ controllers: [UserController] });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Visit http://localhost:3000/docs to see your auto-generated Swagger UI.
|
|
9
63
|
|
|
10
64
|
## Features
|
|
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
|
-
|
|
65
|
+
|
|
66
|
+
- **Decorator-based routing** - `@Controller`, `@Get`, `@Post`, `@Put`, `@Patch`, `@Delete`
|
|
67
|
+
- **Automatic OpenAPI 3.1** - Generate specs from TypeScript decorators
|
|
68
|
+
- **Runtime validation** - AJV-powered request validation
|
|
69
|
+
- **Authentication** - `@Auth()` and `@Public()` decorators with custom schemes
|
|
70
|
+
- **Middleware** - Global, controller-level, and route-level middleware
|
|
71
|
+
- **Type-safe** - Full TypeScript inference throughout
|
|
72
|
+
- **Incremental builds** - Smart caching with `--if-stale` flag
|
|
73
|
+
- **Precompiled validators** - Optimized validation for production
|
|
74
|
+
- **Swagger UI** - Built-in documentation at `/docs`
|
|
75
|
+
- **Metal ORM integration** - Auto-generate schemas from entities
|
|
76
|
+
|
|
77
|
+
## Installation
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npm install adorn-api
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Peer dependency:**
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install express
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Requirements:**
|
|
90
|
+
- Node.js 18+
|
|
91
|
+
- TypeScript 5.0+
|
|
92
|
+
|
|
93
|
+
## Core Concepts
|
|
94
|
+
|
|
95
|
+
### Controllers
|
|
96
|
+
|
|
97
|
+
A controller is a class decorated with `@Controller(path)` that groups related endpoints:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
@Controller("/api/users")
|
|
101
|
+
export class UsersController {
|
|
102
|
+
@Get("/")
|
|
103
|
+
async getUsers() { /* ... */ }
|
|
104
|
+
|
|
105
|
+
@Get("/:id")
|
|
106
|
+
async getUser(id: number) { /* ... */ }
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### HTTP Methods
|
|
111
|
+
|
|
112
|
+
All standard HTTP methods are supported:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
@Get("/") // GET
|
|
116
|
+
@Post("/") // POST
|
|
117
|
+
@Put("/:id") // PUT
|
|
118
|
+
@Patch("/:id") // PATCH
|
|
119
|
+
@Delete("/:id") // DELETE
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Parameters
|
|
123
|
+
|
|
124
|
+
Adorn-API automatically extracts parameters from your handler signatures:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
@Controller("/products")
|
|
128
|
+
export class ProductsController {
|
|
129
|
+
@Get("/:id")
|
|
130
|
+
async getProduct(
|
|
131
|
+
id: number, // Path parameter
|
|
132
|
+
query?: { category?: string } // Query parameter
|
|
133
|
+
) { /* ... */ }
|
|
134
|
+
|
|
135
|
+
@Post("/")
|
|
136
|
+
async createProduct(
|
|
137
|
+
body: { name: string }, // Request body
|
|
138
|
+
headers: { "X-Request-Id": string } // Headers
|
|
139
|
+
) { /* ... */ }
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Examples
|
|
144
|
+
|
|
145
|
+
### Basic Example
|
|
146
|
+
|
|
147
|
+
Minimal API with CRUD operations. See: `examples/basic/`
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { Controller, Get, Post, Put, Delete } from "adorn-api";
|
|
151
|
+
|
|
152
|
+
@Controller("/users")
|
|
153
|
+
export class UserController {
|
|
154
|
+
@Get("/")
|
|
155
|
+
async getUsers() { return [{ id: 1, name: "Alice" }]; }
|
|
156
|
+
|
|
157
|
+
@Get("/:id")
|
|
158
|
+
async getUser(id: number) { /* ... */ }
|
|
159
|
+
|
|
160
|
+
@Post("/")
|
|
161
|
+
async createUser(body: { name: string }) { /* ... */ }
|
|
162
|
+
|
|
163
|
+
@Put("/:id")
|
|
164
|
+
async updateUser(id: number, body: { name?: string }) { /* ... */ }
|
|
165
|
+
|
|
166
|
+
@Delete("/:id")
|
|
167
|
+
async deleteUser(id: number) { return { success: true }; }
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Authentication Example
|
|
172
|
+
|
|
173
|
+
Bearer token auth with scopes and public endpoints. See: `examples/simple-auth/`
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { Controller, Get, Post } from "adorn-api";
|
|
177
|
+
import { Auth, Public } from "adorn-api/decorators";
|
|
178
|
+
|
|
179
|
+
@Controller("/api")
|
|
180
|
+
export class ApiController {
|
|
181
|
+
@Get("/public")
|
|
182
|
+
@Public()
|
|
183
|
+
async publicEndpoint() {
|
|
184
|
+
return { message: "No auth required" };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@Get("/profile")
|
|
188
|
+
@Auth("BearerAuth")
|
|
189
|
+
async getProfile(req: any) {
|
|
190
|
+
return { user: req.auth };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@Get("/data")
|
|
194
|
+
@Auth("BearerAuth", { scopes: ["read"] })
|
|
195
|
+
async getData() {
|
|
196
|
+
return { data: ["item1", "item2"] };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@Post("/items")
|
|
200
|
+
@Auth("BearerAuth", { scopes: ["write"] })
|
|
201
|
+
async createItem(req: any) {
|
|
202
|
+
return { id: 1, name: req.body.name };
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Configure the auth scheme when creating your router:
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
const bearerRuntime = {
|
|
211
|
+
name: "BearerAuth",
|
|
212
|
+
async authenticate(req) {
|
|
213
|
+
const auth = req.headers.authorization;
|
|
214
|
+
if (!auth?.startsWith("Bearer ")) return null;
|
|
215
|
+
if (auth !== "Bearer valid-token") return null;
|
|
216
|
+
return { principal: { userId: 1 }, scopes: ["read", "write"] };
|
|
217
|
+
},
|
|
218
|
+
challenge(res) {
|
|
219
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
220
|
+
},
|
|
221
|
+
authorize(auth, requiredScopes) {
|
|
222
|
+
return requiredScopes.every(s => auth.scopes?.includes(s));
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
await createExpressRouter({
|
|
227
|
+
controllers: [ApiController],
|
|
228
|
+
auth: { schemes: { BearerAuth: bearerRuntime } },
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### E-commerce Example
|
|
233
|
+
|
|
234
|
+
Full CRUD with search and status management. See: `examples/ecommerce/`
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
@Controller("/products")
|
|
238
|
+
export class ProductsController {
|
|
239
|
+
@Get("/")
|
|
240
|
+
async getProducts() {
|
|
241
|
+
return products.filter(p => p.status === "published");
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@Get("/:id")
|
|
245
|
+
async getProduct(id: number) { /* ... */ }
|
|
246
|
+
|
|
247
|
+
@Post("/")
|
|
248
|
+
async createProduct(body: { name: string; price: number }) { /* ... */ }
|
|
249
|
+
|
|
250
|
+
@Put("/:id")
|
|
251
|
+
async updateProduct(id: number, body: Partial<{ name: string; price: number }>) { /* ... */ }
|
|
252
|
+
|
|
253
|
+
@Delete("/:id")
|
|
254
|
+
async deleteProduct(id: number) { return { success: true }; }
|
|
255
|
+
|
|
256
|
+
@Post("/:id/publish")
|
|
257
|
+
async publishProduct(id: number) { /* ... */ }
|
|
258
|
+
|
|
259
|
+
@Post("/search/advanced")
|
|
260
|
+
async advancedSearch(body: {
|
|
261
|
+
query?: string;
|
|
262
|
+
minPrice?: number;
|
|
263
|
+
maxPrice?: number;
|
|
264
|
+
inStockOnly?: boolean;
|
|
265
|
+
}) { /* ... */ }
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Blog Platform with Metal ORM
|
|
270
|
+
|
|
271
|
+
Database-driven API using Metal ORM entities. See: `examples/blog-platform-metal-orm/`
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
import { Controller, Get, Post, Put, Delete } from "adorn-api";
|
|
275
|
+
import { Post as PostEntity } from "../entities/index.js";
|
|
276
|
+
import { getSession, selectFromEntity, eq } from "metal-orm";
|
|
277
|
+
|
|
278
|
+
@Controller("/posts")
|
|
279
|
+
export class PostsController {
|
|
280
|
+
@Get("/")
|
|
281
|
+
async getPosts(query?: { authorId?: number; status?: string }) {
|
|
282
|
+
const session = getSession();
|
|
283
|
+
let qb = selectFromEntity(PostEntity);
|
|
284
|
+
if (query?.authorId) qb = qb.where(eq(PostEntity.authorId, query.authorId));
|
|
285
|
+
if (query?.status) qb = qb.where(eq(PostEntity.status, query.status));
|
|
286
|
+
return qb.execute(session);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
@Get("/:id")
|
|
290
|
+
async getPost(id: number) { /* ... */ }
|
|
291
|
+
|
|
292
|
+
@Post("/")
|
|
293
|
+
async createPost(body: Pick<PostEntity, "title" | "content" | "authorId">) {
|
|
294
|
+
const session = getSession();
|
|
295
|
+
const post = new PostEntity();
|
|
296
|
+
Object.assign(post, body);
|
|
297
|
+
await session.persist(post);
|
|
298
|
+
await session.flush();
|
|
299
|
+
return post;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
@Put("/:id")
|
|
303
|
+
async updatePost(id: number, body: Partial<PostEntity>) { /* ... */ }
|
|
304
|
+
|
|
305
|
+
@Delete("/:id")
|
|
306
|
+
async deletePost(id: number) { return { success: true }; }
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Task Manager Example
|
|
311
|
+
|
|
312
|
+
Multi-controller architecture with SQL database. See: `examples/task-manager/`
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
@Controller("/tasks")
|
|
316
|
+
export class TasksController {
|
|
317
|
+
@Get("/")
|
|
318
|
+
async getTasks(query?: { status?: string; priority?: string; search?: string }) {
|
|
319
|
+
let sql = "SELECT * FROM tasks WHERE 1=1";
|
|
320
|
+
if (query?.status) sql += " AND status = ?";
|
|
321
|
+
return allQuery(sql, params);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
@Get("/:id")
|
|
325
|
+
async getTask(id: number) { /* returns task with tags */ }
|
|
326
|
+
|
|
327
|
+
@Post("/")
|
|
328
|
+
async createTask(body: { title: string; priority?: "low" | "medium" | "high" }) {
|
|
329
|
+
const now = new Date().toISOString();
|
|
330
|
+
return runQuery(sql, [...values, now, now]);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
@Put("/:id")
|
|
334
|
+
async updateTask(id: number, body: Partial<Task>) { /* ... */ }
|
|
335
|
+
|
|
336
|
+
@Delete("/:id")
|
|
337
|
+
async deleteTask(id: number) { return { success: result.changes > 0 }; }
|
|
338
|
+
|
|
339
|
+
@Post("/:id/tags")
|
|
340
|
+
async addTagToTask(id: number, body: { tag_id: number }) { /* ... */ }
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
@Controller("/tags")
|
|
344
|
+
export class TagsController {
|
|
345
|
+
@Get("/")
|
|
346
|
+
async getTags() { return allQuery("SELECT * FROM tags"); }
|
|
347
|
+
|
|
348
|
+
@Post("/")
|
|
349
|
+
async createTag(body: { name: string; color?: string }) { /* ... */ }
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
@Controller("/stats")
|
|
353
|
+
export class StatsController {
|
|
354
|
+
@Get("/")
|
|
355
|
+
async getStats() {
|
|
356
|
+
return {
|
|
357
|
+
total: count,
|
|
358
|
+
byStatus: statusMap,
|
|
359
|
+
byPriority: priorityMap,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Authentication
|
|
366
|
+
|
|
367
|
+
### @Auth Decorator
|
|
368
|
+
|
|
369
|
+
Protect endpoints with authentication requirements:
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
@Controller("/api")
|
|
373
|
+
export class ApiController {
|
|
374
|
+
@Get("/secure")
|
|
375
|
+
@Auth("BearerAuth")
|
|
376
|
+
async secureEndpoint(req: any) {
|
|
377
|
+
return { user: req.auth };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
@Get("/with-scopes")
|
|
381
|
+
@Auth("BearerAuth", { scopes: ["read", "write"] })
|
|
382
|
+
async scopedEndpoint() {
|
|
383
|
+
return { data: "secret" };
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
@Get("/optional")
|
|
387
|
+
@Auth("BearerAuth", { optional: true })
|
|
388
|
+
async optionalAuth(req: any) {
|
|
389
|
+
return { user: req.auth }; // null if no token
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### @Public Decorator
|
|
395
|
+
|
|
396
|
+
Mark endpoints as publicly accessible (bypasses auth):
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
@Controller("/api")
|
|
400
|
+
export class ApiController {
|
|
401
|
+
@Get("/public")
|
|
402
|
+
@Public()
|
|
403
|
+
async publicEndpoint() {
|
|
404
|
+
return { message: "Anyone can access this" };
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
@Get("/protected")
|
|
408
|
+
@Auth("BearerAuth")
|
|
409
|
+
async protectedEndpoint() {
|
|
410
|
+
return { message: "Auth required" };
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Auth Scheme Configuration
|
|
416
|
+
|
|
417
|
+
Define custom authentication schemes:
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
const jwtRuntime = {
|
|
421
|
+
name: "JwtAuth",
|
|
422
|
+
async authenticate(req) {
|
|
423
|
+
const token = req.headers.authorization?.split(" ")[1];
|
|
424
|
+
if (!token) return null;
|
|
425
|
+
try {
|
|
426
|
+
const payload = verify(token, process.env.JWT_SECRET!);
|
|
427
|
+
return { principal: payload, scopes: payload.scopes || [] };
|
|
428
|
+
} catch {
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
challenge(res) {
|
|
433
|
+
res.setHeader("WWW-Authenticate", 'Bearer realm="api"');
|
|
434
|
+
res.status(401).json({ error: "Invalid token" });
|
|
435
|
+
},
|
|
436
|
+
authorize(auth, requiredScopes) {
|
|
437
|
+
return requiredScopes.every(s => auth.scopes.includes(s));
|
|
438
|
+
},
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
await createExpressRouter({
|
|
442
|
+
controllers: [ApiController],
|
|
443
|
+
auth: { schemes: { JwtAuth: jwtRuntime } },
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Middleware
|
|
448
|
+
|
|
449
|
+
Adorn-API supports middleware at three levels: global, controller, and route.
|
|
450
|
+
|
|
451
|
+
### Global Middleware
|
|
452
|
+
|
|
453
|
+
Apply middleware to all routes:
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
await createExpressRouter({
|
|
457
|
+
controllers: [ControllerA, ControllerB],
|
|
458
|
+
middleware: {
|
|
459
|
+
global: [loggingMw, corsMw],
|
|
460
|
+
},
|
|
461
|
+
});
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Controller-Level Middleware
|
|
465
|
+
|
|
466
|
+
Use `@Use` on a controller class:
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
@Controller("/api")
|
|
470
|
+
@Use(controllerMw)
|
|
471
|
+
export class ApiController {
|
|
472
|
+
@Get("/")
|
|
473
|
+
async getData() { /* global, controller, then handler */ }
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Route-Level Middleware
|
|
478
|
+
|
|
479
|
+
Use `@Use` on individual methods:
|
|
480
|
+
|
|
481
|
+
```typescript
|
|
482
|
+
@Controller("/api")
|
|
483
|
+
export class ApiController {
|
|
484
|
+
@Get("/")
|
|
485
|
+
@Use(routeMw)
|
|
486
|
+
async getData() { /* global, controller, route, then handler */ }
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Middleware execution order: `global` → `controller` → `route` → `handler`
|
|
491
|
+
|
|
492
|
+
### Named Middleware
|
|
493
|
+
|
|
494
|
+
Register middleware by name for reuse:
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
const rateLimiter = (req: any, res: any, next: any) => {
|
|
498
|
+
// rate limiting logic
|
|
499
|
+
next();
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
await createExpressRouter({
|
|
503
|
+
controllers: [ApiController],
|
|
504
|
+
middleware: {
|
|
505
|
+
named: { rateLimiter },
|
|
506
|
+
},
|
|
507
|
+
});
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
@Controller("/api")
|
|
512
|
+
export class ApiController {
|
|
513
|
+
@Get("/")
|
|
514
|
+
@Use("rateLimiter")
|
|
515
|
+
async getData() { /* uses named middleware */ }
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
## Schema & Validation
|
|
520
|
+
|
|
521
|
+
### Schema Decorators
|
|
522
|
+
|
|
523
|
+
Apply validation rules to object properties:
|
|
524
|
+
|
|
525
|
+
```typescript
|
|
526
|
+
import { Schema, Min, Max, MinLength, MaxLength, Pattern, Enum } from "adorn-api/schema";
|
|
527
|
+
|
|
528
|
+
class CreateUserRequest {
|
|
529
|
+
@MinLength(2)
|
|
530
|
+
@MaxLength(50)
|
|
531
|
+
name: string;
|
|
532
|
+
|
|
533
|
+
@Pattern("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")
|
|
534
|
+
email: string;
|
|
535
|
+
|
|
536
|
+
@Min(18)
|
|
537
|
+
@Max(120)
|
|
538
|
+
age: number;
|
|
539
|
+
|
|
540
|
+
@Enum(["admin", "user", "guest"])
|
|
541
|
+
role: "admin" | "user" | "guest";
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
Available decorators:
|
|
546
|
+
|
|
547
|
+
| Decorator | Purpose |
|
|
548
|
+
|-----------|---------|
|
|
549
|
+
| `@Min(n)` | Minimum numeric value |
|
|
550
|
+
| `@Max(n)` | Maximum numeric value |
|
|
551
|
+
| `@ExclusiveMin(n)` | Exclusive minimum |
|
|
552
|
+
| `@ExclusiveMax(n)` | Exclusive maximum |
|
|
553
|
+
| `@MinLength(n)` | Minimum string/array length |
|
|
554
|
+
| `@MaxLength(n)` | Maximum string/array length |
|
|
555
|
+
| `@Pattern(regex)` | Regex pattern match |
|
|
556
|
+
| `@Format(fmt)` | Format validation (email, uuid, etc.) |
|
|
557
|
+
| `@MinItems(n)` | Minimum array items |
|
|
558
|
+
| `@MaxItems(n)` | Maximum array items |
|
|
559
|
+
| `@MinProperties(n)` | Minimum object properties |
|
|
560
|
+
| `@MaxProperties(n)` | Maximum object properties |
|
|
561
|
+
| `@MultipleOf(n)` | Numeric multiple |
|
|
562
|
+
| `@Enum([...])` | Enumeration values |
|
|
563
|
+
| `@Const(value)` | Constant value |
|
|
564
|
+
| `@Default(value)` | Default value |
|
|
565
|
+
| `@Example(value)` | Example value for docs |
|
|
566
|
+
| `@Description(text)` | Property description |
|
|
567
|
+
| `@Closed()` | No additional properties |
|
|
568
|
+
| `@ClosedUnevaluated()` | Unevaluated properties not allowed |
|
|
569
|
+
|
|
570
|
+
### Validation Modes
|
|
571
|
+
|
|
572
|
+
Control how validation runs:
|
|
573
|
+
|
|
574
|
+
**Runtime (default):**
|
|
575
|
+
|
|
576
|
+
```bash
|
|
577
|
+
adorn-api build --validation-mode ajv-runtime
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
**Precompiled (production-optimized):**
|
|
581
|
+
|
|
582
|
+
```bash
|
|
583
|
+
adorn-api build --validation-mode precompiled
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
Generates optimized validator modules for faster startup.
|
|
587
|
+
|
|
588
|
+
**Disabled:**
|
|
589
|
+
|
|
590
|
+
```bash
|
|
591
|
+
adorn-api build --validation-mode none
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
## CLI Reference
|
|
595
|
+
|
|
596
|
+
### Build Command
|
|
597
|
+
|
|
598
|
+
Generate OpenAPI spec and manifest from TypeScript source:
|
|
599
|
+
|
|
600
|
+
```bash
|
|
601
|
+
adorn-api build -p ./tsconfig.json --output .adorn
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
**Options:**
|
|
605
|
+
|
|
606
|
+
| Option | Description | Default |
|
|
607
|
+
|--------|-------------|---------|
|
|
608
|
+
| `-p <path>` | Path to tsconfig.json | `./tsconfig.json` |
|
|
609
|
+
| `--output <dir>` | Output directory | `.adorn` |
|
|
610
|
+
| `--if-stale` | Only rebuild if stale | `false` |
|
|
611
|
+
| `--validation-mode <mode>` | Validation mode | `ajv-runtime` |
|
|
612
|
+
|
|
613
|
+
**Validation modes:** `none`, `ajv-runtime`, `precompiled`
|
|
614
|
+
|
|
615
|
+
### Clean Command
|
|
616
|
+
|
|
617
|
+
Remove generated artifacts:
|
|
618
|
+
|
|
619
|
+
```bash
|
|
620
|
+
adorn-api clean --output .adorn
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
### Incremental Builds
|
|
624
|
+
|
|
625
|
+
Use `--if-stale` for efficient rebuilds:
|
|
626
|
+
|
|
627
|
+
```bash
|
|
628
|
+
adorn-api build --if-stale
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
Only rebuilds when:
|
|
632
|
+
- Controller source files changed
|
|
633
|
+
- TypeScript version changed
|
|
634
|
+
- Adorn-API version changed
|
|
635
|
+
|
|
636
|
+
## API Reference
|
|
637
|
+
|
|
638
|
+
### bootstrap()
|
|
639
|
+
|
|
640
|
+
Quick server setup with sensible defaults:
|
|
641
|
+
|
|
642
|
+
```typescript
|
|
643
|
+
import { bootstrap } from "adorn-api/express";
|
|
644
|
+
|
|
645
|
+
await bootstrap({
|
|
646
|
+
controllers: [UserController],
|
|
647
|
+
port?: number, // Default: 3000 or PORT env
|
|
648
|
+
host?: string, // Default: "0.0.0.0" or HOST env
|
|
649
|
+
artifactsDir?: string, // Default: ".adorn"
|
|
650
|
+
enableSwagger?: boolean, // Default: true
|
|
651
|
+
swaggerPath?: string, // Default: "/docs"
|
|
652
|
+
swaggerJsonPath?: string, // Default: "/docs/openapi.json"
|
|
653
|
+
middleware?: CreateRouterOptions["middleware"],
|
|
654
|
+
auth?: CreateRouterOptions["auth"],
|
|
655
|
+
});
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
**Returns:** `{ server, app, url, port, host, close }`
|
|
659
|
+
|
|
660
|
+
### createExpressRouter()
|
|
661
|
+
|
|
662
|
+
Full control over router creation:
|
|
663
|
+
|
|
664
|
+
```typescript
|
|
665
|
+
import { createExpressRouter } from "adorn-api/express";
|
|
666
|
+
|
|
667
|
+
const router = await createExpressRouter({
|
|
668
|
+
controllers: [UserController],
|
|
669
|
+
artifactsDir?: string, // Default: ".adorn"
|
|
670
|
+
manifest?: ManifestV1, // Auto-loaded if not provided
|
|
671
|
+
openapi?: OpenAPI31, // Auto-loaded if not provided
|
|
672
|
+
auth?: {
|
|
673
|
+
schemes: Record<string, AuthSchemeRuntime>,
|
|
674
|
+
},
|
|
675
|
+
middleware?: {
|
|
676
|
+
global?: Middleware[],
|
|
677
|
+
named?: Record<string, Middleware>,
|
|
678
|
+
},
|
|
679
|
+
});
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
### setupSwagger()
|
|
683
|
+
|
|
684
|
+
Add Swagger UI to any Express app:
|
|
685
|
+
|
|
686
|
+
```typescript
|
|
687
|
+
import { setupSwagger } from "adorn-api/express";
|
|
688
|
+
|
|
689
|
+
app.use(setupSwagger({
|
|
690
|
+
artifactsDir?: string, // Default: ".adorn"
|
|
691
|
+
jsonPath?: string, // Default: "/docs/openapi.json"
|
|
692
|
+
uiPath?: string, // Default: "/docs"
|
|
693
|
+
swaggerOptions?: {
|
|
694
|
+
servers?: [{ url: string }],
|
|
695
|
+
// Other Swagger UI options
|
|
696
|
+
},
|
|
697
|
+
}));
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
## Why Adorn-API?
|
|
701
|
+
|
|
702
|
+
| Feature | Adorn-API | tsoa | NestJS |
|
|
703
|
+
|---------|-----------|------|--------|
|
|
704
|
+
| Decorator-first | Yes | Yes | Yes |
|
|
705
|
+
| OpenAPI 3.1 | Yes | Yes | Yes |
|
|
706
|
+
| No transpilation | Yes | No | No |
|
|
707
|
+
| Incremental builds | Yes | No | No |
|
|
708
|
+
| Precompiled validators | Yes | No | No |
|
|
709
|
+
| Stage-3 decorators | Yes | Stage 2 | Custom |
|
|
710
|
+
| Learning curve | Low | Medium | High |
|
|
711
|
+
| Framework agnostic | Yes | Partial | No |
|
|
712
|
+
| Metal ORM integration | Yes | No | No |
|
|
713
|
+
|
|
714
|
+
### What Makes Adorn-API Different
|
|
715
|
+
|
|
716
|
+
**Stage-3 Decorators:** Uses the official TC39 decorators proposal (ES2024), not legacy TypeScript experimental decorators. This means no build-time transformer is required—your decorators compile directly to metadata that Adorn-API reads at runtime.
|
|
717
|
+
|
|
718
|
+
**No Transpilation Needed:** Unlike tsoa, Adorn-API doesn't require a custom TypeScript transformer. Controllers are regular TypeScript classes that work with native decorators.
|
|
719
|
+
|
|
720
|
+
**Incremental Builds:** The `--if-stale` flag intelligently determines when rebuilds are needed, caching TypeScript program states for fast iteration.
|
|
721
|
+
|
|
722
|
+
**Precompiled Validators:** Generate optimized validation modules at build time for production deployments where startup time matters.
|
|
723
|
+
|
|
724
|
+
**Framework Agnostic:** While Express is the primary adapter, the core is adapter-based and could support other frameworks in the future.
|
|
725
|
+
|
|
726
|
+
## Metal ORM Integration
|
|
727
|
+
|
|
728
|
+
Adorn-API can auto-generate OpenAPI schemas from Metal ORM entities:
|
|
729
|
+
|
|
730
|
+
```typescript
|
|
731
|
+
import { Controller, Get } from "adorn-api";
|
|
732
|
+
import { User } from "./entities/index.js";
|
|
733
|
+
import { registerMetalEntities } from "adorn-api/metal";
|
|
734
|
+
|
|
735
|
+
@Controller("/users")
|
|
736
|
+
export class UsersController {
|
|
737
|
+
@Get("/")
|
|
738
|
+
async getUsers(): Promise<User[]> {
|
|
739
|
+
return session.find(User);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// Auto-generate schema from entity
|
|
744
|
+
const openapi = { /* base openapi */ };
|
|
745
|
+
registerMetalEntities(openapi, [User], { stripEntitySuffix: true });
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
Options:
|
|
749
|
+
- `mode`: `"read"` or `"create"` (excludes auto-generated columns)
|
|
750
|
+
- `stripEntitySuffix`: Remove `_Entity` suffix from schema names
|
|
751
|
+
|
|
752
|
+
## Project Structure
|
|
753
|
+
|
|
754
|
+
```
|
|
755
|
+
my-api/
|
|
756
|
+
├── src/
|
|
757
|
+
│ ├── controller.ts # Your controllers
|
|
758
|
+
│ └── server.ts # Entry point
|
|
759
|
+
├── .adorn/ # Generated artifacts (gitignored)
|
|
760
|
+
│ ├── openapi.json # OpenAPI spec
|
|
761
|
+
│ ├── manifest.json # Route manifest
|
|
762
|
+
│ └── cache.json # Build cache
|
|
763
|
+
├── tsconfig.json
|
|
764
|
+
└── package.json
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
## License
|
|
768
|
+
|
|
769
|
+
MIT
|