Compare commits
8 Commits
main
...
platform-a
Author | SHA1 | Date |
---|---|---|
Ryukemeister | fcabcf7266 | |
Ryukemeister | 25f4273124 | |
Ryukemeister | 630a1f38a1 | |
Ryukemeister | 035191125e | |
Ryukemeister | 9cd771f7e7 | |
Ryukemeister | ee60f5611d | |
Morgan Vernay | 95c2bf9b54 | |
Morgan Vernay | a77839f0e5 |
|
@ -0,0 +1,65 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
jspm_packages
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# 0x
|
||||
profile-*
|
||||
|
||||
# mac files
|
||||
.DS_Store
|
||||
|
||||
# vim swap files
|
||||
*.swp
|
||||
|
||||
# webstorm
|
||||
.idea
|
||||
|
||||
# vscode
|
||||
.vscode
|
||||
*code-workspace
|
||||
|
||||
# clinic
|
||||
profile*
|
||||
*clinic*
|
||||
*flamegraph*
|
||||
|
||||
# generated code
|
||||
examples/typescript-server.js
|
||||
test/types/index.js
|
||||
|
||||
# compiled app
|
||||
dist
|
|
@ -0,0 +1,11 @@
|
|||
module.exports = {
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: true,
|
||||
singleQuote: true,
|
||||
trailingComma: 'all',
|
||||
bracketSpacing: true,
|
||||
jsxBracketSameLine: false,
|
||||
arrowParens: 'always',
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
test-env: [
|
||||
TS_NODE_FILES=true,
|
||||
TS_NODE_PROJECT=./test/tsconfig.json
|
||||
]
|
||||
timeout: 120
|
|
@ -0,0 +1,23 @@
|
|||
# Getting Started with [Fastify-CLI](https://www.npmjs.com/package/fastify-cli)
|
||||
This project was bootstrapped with Fastify-CLI.
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm run dev`
|
||||
|
||||
To start the app in dev mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
### `npm start`
|
||||
|
||||
For production mode
|
||||
|
||||
### `npm run test`
|
||||
|
||||
Run the test cases.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn Fastify, check out the [Fastify documentation](https://www.fastify.io/docs/latest/).
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"name": "api",
|
||||
"version": "1.0.0",
|
||||
"description": "This project was bootstrapped with Fastify-CLI.",
|
||||
"main": "app.ts",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npm run build:ts && tsc -p test/tsconfig.json && tap --ts \"test/**/*.test.ts\"",
|
||||
"start": "npm run build:ts && fastify start -l info dist/app.js",
|
||||
"build:ts": "tsc",
|
||||
"watch:ts": "tsc -w",
|
||||
"dev": "npm run build:ts && concurrently -k -p \"[{name}]\" -n \"TypeScript,App\" -c \"yellow.bold,cyan.bold\" \"npm:watch:ts\" \"npm:dev:start\"",
|
||||
"dev:start": "fastify start --ignore-watch=.ts$ -w -l info -P dist/app.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@fastify/autoload": "^5.0.0",
|
||||
"@fastify/sensible": "^5.0.0",
|
||||
"fastify": "^4.0.0",
|
||||
"fastify-cli": "^5.8.0",
|
||||
"fastify-plugin": "^4.0.0",
|
||||
"kysely": "^0.26.3",
|
||||
"pg": "^8.11.3",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.4.4",
|
||||
"@types/pg": "^8.10.7",
|
||||
"@types/tap": "^15.0.5",
|
||||
"concurrently": "^7.0.0",
|
||||
"fastify-tsconfig": "^1.0.1",
|
||||
"kysely-codegen": "^0.11.0",
|
||||
"prisma-kysely": "^1.7.1",
|
||||
"tap": "^16.1.0",
|
||||
"ts-node": "^10.4.0",
|
||||
"typescript": "^5.2.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
import type { Selectable } from 'kysely';
|
||||
import type { ApiKey } from 'kysely-codegen';
|
||||
|
||||
export type ApiKeyType = Selectable<ApiKey>;
|
|
@ -0,0 +1,4 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getApiKeyByHash = (hash: string) =>
|
||||
db.selectFrom('ApiKey').selectAll().where('hashedKey', '=', hash).executeTakeFirst();
|
|
@ -0,0 +1,11 @@
|
|||
import { hashAPIKey } from '../../utils/apiKey';
|
||||
import type { ApiKeyType } from '../entities/types';
|
||||
|
||||
export const getApiKeyService = async (
|
||||
{ getApiKeyByHash }: { getApiKeyByHash: (key: string) => Promise<ApiKeyType | undefined> },
|
||||
apiKey: string,
|
||||
) => {
|
||||
const strippedApiKey = `${apiKey}`.replace(process.env.API_KEY_PREFIX || 'cal_', '');
|
||||
const hashedKey = hashAPIKey(strippedApiKey);
|
||||
return await getApiKeyByHash(hashedKey);
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
import type { AutoloadPluginOptions } from '@fastify/autoload';
|
||||
import AutoLoad from '@fastify/autoload';
|
||||
import type { FastifyPluginAsync, FastifyServerOptions } from 'fastify';
|
||||
import { join } from 'path';
|
||||
|
||||
export interface AppOptions extends FastifyServerOptions, Partial<AutoloadPluginOptions> {}
|
||||
// Pass --options via CLI arguments in command to enable these options.
|
||||
const options: AppOptions = {};
|
||||
|
||||
const app: FastifyPluginAsync<AppOptions> = async (fastify, opts): Promise<void> => {
|
||||
// Place here your custom code!
|
||||
|
||||
// Do not touch the following lines
|
||||
|
||||
// This loads all plugins defined in plugins
|
||||
// those should be support plugins that are reused
|
||||
// through your application
|
||||
void fastify.register(AutoLoad, {
|
||||
dir: join(__dirname, 'plugins'),
|
||||
options: opts,
|
||||
});
|
||||
|
||||
// This loads all plugins defined in routes
|
||||
// define your routes in one of these
|
||||
void fastify.register(AutoLoad, {
|
||||
dir: join(__dirname, 'routes'),
|
||||
options: opts,
|
||||
});
|
||||
};
|
||||
|
||||
export default app;
|
||||
export { app, options };
|
|
@ -0,0 +1,4 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getUserAvailability = (userId: number) =>
|
||||
db.selectFrom('Availability').selectAll().where('userId', '=', userId).executeTakeFirst();
|
|
@ -0,0 +1,44 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const createBooking = async ({
|
||||
name,
|
||||
email,
|
||||
timeZone,
|
||||
}: {
|
||||
name: string;
|
||||
email: string;
|
||||
timeZone: string;
|
||||
}) => {
|
||||
await db
|
||||
.insertInto('Attendee')
|
||||
.values({
|
||||
id: 6969,
|
||||
email: 'sahalrajiv690000000@gmail.com',
|
||||
name: 'Ryukeeeeee',
|
||||
timeZone: 'Europe/London',
|
||||
bookingId: 16,
|
||||
locale: 'en',
|
||||
})
|
||||
.execute();
|
||||
|
||||
// db.insertInto('Booking')
|
||||
// .values({
|
||||
// responses: {
|
||||
// email: '{{$randomExampleEmail}}',
|
||||
// name: '{{$randomFullName}}',
|
||||
// notes: '{{$randomCatchPhrase}}',
|
||||
// guests: [],
|
||||
// phone: '{{$randomPhoneNumber}}',
|
||||
// },
|
||||
// start: '{{start}}',
|
||||
// end: '{{end}}',
|
||||
// eventTypeId: 3,
|
||||
// timeZone: 'America/Mazatlan',
|
||||
// language: 'en',
|
||||
// location: '',
|
||||
// metadata: {},
|
||||
// hasHashedBookingLink: false,
|
||||
// hashedLink: null,
|
||||
// })
|
||||
// .executeTakeFirst();
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getAllBooking = async () => {
|
||||
return await db.selectFrom('Booking').selectAll().execute();
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getBookingById = async (id: number) => {
|
||||
return await db.selectFrom('Booking').selectAll().where('id', '=', id).executeTakeFirst();
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getAllEventTypes = async () => {
|
||||
return await db.selectFrom('EventType').selectAll().execute();
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getEventTypeById = async (id: number) => {
|
||||
return await db
|
||||
.selectFrom('EventType')
|
||||
.select(['userId', 'title', 'description', 'length', 'hidden'])
|
||||
.where('id', '=', id)
|
||||
.executeTakeFirst();
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
import { Kysely, PostgresDialect } from 'kysely';
|
||||
import type { DB } from 'kysely-codegen';
|
||||
// this is the Database interface we defined earlier
|
||||
import { Pool } from 'pg';
|
||||
|
||||
export const db = (function () {
|
||||
const dialect = new PostgresDialect({
|
||||
pool: new Pool({
|
||||
database: 'calendso',
|
||||
host: 'localhost',
|
||||
user: 'postgres',
|
||||
password: '',
|
||||
ssl: false,
|
||||
port: 5450,
|
||||
max: 10,
|
||||
}),
|
||||
});
|
||||
return new Kysely<DB>({
|
||||
dialect,
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,16 @@
|
|||
# Plugins Folder
|
||||
|
||||
Plugins define behavior that is common to all the routes in your
|
||||
application. Authentication, caching, templates, and all the other cross
|
||||
cutting concerns should be handled by plugins placed in this folder.
|
||||
|
||||
Files in this folder are typically defined through the
|
||||
[`fastify-plugin`](https://github.com/fastify/fastify-plugin) module,
|
||||
making them non-encapsulated. They can define decorators and set hooks
|
||||
that will then be used in the rest of your application.
|
||||
|
||||
Check out:
|
||||
|
||||
* [The hitchhiker's guide to plugins](https://www.fastify.io/docs/latest/Guides/Plugins-Guide/)
|
||||
* [Fastify decorators](https://www.fastify.io/docs/latest/Reference/Decorators/).
|
||||
* [Fastify lifecycle](https://www.fastify.io/docs/latest/Reference/Lifecycle/).
|
|
@ -0,0 +1,40 @@
|
|||
import { getApiKeyByHash } from '../api-keys/repository/getApiKeyByHash';
|
||||
import { getApiKeyService } from '../api-keys/services/getApiKey';
|
||||
import { getUserById } from '../users/repository/getUserById';
|
||||
import { dateNotInPast } from '../utils/date';
|
||||
import fp from 'fastify-plugin';
|
||||
|
||||
export default fp(async (fastify, opts) => {
|
||||
fastify.addHook<{ Querystring: { apiKey?: string } }>('preHandler', async (request, reply) => {
|
||||
// Check for authentication here
|
||||
const { apiKey } = request.query;
|
||||
|
||||
if (!apiKey) {
|
||||
return reply.code(401).send({ error: 'Unauthorized' });
|
||||
}
|
||||
|
||||
const key = await getApiKeyService({ getApiKeyByHash }, apiKey);
|
||||
|
||||
if (!key) {
|
||||
return reply.code(401).send({ error: 'Your apiKey is not valid' });
|
||||
}
|
||||
|
||||
if (key.expiresAt && dateNotInPast(key.expiresAt)) {
|
||||
return reply.code(401).send({ error: 'This apiKey is expired' });
|
||||
}
|
||||
|
||||
if (!key.userId) return reply.code(404).send({ error: 'No user found for this apiKey' });
|
||||
|
||||
const user = await getUserById(key.userId);
|
||||
if (user) {
|
||||
request.user = { ...user, id: key.userId, isAdmin: user.role === 'ADMIN' };
|
||||
}
|
||||
return;
|
||||
});
|
||||
});
|
||||
|
||||
declare module 'fastify' {
|
||||
export interface FastifyRequest {
|
||||
user: Awaited<ReturnType<typeof getUserById>> & { isAdmin: boolean; id: number };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import type { SensibleOptions } from '@fastify/sensible';
|
||||
import sensible from '@fastify/sensible';
|
||||
import fp from 'fastify-plugin';
|
||||
|
||||
/**
|
||||
* This plugins adds some utilities to handle http errors
|
||||
*
|
||||
* @see https://github.com/fastify/fastify-sensible
|
||||
*/
|
||||
export default fp<SensibleOptions>(async (fastify) => {
|
||||
fastify.register(sensible);
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
import fp from 'fastify-plugin';
|
||||
|
||||
export interface SupportPluginOptions {
|
||||
example?: string;
|
||||
}
|
||||
|
||||
// The use of fastify-plugin is required to be able
|
||||
// to export the decorators to the outer scope
|
||||
export default fp<SupportPluginOptions>(async (fastify, opts) => {
|
||||
fastify.decorate('someSupport', function () {
|
||||
return 'hugs';
|
||||
});
|
||||
});
|
||||
|
||||
// When using .decorate you have to specify added properties for Typescript
|
||||
declare module 'fastify' {
|
||||
export interface FastifyInstance {
|
||||
someSupport(): string;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
# Routes Folder
|
||||
|
||||
Routes define endpoints within your application. Fastify provides an
|
||||
easy path to a microservice architecture, in the future you might want
|
||||
to independently deploy some of those.
|
||||
|
||||
In this folder you should define all the routes that define the endpoints
|
||||
of your web application.
|
||||
Each service is a [Fastify
|
||||
plugin](https://www.fastify.io/docs/latest/Reference/Plugins/), it is
|
||||
encapsulated (it can have its own independent plugins) and it is
|
||||
typically stored in a file; be careful to group your routes logically,
|
||||
e.g. all `/users` routes in a `users.js` file. We have added
|
||||
a `root.js` file for you with a '/' root added.
|
||||
|
||||
If a single file become too large, create a folder and add a `index.js` file there:
|
||||
this file must be a Fastify plugin, and it will be loaded automatically
|
||||
by the application. You can now add as many files as you want inside that folder.
|
||||
In this way you can create complex routes within a single monolith,
|
||||
and eventually extract them.
|
||||
|
||||
If you need to share functionality between routes, place that
|
||||
functionality into the `plugins` folder, and share it via
|
||||
[decorators](https://www.fastify.io/docs/latest/Reference/Decorators/).
|
|
@ -0,0 +1,20 @@
|
|||
import { getAllBooking } from '../../booking/repository/getAllBooking';
|
||||
import { getBookingById } from '../../booking/repository/getBookingById';
|
||||
import type { FastifyPluginAsync } from 'fastify';
|
||||
|
||||
const get: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
|
||||
fastify.get('/', async (request, reply) => {
|
||||
const booking = getAllBooking();
|
||||
|
||||
return booking;
|
||||
});
|
||||
|
||||
fastify.get<{ Params: { id: number } }>('/:id', async (request, reply) => {
|
||||
const { id } = request.params;
|
||||
const booking = getBookingById(id);
|
||||
|
||||
return booking;
|
||||
});
|
||||
};
|
||||
|
||||
export default get;
|
|
@ -0,0 +1,24 @@
|
|||
import { createBooking } from '../../booking/repository/createBooking';
|
||||
import type { FastifyPluginAsync } from 'fastify';
|
||||
|
||||
const schema = {
|
||||
body: {
|
||||
properties: {
|
||||
username: { type: 'string' },
|
||||
},
|
||||
required: ['username'],
|
||||
},
|
||||
};
|
||||
|
||||
const post: FastifyPluginAsync = async (fastify, opts) => {
|
||||
fastify.post<{ Params: { id: number } }>('/post/:id', { schema }, async (request, reply) => {
|
||||
const { id } = request.params;
|
||||
const book = createBooking({ id });
|
||||
|
||||
console.log(book);
|
||||
|
||||
return 'Booking created successfully';
|
||||
});
|
||||
};
|
||||
|
||||
export default post;
|
|
@ -0,0 +1,24 @@
|
|||
import { getAllEventTypes } from '../../eventType/repository/getAllEventTypes';
|
||||
import { getEventTypeById } from '../../eventType/repository/getEventTypeById';
|
||||
import type { FastifyPluginAsync } from 'fastify';
|
||||
|
||||
const get: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
|
||||
fastify.get('/', async (request, reply) => {
|
||||
const eventType = getAllEventTypes();
|
||||
|
||||
return eventType;
|
||||
});
|
||||
|
||||
fastify.get<{ Params: { id: number } }>('/:id', async (request, reply) => {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
const eventTypes = getEventTypeById(id);
|
||||
|
||||
return eventTypes;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default get;
|
|
@ -0,0 +1,96 @@
|
|||
import type { FastifyPluginAsync } from 'fastify';
|
||||
|
||||
// const optsss = {
|
||||
// schema: {
|
||||
// body: {
|
||||
// type: 'object',
|
||||
// properties: {
|
||||
// someKey: { type: 'string' },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
// const bodyJsonSchema = {
|
||||
// type: 'object',
|
||||
// required: ['requiredKey'],
|
||||
// properties: {
|
||||
// someKey: { type: 'string' },
|
||||
// someOtherKey: { type: 'number' },
|
||||
// requiredKey: {
|
||||
// type: 'array',
|
||||
// maxItems: 3,
|
||||
// items: { type: 'integer' },
|
||||
// },
|
||||
// nullableKey: { type: ['number', 'null'] }, // or { type: 'number', nullable: true }
|
||||
// multipleTypesKey: { type: ['boolean', 'number'] },
|
||||
// multipleRestrictedTypesKey: {
|
||||
// oneOf: [
|
||||
// { type: 'string', maxLength: 5 },
|
||||
// { type: 'number', minimum: 10 },
|
||||
// ],
|
||||
// },
|
||||
// enumKey: {
|
||||
// type: 'string',
|
||||
// enum: ['John', 'Foo'],
|
||||
// },
|
||||
// notTypeKey: {
|
||||
// not: { type: 'array' },
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
// const queryStringJsonSchema = {
|
||||
// type: 'object',
|
||||
// properties: {
|
||||
// name: { type: 'string' },
|
||||
// excitement: { type: 'integer' },
|
||||
// },
|
||||
// };
|
||||
|
||||
// const paramsJsonSchema = {
|
||||
// type: 'object',
|
||||
// properties: {
|
||||
// par1: { type: 'string' },
|
||||
// par2: { type: 'number' },
|
||||
// },
|
||||
// };
|
||||
|
||||
// const headersJsonSchema = {
|
||||
// type: 'object',
|
||||
// properties: {
|
||||
// 'x-foo': { type: 'string' },
|
||||
// },
|
||||
// required: ['x-foo'],
|
||||
// };
|
||||
|
||||
// const schema = {
|
||||
// body: bodyJsonSchema,
|
||||
// querystring: queryStringJsonSchema,
|
||||
// params: paramsJsonSchema,
|
||||
// headers: headersJsonSchema,
|
||||
// };
|
||||
|
||||
const schema = {
|
||||
body: {
|
||||
properties: {
|
||||
username: { type: 'string' },
|
||||
age: { type: 'number' },
|
||||
},
|
||||
required: ['age'],
|
||||
},
|
||||
};
|
||||
|
||||
const post: FastifyPluginAsync = async (fastify, opts) => {
|
||||
fastify.post('/', { schema }, async (request, reply) => {
|
||||
try {
|
||||
fastify.log.info('Hiiiiiii');
|
||||
|
||||
return `Hiii`;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default post;
|
|
@ -0,0 +1,9 @@
|
|||
import type { FastifyPluginAsync } from 'fastify';
|
||||
|
||||
const root: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
|
||||
fastify.get('/', async function (request, reply) {
|
||||
return { root: true };
|
||||
});
|
||||
};
|
||||
|
||||
export default root;
|
|
@ -0,0 +1,28 @@
|
|||
import { getAllSchedules } from '../../schedule/repository/getAllSchedules';
|
||||
import { getScheduleById } from '../../schedule/repository/getScheduleById';
|
||||
import type { FastifyPluginAsync } from 'fastify';
|
||||
|
||||
const get: FastifyPluginAsync = async (fastify, opts) => {
|
||||
fastify.get('/', async (request, reply) => {
|
||||
try {
|
||||
const schedule = getAllSchedules();
|
||||
|
||||
return schedule;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
fastify.get<{ Params: { id: number } }>('/:id', async (request, reply) => {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
const schedule = getScheduleById(id);
|
||||
|
||||
return schedule;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default get;
|
|
@ -0,0 +1,19 @@
|
|||
import { getTeamById } from '../../teams/repository/getTeamById';
|
||||
// import * as TeamRepo from '../teams/repository/getTeamById';
|
||||
import type { FastifyPluginAsync } from 'fastify';
|
||||
|
||||
const get: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
|
||||
fastify.get<{ Params: { id: number } }>('/:id', async (request, reply) => {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
const team = await getTeamById(id);
|
||||
|
||||
return team;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return 'error';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default get;
|
|
@ -0,0 +1,37 @@
|
|||
import * as UserRepo from '../../users/repository';
|
||||
import type { FastifyPluginAsync } from 'fastify';
|
||||
|
||||
const get: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
|
||||
fastify.register(import('../../plugins/auth'));
|
||||
|
||||
fastify.get<{ Params: { id: number } }>('/', async function (request, reply) {
|
||||
try {
|
||||
return `Users`;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return 'error';
|
||||
}
|
||||
});
|
||||
|
||||
fastify.get('/me', async function (request, reply) {
|
||||
try {
|
||||
return await UserRepo.getUserById(request.user.id);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return 'error';
|
||||
}
|
||||
});
|
||||
|
||||
fastify.get<{ Params: { id: number } }>('/:id', async function (request, reply) {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
const user = await UserRepo.getUserById(id);
|
||||
return `this is an getUserById: ${user?.name}`;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return 'error';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default get;
|
|
@ -0,0 +1,5 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getAllSchedules = async () => {
|
||||
return await db.selectFrom('Schedule').selectAll().execute();
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getScheduleById = async (id: number) => {
|
||||
return await db.selectFrom('Schedule').selectAll().where('id', '=', id).executeTakeFirst();
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getTeamById = async (id: number) => {
|
||||
return await db
|
||||
.selectFrom('Team')
|
||||
.select(['name', 'slug', 'bio', 'timeZone'])
|
||||
.where('id', '=', id)
|
||||
.executeTakeFirst();
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
import { db } from '../../lib/db';
|
||||
|
||||
export const getUserById = async (id: number) => {
|
||||
return await db
|
||||
.selectFrom('users')
|
||||
.select(['name', 'email', 'role'])
|
||||
.where('id', '=', id)
|
||||
.executeTakeFirst();
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export { getUserById } from './getUserById';
|
|
@ -0,0 +1,4 @@
|
|||
import { createHash } from 'crypto';
|
||||
|
||||
export const hashAPIKey = (apiKey: string): string =>
|
||||
createHash('sha256').update(apiKey).digest('hex');
|
|
@ -0,0 +1,6 @@
|
|||
export const dateNotInPast = function (date: Date) {
|
||||
const now = new Date();
|
||||
if (now.setHours(0, 0, 0, 0) > date.setHours(0, 0, 0, 0)) {
|
||||
return true;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
// This file contains code that we reuse between our tests.
|
||||
import * as helper from 'fastify-cli/helper.js';
|
||||
import * as path from 'path';
|
||||
import type * as tap from 'tap';
|
||||
|
||||
export type Test = (typeof tap)['Test']['prototype'];
|
||||
|
||||
const AppPath = path.join(__dirname, '..', 'src', 'app.ts');
|
||||
|
||||
// Fill in this config with all the configurations
|
||||
// needed for testing the application
|
||||
async function config() {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Automatically build and tear down our instance
|
||||
async function build(t: Test) {
|
||||
// you can set all the options supported by the fastify CLI command
|
||||
const argv = [AppPath];
|
||||
|
||||
// fastify-plugin ensures that all decorators
|
||||
// are exposed for testing purposes, this is
|
||||
// different from the production setup
|
||||
const app = await helper.build(argv, await config());
|
||||
|
||||
// Tear down our app after we are done
|
||||
t.teardown(() => void app.close());
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
export { config, build };
|
|
@ -0,0 +1,11 @@
|
|||
import Support from '../../src/plugins/support';
|
||||
import Fastify from 'fastify';
|
||||
import { test } from 'tap';
|
||||
|
||||
test('support works standalone', async (t) => {
|
||||
const fastify = Fastify();
|
||||
void fastify.register(Support);
|
||||
await fastify.ready();
|
||||
|
||||
t.equal(fastify.someSupport(), 'hugs');
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
import { build } from '../helper';
|
||||
import { test } from 'tap';
|
||||
|
||||
test('example is loaded', async (t) => {
|
||||
const app = await build(t);
|
||||
|
||||
const res = await app.inject({
|
||||
url: '/example',
|
||||
});
|
||||
|
||||
t.equal(res.payload, 'this is an example');
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
import { build } from '../helper';
|
||||
import { test } from 'tap';
|
||||
|
||||
test('default root route', async (t) => {
|
||||
const app = await build(t);
|
||||
|
||||
const res = await app.inject({
|
||||
url: '/',
|
||||
});
|
||||
t.same(JSON.parse(res.payload), { root: true });
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["../src/**/*.ts", "**/*.ts"]
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "fastify-tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["./node_modules"]
|
||||
}
|
Loading…
Reference in New Issue