create-cloudflare 0.0.0-e144f63f → 0.0.0-e176ba485

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.
Files changed (56) hide show
  1. package/dist/cli.js +6215 -7003
  2. package/dist/tsconfig.tsbuildinfo +1 -1
  3. package/package.json +19 -20
  4. package/templates/angular/c3.ts +1 -0
  5. package/templates/common/c3.ts +3 -0
  6. package/templates/common/js/package.json +1 -1
  7. package/templates/common/ts/package.json +2 -2
  8. package/templates/common/ts/src/ab-test.ts +2 -2
  9. package/templates/common/ts/src/index.ts +2 -2
  10. package/templates/common/ts/src/proxy.ts +2 -2
  11. package/templates/common/ts/src/redirect.ts +2 -2
  12. package/templates/common/ts/tsconfig.json +1 -1
  13. package/templates/hello-world/c3.ts +5 -1
  14. package/templates/hello-world/js/package.json +3 -3
  15. package/templates/{hello-world-python → hello-world}/py/package.json +1 -1
  16. package/templates/hello-world/ts/package.json +4 -4
  17. package/templates/hello-world/ts/src/index.ts +2 -2
  18. package/templates/hello-world/ts/tsconfig.json +3 -2
  19. package/templates/hello-world-durable-object/c3.ts +3 -1
  20. package/templates/hello-world-durable-object/js/package.json +1 -1
  21. package/templates/hello-world-durable-object/ts/package.json +2 -2
  22. package/templates/hello-world-durable-object/ts/src/index.ts +2 -2
  23. package/templates/hello-world-durable-object/ts/tsconfig.json +1 -1
  24. package/templates/hono/c3.ts +0 -10
  25. package/templates/hono/snippets/appDeclaration.ts +1 -1
  26. package/templates/next/README.md +1 -1
  27. package/templates/next/c3.ts +1 -1
  28. package/templates/nuxt/c3.ts +5 -6
  29. package/templates/openapi/c3.ts +1 -0
  30. package/templates/openapi/ts/README.md +3 -3
  31. package/templates/openapi/ts/package.json +5 -3
  32. package/templates/openapi/ts/src/endpoints/taskCreate.ts +26 -16
  33. package/templates/openapi/ts/src/endpoints/taskDelete.ts +20 -19
  34. package/templates/openapi/ts/src/endpoints/taskFetch.ts +30 -23
  35. package/templates/openapi/ts/src/endpoints/taskList.ts +27 -24
  36. package/templates/openapi/ts/src/index.ts +14 -20
  37. package/templates/openapi/ts/src/types.ts +9 -8
  38. package/templates/pre-existing/js/package.json +1 -1
  39. package/templates/queues/c3.ts +2 -0
  40. package/templates/queues/js/package.json +1 -1
  41. package/templates/queues/ts/package.json +2 -2
  42. package/templates/queues/ts/src/index.ts +3 -3
  43. package/templates/queues/ts/tsconfig.json +1 -1
  44. package/templates/react/c3.ts +31 -3
  45. package/templates/scheduled/c3.ts +2 -0
  46. package/templates/scheduled/js/package.json +1 -1
  47. package/templates/scheduled/ts/package.json +2 -2
  48. package/templates/scheduled/ts/src/index.ts +2 -2
  49. package/templates/scheduled/ts/tsconfig.json +1 -1
  50. package/templates/solid/c3.ts +7 -5
  51. package/templates/hello-world-python/c3.ts +0 -9
  52. package/templates/hono/snippets/bindingsType.ts +0 -3
  53. /package/templates/{hello-world-python → hello-world}/py/__dot__gitignore +0 -0
  54. /package/templates/{hello-world-python → hello-world}/py/src/entry.py +0 -0
  55. /package/templates/{hello-world-python → hello-world}/py/wrangler.toml +0 -0
  56. /package/templates/hello-world/ts/{vitest.config.ts → vitest.config.mts} +0 -0
@@ -6,7 +6,7 @@ const EXPERIMENTS = [
6
6
  ];
7
7
 
8
8
  export default {
9
- async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
9
+ async fetch(request, env, ctx): Promise<Response> {
10
10
  const fingerprint = [request.headers.get('cf-connecting-ip'), request.cf?.postalCode]; // add any values you want considered as a fingerprint
11
11
  const activeExperiments = await getActiveExperiments(fingerprint, EXPERIMENTS);
12
12
 
@@ -22,7 +22,7 @@ export default {
22
22
 
23
23
  return rewriter.transform(res);
24
24
  },
25
- };
25
+ } satisfies ExportedHandler<Env>;
26
26
 
27
27
  // Get active experiments by hashing a fingerprint
28
28
  async function getActiveExperiments(fingerprint: unknown, experiments: Array<{ name: string; threshold: number }>) {
@@ -19,7 +19,7 @@ import apiRouter from './router';
19
19
  export default {
20
20
  // The fetch handler is invoked when this worker receives a HTTP(S) request
21
21
  // and should return a Response (optionally wrapped in a Promise)
22
- async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
22
+ async fetch(request, env, ctx): Promise<Response> {
23
23
  // You'll find it helpful to parse the request.url string into a URL object. Learn more at https://developer.mozilla.org/en-US/docs/Web/API/URL
24
24
  const url = new URL(request.url);
25
25
 
@@ -46,4 +46,4 @@ export default {
46
46
  { headers: { 'Content-Type': 'text/html' } }
47
47
  );
48
48
  },
49
- };
49
+ } satisfies ExportedHandler<Env>;
@@ -1,5 +1,5 @@
1
1
  export default {
2
- async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
2
+ async fetch(request, env, ctx): Promise<Response> {
3
3
  const url = new URL(request.url);
4
4
 
5
5
  const proxyUrl = url.searchParams.get('proxyUrl'); // get a query param value (?proxyUrl=...)
@@ -20,4 +20,4 @@ export default {
20
20
 
21
21
  return res;
22
22
  },
23
- };
23
+ } satisfies ExportedHandler<Env>;
@@ -1,5 +1,5 @@
1
1
  export default {
2
- async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
2
+ async fetch(request, env, ctx): Promise<Response> {
3
3
  const url = new URL(request.url);
4
4
  const redirectUrl = url.searchParams.get('redirectUrl'); // get a query param value (?redirectUrl=...)
5
5
 
@@ -10,4 +10,4 @@ export default {
10
10
  // The Response class has static methods to create common Response objects as a convenience
11
11
  return Response.redirect(redirectUrl);
12
12
  },
13
- };
13
+ } satisfies ExportedHandler<Env>;
@@ -13,7 +13,7 @@
13
13
  /* Language and Environment */
14
14
  "target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
15
15
  "lib": ["es2021"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
16
- "jsx": "react" /* Specify what JSX code is generated. */,
16
+ "jsx": "react-jsx" /* Specify what JSX code is generated. */,
17
17
  // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
18
18
  // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19
19
  // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
@@ -1,7 +1,8 @@
1
1
  export default {
2
2
  configVersion: 1,
3
3
  id: "hello-world",
4
- displayName: '"Hello World" Worker',
4
+ displayName: "Hello World Worker",
5
+ description: "Get started with a basic Worker in the language of your choice",
5
6
  platform: "workers",
6
7
  copyFiles: {
7
8
  variants: {
@@ -11,6 +12,9 @@ export default {
11
12
  ts: {
12
13
  path: "./ts",
13
14
  },
15
+ python: {
16
+ path: "./py",
17
+ },
14
18
  },
15
19
  },
16
20
  };
@@ -9,8 +9,8 @@
9
9
  "test": "vitest"
10
10
  },
11
11
  "devDependencies": {
12
- "wrangler": "^3.0.0",
13
- "vitest": "1.3.0",
14
- "@cloudflare/vitest-pool-workers": "^0.1.0"
12
+ "@cloudflare/vitest-pool-workers": "^0.4.5",
13
+ "wrangler": "^3.60.3",
14
+ "vitest": "1.5.0"
15
15
  }
16
16
  }
@@ -8,6 +8,6 @@
8
8
  "start": "wrangler dev"
9
9
  },
10
10
  "devDependencies": {
11
- "wrangler": "^3.0.0"
11
+ "wrangler": "^3.60.3"
12
12
  }
13
13
  }
@@ -10,9 +10,9 @@
10
10
  "cf-typegen": "wrangler types"
11
11
  },
12
12
  "devDependencies": {
13
- "typescript": "^5.0.4",
14
- "wrangler": "^3.0.0",
15
- "vitest": "1.3.0",
16
- "@cloudflare/vitest-pool-workers": "^0.1.0"
13
+ "@cloudflare/vitest-pool-workers": "^0.4.5",
14
+ "typescript": "^5.5.2",
15
+ "vitest": "1.5.0",
16
+ "wrangler": "^3.60.3"
17
17
  }
18
18
  }
@@ -12,7 +12,7 @@
12
12
  */
13
13
 
14
14
  export default {
15
- async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
15
+ async fetch(request, env, ctx): Promise<Response> {
16
16
  return new Response('Hello World!');
17
17
  },
18
- };
18
+ } satisfies ExportedHandler<Env>;
@@ -13,7 +13,7 @@
13
13
  /* Language and Environment */
14
14
  "target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
15
15
  "lib": ["es2021"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
16
- "jsx": "react" /* Specify what JSX code is generated. */,
16
+ "jsx": "react-jsx" /* Specify what JSX code is generated. */,
17
17
  // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
18
18
  // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19
19
  // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
@@ -98,5 +98,6 @@
98
98
  // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
99
99
  "skipLibCheck": true /* Skip type checking all .d.ts files. */
100
100
  },
101
- "exclude": ["test"]
101
+ "exclude": ["test"],
102
+ "include": ["worker-configuration.d.ts", "src/**/*.ts"]
102
103
  }
@@ -1,7 +1,9 @@
1
1
  export default {
2
2
  configVersion: 1,
3
3
  id: "hello-world-durable-object",
4
- displayName: "Co-ordination / multiplayer API (using Durable Objects)",
4
+ displayName: "Hello World Worker Using Durable Objects",
5
+ description:
6
+ "Get started with a basic stateful app to build projects like real-time chats, collaborative apps, and multiplayer games",
5
7
  platform: "workers",
6
8
  copyFiles: {
7
9
  variants: {
@@ -8,6 +8,6 @@
8
8
  "start": "wrangler dev"
9
9
  },
10
10
  "devDependencies": {
11
- "wrangler": "^3.0.0"
11
+ "wrangler": "^3.60.3"
12
12
  }
13
13
  }
@@ -9,7 +9,7 @@
9
9
  "cf-typegen": "wrangler types"
10
10
  },
11
11
  "devDependencies": {
12
- "typescript": "^5.0.4",
13
- "wrangler": "^3.0.0"
12
+ "typescript": "^5.5.2",
13
+ "wrangler": "^3.60.3"
14
14
  }
15
15
  }
@@ -68,7 +68,7 @@ export default {
68
68
  * @param ctx - The execution context of the Worker
69
69
  * @returns The response to be sent back to the client
70
70
  */
71
- async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
71
+ async fetch(request, env, ctx): Promise<Response> {
72
72
  // We will create a `DurableObjectId` using the pathname from the Worker request
73
73
  // This id refers to a unique instance of our 'MyDurableObject' class above
74
74
  let id: DurableObjectId = env.MY_DURABLE_OBJECT.idFromName(new URL(request.url).pathname);
@@ -83,4 +83,4 @@ export default {
83
83
 
84
84
  return new Response(greeting);
85
85
  },
86
- };
86
+ } satisfies ExportedHandler<Env>;
@@ -13,7 +13,7 @@
13
13
  /* Language and Environment */
14
14
  "target": "es2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
15
15
  "lib": ["es2021"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
16
- "jsx": "react" /* Specify what JSX code is generated. */,
16
+ "jsx": "react-jsx" /* Specify what JSX code is generated. */,
17
17
  // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
18
18
  // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19
19
  // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
@@ -32,16 +32,6 @@ const configure = async (ctx: C3Context) => {
32
32
  const snippets = loadTemplateSnippets(ctx);
33
33
 
34
34
  transformFile(indexFile, {
35
- // Insert the env declaration after the last import (but before the rest of the body)
36
- visitProgram: function (n) {
37
- const lastImportIndex = n.node.body.findLastIndex(
38
- (t) => t.type === "ImportDeclaration",
39
- );
40
- const lastImport = n.get("body", lastImportIndex);
41
- lastImport.insertAfter(...snippets.bindingsTypeTs);
42
-
43
- return this.traverse(n);
44
- },
45
35
  visitVariableDeclarator(n) {
46
36
  if (n.node.id.type === "Identifier" && n.node.id.name === "app") {
47
37
  n.node.init = snippets
@@ -1 +1 @@
1
- new Hono<{ Bindings: Bindings }>()
1
+ new Hono<{ Bindings: CloudflareBindings }>()
@@ -23,7 +23,7 @@ Besides the `dev` script mentioned above `c3` has added a few extra scripts that
23
23
  - `preview` to locally preview your Pages application using the [Wrangler](https://developers.cloudflare.com/workers/wrangler/) CLI
24
24
  - `deploy` to deploy your Pages application using the [Wrangler](https://developers.cloudflare.com/workers/wrangler/) CLI
25
25
 
26
- > __Note:__ while the `dev` script is optimal for local development you should preview your Pages application as well (periodically or before deployments) in order to make sure that it can properly work in the Pages environment (for more details see the [`@cloudflare/next-on-pages` recommended workflow](https://github.com/cloudflare/next-on-pages/blob/05b6256/internal-packages/next-dev/README.md#recommended-workflow))
26
+ > __Note:__ while the `dev` script is optimal for local development you should preview your Pages application as well (periodically or before deployments) in order to make sure that it can properly work in the Pages environment (for more details see the [`@cloudflare/next-on-pages` recommended workflow](https://github.com/cloudflare/next-on-pages/blob/main/internal-packages/next-dev/README.md#recommended-development-workflow))
27
27
 
28
28
  ### Bindings
29
29
 
@@ -63,7 +63,7 @@ const updateNextConfig = () => {
63
63
 
64
64
  // Here we use the @cloudflare/next-on-pages next-dev module to allow us to use bindings during local development
65
65
  // (when running the application with \`next dev\`), for more information see:
66
- // https://github.com/cloudflare/next-on-pages/blob/5712c57ea7/internal-packages/next-dev/README.md
66
+ // https://github.com/cloudflare/next-on-pages/blob/main/internal-packages/next-dev/README.md
67
67
  if (process.env.NODE_ENV === 'development') {
68
68
  await setupDevPlatform();
69
69
  }
@@ -2,7 +2,7 @@ import { logRaw } from "@cloudflare/cli";
2
2
  import { brandColor, dim } from "@cloudflare/cli/colors";
3
3
  import { spinner } from "@cloudflare/cli/interactive";
4
4
  import { runFrameworkGenerator } from "frameworks/index";
5
- import { transformFile } from "helpers/codemod";
5
+ import { mergeObjectProperties, transformFile } from "helpers/codemod";
6
6
  import { getLatestTypesEntrypoint } from "helpers/compatDate";
7
7
  import { readFile, writeFile } from "helpers/files";
8
8
  import { detectPackageManager } from "helpers/packageManagers";
@@ -96,11 +96,10 @@ const updateNuxtConfig = () => {
96
96
  visitCallExpression: function (n) {
97
97
  const callee = n.node.callee as recast.types.namedTypes.Identifier;
98
98
  if (callee.name === "defineNuxtConfig") {
99
- const obj = n.node
100
- .arguments[0] as recast.types.namedTypes.ObjectExpression;
101
-
102
- obj.properties.push(presetDef);
103
- obj.properties.push(moduleDef);
99
+ mergeObjectProperties(
100
+ n.node.arguments[0] as recast.types.namedTypes.ObjectExpression,
101
+ [presetDef, moduleDef],
102
+ );
104
103
  }
105
104
 
106
105
  return this.traverse(n);
@@ -2,6 +2,7 @@ export default {
2
2
  configVersion: 1,
3
3
  id: "openapi",
4
4
  displayName: "API starter (OpenAPI compliant)",
5
+ description: "Get started building a basic API on Workers",
5
6
  platform: "workers",
6
7
  copyFiles: {
7
8
  path: "./ts",
@@ -1,6 +1,6 @@
1
1
  # Cloudflare Workers OpenAPI 3.1
2
2
 
3
- This is a Cloudflare Worker with OpenAPI 3.1 using [itty-router-openapi](https://github.com/cloudflare/itty-router-openapi).
3
+ This is a Cloudflare Worker with OpenAPI 3.1 using [chanfana](https://github.com/cloudflare/chanfana) and [Hono](https://github.com/honojs/hono).
4
4
 
5
5
  This is an example project made to be used as a quick start into building OpenAPI compliant Workers that generates the
6
6
  `openapi.json` schema automatically from code and validates the incoming request to the defined parameters or request body.
@@ -16,10 +16,10 @@ This is an example project made to be used as a quick start into building OpenAP
16
16
 
17
17
  1. Your main router is defined in `src/index.ts`.
18
18
  2. Each endpoint has its own file in `src/endpoints/`.
19
- 3. For more information read the [itty-router-openapi official documentation](https://cloudflare.github.io/itty-router-openapi/).
19
+ 3. For more information read the [chanfana documentation](https://chanfana.pages.dev/) and [Hono documentation](https://hono.dev/docs).
20
20
 
21
21
  ## Development
22
22
 
23
23
  1. Run `wrangler dev` to start a local instance of the API.
24
- 2. Open `http://localhost:9000/` in your browser to see the Swagger interface where you can try the endpoints.
24
+ 2. Open `http://localhost:8787/` in your browser to see the Swagger interface where you can try the endpoints.
25
25
  3. Changes made in the `src/` folder will automatically trigger the server to reload, you only need to refresh the Swagger interface.
@@ -9,11 +9,13 @@
9
9
  "cf-typegen": "wrangler types"
10
10
  },
11
11
  "dependencies": {
12
- "@cloudflare/itty-router-openapi": "^1.0.1"
12
+ "chanfana": "^2.0.2",
13
+ "zod": "^3.23.8",
14
+ "hono": "^4.4.7"
13
15
  },
14
16
  "devDependencies": {
15
- "@types/node": "^20.5.7",
17
+ "@types/node": "20.8.3",
16
18
  "@types/service-worker-mock": "^2.0.1",
17
- "wrangler": "^3.0.0"
19
+ "wrangler": "^3.60.3"
18
20
  }
19
21
  }
@@ -1,33 +1,43 @@
1
- import {
2
- OpenAPIRoute,
3
- OpenAPIRouteSchema,
4
- } from "@cloudflare/itty-router-openapi";
1
+ import { Bool, OpenAPIRoute } from "chanfana";
2
+ import { z } from "zod";
5
3
  import { Task } from "../types";
6
4
 
7
5
  export class TaskCreate extends OpenAPIRoute {
8
- static schema: OpenAPIRouteSchema = {
6
+ schema = {
9
7
  tags: ["Tasks"],
10
8
  summary: "Create a new Task",
11
- requestBody: Task,
9
+ request: {
10
+ body: {
11
+ content: {
12
+ "application/json": {
13
+ schema: Task,
14
+ },
15
+ },
16
+ },
17
+ },
12
18
  responses: {
13
19
  "200": {
14
20
  description: "Returns the created task",
15
- schema: {
16
- success: Boolean,
17
- result: {
18
- task: Task,
21
+ content: {
22
+ "application/json": {
23
+ schema: z.object({
24
+ series: z.object({
25
+ success: Bool(),
26
+ result: z.object({
27
+ task: Task,
28
+ }),
29
+ }),
30
+ }),
19
31
  },
20
32
  },
21
33
  },
22
34
  },
23
35
  };
24
36
 
25
- async handle(
26
- request: Request,
27
- env: any,
28
- context: any,
29
- data: Record<string, any>
30
- ) {
37
+ async handle(c) {
38
+ // Get validated data
39
+ const data = await this.getValidatedData<typeof this.schema>();
40
+
31
41
  // Retrieve the validated request body
32
42
  const taskToCreate = data.body;
33
43
 
@@ -1,38 +1,39 @@
1
- import {
2
- OpenAPIRoute,
3
- OpenAPIRouteSchema,
4
- Path,
5
- } from "@cloudflare/itty-router-openapi";
1
+ import { Bool, OpenAPIRoute, Str } from "chanfana";
2
+ import { z } from "zod";
6
3
  import { Task } from "../types";
7
4
 
8
5
  export class TaskDelete extends OpenAPIRoute {
9
- static schema: OpenAPIRouteSchema = {
6
+ schema = {
10
7
  tags: ["Tasks"],
11
8
  summary: "Delete a Task",
12
- parameters: {
13
- taskSlug: Path(String, {
14
- description: "Task slug",
9
+ request: {
10
+ params: z.object({
11
+ taskSlug: Str({ description: "Task slug" }),
15
12
  }),
16
13
  },
17
14
  responses: {
18
15
  "200": {
19
16
  description: "Returns if the task was deleted successfully",
20
- schema: {
21
- success: Boolean,
22
- result: {
23
- task: Task,
17
+ content: {
18
+ "application/json": {
19
+ schema: z.object({
20
+ series: z.object({
21
+ success: Bool(),
22
+ result: z.object({
23
+ task: Task,
24
+ }),
25
+ }),
26
+ }),
24
27
  },
25
28
  },
26
29
  },
27
30
  },
28
31
  };
29
32
 
30
- async handle(
31
- request: Request,
32
- env: any,
33
- context: any,
34
- data: Record<string, any>
35
- ) {
33
+ async handle(c) {
34
+ // Get validated data
35
+ const data = await this.getValidatedData<typeof this.schema>();
36
+
36
37
  // Retrieve the validated slug
37
38
  const { taskSlug } = data.params;
38
39
 
@@ -1,45 +1,52 @@
1
- import {
2
- OpenAPIRoute,
3
- OpenAPIRouteSchema,
4
- Path,
5
- } from "@cloudflare/itty-router-openapi";
1
+ import { Bool, OpenAPIRoute, Str } from "chanfana";
2
+ import { z } from "zod";
6
3
  import { Task } from "../types";
7
4
 
8
5
  export class TaskFetch extends OpenAPIRoute {
9
- static schema: OpenAPIRouteSchema = {
6
+ schema = {
10
7
  tags: ["Tasks"],
11
8
  summary: "Get a single Task by slug",
12
- parameters: {
13
- taskSlug: Path(String, {
14
- description: "Task slug",
9
+ request: {
10
+ params: z.object({
11
+ taskSlug: Str({ description: "Task slug" }),
15
12
  }),
16
13
  },
17
14
  responses: {
18
15
  "200": {
19
16
  description: "Returns a single task if found",
20
- schema: {
21
- success: Boolean,
22
- result: {
23
- task: Task,
17
+ content: {
18
+ "application/json": {
19
+ schema: z.object({
20
+ series: z.object({
21
+ success: Bool(),
22
+ result: z.object({
23
+ task: Task,
24
+ }),
25
+ }),
26
+ }),
24
27
  },
25
28
  },
26
29
  },
27
30
  "404": {
28
31
  description: "Task not found",
29
- schema: {
30
- success: Boolean,
31
- error: String,
32
+ content: {
33
+ "application/json": {
34
+ schema: z.object({
35
+ series: z.object({
36
+ success: Bool(),
37
+ error: Str(),
38
+ }),
39
+ }),
40
+ },
32
41
  },
33
42
  },
34
43
  },
35
44
  };
36
45
 
37
- async handle(
38
- request: Request,
39
- env: any,
40
- context: any,
41
- data: Record<string, any>
42
- ) {
46
+ async handle(c) {
47
+ // Get validated data
48
+ const data = await this.getValidatedData<typeof this.schema>();
49
+
43
50
  // Retrieve the validated slug
44
51
  const { taskSlug } = data.params;
45
52
 
@@ -56,7 +63,7 @@ export class TaskFetch extends OpenAPIRoute {
56
63
  },
57
64
  {
58
65
  status: 404,
59
- }
66
+ },
60
67
  );
61
68
  }
62
69
 
@@ -1,43 +1,46 @@
1
- import {
2
- OpenAPIRoute,
3
- OpenAPIRouteSchema,
4
- Query,
5
- } from "@cloudflare/itty-router-openapi";
1
+ import { Bool, Num, OpenAPIRoute } from "chanfana";
2
+ import { z } from "zod";
6
3
  import { Task } from "../types";
7
4
 
8
5
  export class TaskList extends OpenAPIRoute {
9
- static schema: OpenAPIRouteSchema = {
6
+ schema = {
10
7
  tags: ["Tasks"],
11
8
  summary: "List Tasks",
12
- parameters: {
13
- page: Query(Number, {
14
- description: "Page number",
15
- default: 0,
16
- }),
17
- isCompleted: Query(Boolean, {
18
- description: "Filter by completed flag",
19
- required: false,
9
+ request: {
10
+ query: z.object({
11
+ page: Num({
12
+ description: "Page number",
13
+ default: 0,
14
+ }),
15
+ isCompleted: Bool({
16
+ description: "Filter by completed flag",
17
+ required: false,
18
+ }),
20
19
  }),
21
20
  },
22
21
  responses: {
23
22
  "200": {
24
23
  description: "Returns a list of tasks",
25
- schema: {
26
- success: Boolean,
27
- result: {
28
- tasks: [Task],
24
+ content: {
25
+ "application/json": {
26
+ schema: z.object({
27
+ series: z.object({
28
+ success: Bool(),
29
+ result: z.object({
30
+ tasks: Task.array(),
31
+ }),
32
+ }),
33
+ }),
29
34
  },
30
35
  },
31
36
  },
32
37
  },
33
38
  };
34
39
 
35
- async handle(
36
- request: Request,
37
- env: any,
38
- context: any,
39
- data: Record<string, any>
40
- ) {
40
+ async handle(c) {
41
+ // Get validated data
42
+ const data = await this.getValidatedData<typeof this.schema>();
43
+
41
44
  // Retrieve the validated parameters
42
45
  const { page, isCompleted } = data.query;
43
46