Giter VIP home page Giter VIP logo

sveltekit-api's Introduction

SvelteKit-API

Handles all kinds of SvelteKit data flows in one place, and automatically generate OpenAPI documentation.

Features

  • API: Manage API endpoints and automatically generate OpenAPI documentation
  • load2api: Transform a server-side load function into an API endpoint
  • tree: Build a tree of endpoint routes

Installation

pnpm i -D sveltekit-api

Projects using SvelteKit-API

These projects are using SvelteKit-API and can be used as examples:

  • WASM OJ Wonderland: A SvelteKit-based online judge system core.
  • PEA: A serverless email authentication and verification service.
  • Add your project here by submitting a pull request!

Usage

API

Add $api to your svelte.config.js:

/** @type {import('@sveltejs/kit').Config} */
const config = {
  kit: {
    alias: {
      "$api": "./src/api",
    },
  },
};

Create the API endpoints in the structure like src/api.

// for example:
src
├── api
   ├── index.ts
   └── post
       ├── GET.ts
       ├── POST.ts
       ├── [...id]
          └── GET.ts
       └── search
           └── GET.ts
├── lib
   └── ...
└── routes
    └── ...
// file: src/api/index.ts
import { API } from "sveltekit-api";

export default new API(import.meta.glob("./**/*.ts"), {
  openapi: "3.0.0",
  info: {
    title: "Simple Post API",
    version: "1.0.0",
    description: "An example API",
  },
});
// file: src/api/post/[...id]/PUT.ts
import { Endpoint, z, error } from "sveltekit-api";
import { posts, type Post } from "../../db.js";

export const Query = z.object({
  password: z.string().optional(),
});

export const Param = z.object({
  id: z.string(),
});

export const Input = z.object({
  title: z.string(),
  content: z.string(),
  author: z.string(),
});

export const Output = z.object({
  id: z.string(),
  title: z.string(),
  content: z.string(),
  author: z.string(),
  date: z.string(),
}) satisfies z.ZodSchema<Post>;

export const Error = {
  404: error(404, "Post not found"),
  403: error(403, "Forbidden"),
};

export default new Endpoint({ Param, Query, Input, Output, Error }).handle(async (param) => {
  const post = posts.get(param.id);

  if (!post) {
    throw Error[404];
  }

  if (post.password && post.password !== param.password) {
    throw Error[403];
  }

  post.title = param.title;
  post.content = param.content;
  post.author = param.author;

  return post;
});

Call the API handler and OpenAPI generator in your routes like src/routes/api.

// file: src/routes/+server.ts
import api from "$api";
import { json } from "@sveltejs/kit";

export const prerender = true;

export const GET = async (evt) => json(await api.openapi(evt));
// file: src/routes/api/post/+server.ts
import api from "$api";

export const GET = async (evt) => api.handle(evt);
export const POST = async (evt) => api.handle(evt);
export const OPTIONS = async (evt) => api.handle(evt);

load2api

Transforms a server-side load function into an API endpoint in a single line.

// file: src/routes/api/problem/[...id]/+server.ts
import { load2api } from "sveltekit-api";
import { load } from "$routes/problem/[...id]/+page.server";

export const GET = async (evt) => load2api("/problem/[...id]", load, evt);

tree

Build a self-explanatory tree of API endpoints.

import { tree } from "sveltekit-api";
import { json } from "@sveltejs/kit";

export const prerender = true;

export const GET = async () => {
  return json(await tree(import.meta.glob("./**/*/+server.ts")));
};

sveltekit-api's People

Contributors

jacoblincool avatar github-actions[bot] avatar doublemalt avatar andndre avatar plckr avatar woodyloody avatar

Stargazers

Ryan E avatar qwerty avatar  avatar Saenyakorn Siangsanoh avatar Chris Jayden avatar  avatar aTomohiroIto avatar  avatar pdina avatar  avatar  avatar Oleksandr Sadovyi avatar  avatar Nick Ludlam avatar Shawn avatar Arnav Gosain avatar Rohan Rajpal avatar Felix T.J. Dietrich avatar Nobu Kakegawa avatar Alexandre Brayer avatar  avatar Ming Fang avatar Richard Moore avatar Guillaume Schurck avatar wk-Tom avatar ryoppippi avatar

Watchers

Shawn avatar  avatar  avatar  avatar

sveltekit-api's Issues

Overall feedback

Hey, I'm looking for ways to implement openapi into sveltekit, I found this repository and I'm currently testing.

I find it pretty interesting, nice work!

There is specially one thing that bothers me, is that you suggest to duplicate routes in different locations.
Inside routes and inside a custom folder (you name it api). I wonder why you implemented this way.
Doesn't it make more sense to have the routes into a single location only?

For example:
Having a catch all into routes/api/[...route] and pointing all requests into the api.

// routes/api/[...route]/+server.ts

import api from '$api';
import type { RequestHandler } from './$types';

export const GET: RequestHandler = (evt) => api.handle(evt);
export const POST: RequestHandler = (evt) => api.handle(evt);
export const PUT: RequestHandler = (evt) => api.handle(evt);
export const DELETE: RequestHandler = (evt) => api.handle(evt);
export const OPTIONS: RequestHandler = (evt) => api.handle(evt);

and then control the routes in a different or the same location.


Another thing I just noticed is that this library isn't capable to deal with group routes
E.g.: /routes/(protected)/api/some-route
The example above will be read from the library as (protected)/api/some-route
image

I tried adding a new replace into the parse_module function and it seems to work well
At this line, add .replace(/\(.+\)\//g, "")


For last, don't you find it easier to export an object from each route/method instead of exports individual variables?
For someone that isn't aware of the library, it's more difficult to remember each variable to export.
My suggestion would be something like this:

import api from '$api';

// a function is used for type-safety purposes
export default api.defineEndpoint({
  query: z.object({
    password: z.string().optional(),
  }),
  param: z.object({
    id: z.string(),
  }),
  input: z.object({
    title: z.string(),
    content: z.string(),
    author: z.string(),
  }),
  output: z.object({
    id: z.string(),
    title: z.string(),
    content: z.string(),
    author: z.string(),
    date: z.string(),
  }) satisfies z.ZodSchema<Post>,
  error: {
    404: error(404, "Post not found"),
    403: error(403, "Forbidden"),
  },
  endpoint: async (param) => {
    const post = posts.get(param.id);
  
    if (!post) {
      throw Error[404];
    }
  
    if (post.password && post.password !== param.password) {
      throw Error[403];
    }
  
    post.title = param.title;
    post.content = param.content;
    post.author = param.author;
  
    return post;
  }
})

I'm able to fork and submit a pull request if you wish, I had like to discuss first.

`parse_module` Cannot Parse Routes With More than One Params

I recently discovered that routes containing more than one parameter are not parsed correctly by the current implementation.

Example

Consider the following route template:

/path/[first]/to/[second]/api

The current parsing result is:

/path/{first]/to/[second}/api

However, the expected result should be:

/path/{first}/to/{second}/api

Impact

This issue leads to incorrect parsing of parameters, causing the values of {first} and {second} to include extra characters, resulting in "{first]" and "[second}" instead of the expected values.

I am planning to submit a pull request to address this problem by fixing the parsing logic.

Openapi docs

Hello

This project looks great!

I'm wondering how/where are the openapi docs for the endpoint(s)?

Thanks

OpenAPI definition not created correctly if Output schema is a ZodArray

Eg. if in the api file Output is defined export const Output = z.array(someZodSchema); no response for the code 200 is generated.

However the output is validated correctly. As zod-to-openapi supports ZodArrays I think that should be fixable.

I'm happy to give it a stab if you point me to the right file to look at.

Other than that I'm super happy with your library!

Summary & Description for each path in OpenAPI

Hello,

Bravo for your idea and your implementation. I will adopt sveltekit-api.

I have a suggestion:
Be able to enter a summary and a description in each path. This will allow for more explanation in Swagger or PostMan.

I made an implementation, but I'm not up to the standard with TypeScript to publish it.
Sorry for the quality of the code, it's just to give an idea of possible implementation.
If someone better at TypeScrip than me could finish the job, that would be great.

Good day.
Archive.zip

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update dependency @changesets/cli to v2.27.7
  • chore(deps): update dependency publint to v0.2.9
  • chore(deps): update dependency svelte to v4.2.18
  • chore(deps): update dependency tslib to v2.6.3
  • fix(deps): update dependency debug to v4.3.5
  • chore(deps): update dependency @sveltejs/vite-plugin-svelte to v3.1.1
  • chore(deps): update dependency eslint to v8.57.0
  • chore(deps): update dependency eslint-plugin-svelte to v2.42.0
  • chore(deps): update dependency prettier to v3.3.3
  • chore(deps): update dependency prettier-plugin-svelte to v3.2.6
  • chore(deps): update dependency svelte-check to v3.8.4
  • chore(deps): update dependency typescript to v5.5.3
  • chore(deps): update dependency vite to v5.3.4
  • chore(deps): update typescript-eslint monorepo to v6.21.0 (@typescript-eslint/eslint-plugin, @typescript-eslint/parser)
  • fix(deps): update dependency @asteasolutions/zod-to-openapi to v6.4.0
  • fix(deps): update dependency type-fest to v4.22.1
  • fix(deps): update dependency zod to v3.23.8
  • fix(deps): update dependency zod-validation-error to v3.3.0
  • chore(deps): update dependency eslint to v9
  • chore(deps): update dependency prettier-plugin-organize-imports to v4
  • chore(deps): update pnpm to v9
  • chore(deps): update pnpm/action-setup action to v4
  • fix(deps): update dependency @asteasolutions/zod-to-openapi to v7
  • 🔐 Create all rate-limited PRs at once 🔐

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/release.yml
  • actions/checkout v3
  • pnpm/action-setup v2.2.4
  • changesets/action v1
.github/workflows/test.yml
  • actions/checkout v3
  • pnpm/action-setup v2.2.4
npm
package.json
  • @asteasolutions/zod-to-openapi ^6.3.1
  • debug ^4.3.4
  • type-fest ^4.10.2
  • zod ^3.22.4
  • zod-validation-error ^3.0.0
  • @changesets/changelog-github ^0.4.8
  • @changesets/cli ^2.27.1
  • @sveltejs/adapter-auto ^2.1.1
  • @sveltejs/package ^2.2.6
  • @sveltejs/vite-plugin-svelte ^3.0.2
  • @types/better-sqlite3 ^7.6.9
  • @types/debug ^4.1.12
  • @typescript-eslint/eslint-plugin ^6.20.0
  • @typescript-eslint/parser ^6.20.0
  • changeset ^0.2.6
  • eslint ^8.56.0
  • eslint-config-prettier ^9.1.0
  • eslint-plugin-svelte ^2.35.1
  • husky ^9.0.10
  • lint-staged ^15.2.1
  • prettier ^3.2.4
  • prettier-plugin-organize-imports ^3.2.4
  • prettier-plugin-svelte ^3.1.2
  • publint ^0.2.7
  • svelte ^4.2.9
  • svelte-check ^3.6.3
  • tslib ^2.6.2
  • typescript ^5.3.3
  • vite ^5.0.12
  • @sveltejs/kit ^1.0.0 || ^2.0.0
  • svelte ^3.0.0 || ^4.0.0
  • pnpm 8.15.1

  • Check this box to trigger a request for Renovate to run again on this repository

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.