Skip to content

Commit

Permalink
Merge branch 'main' into nick_edithome
Browse files Browse the repository at this point in the history
  • Loading branch information
santhitak authored Mar 28, 2024
2 parents 93268fe + 7caf720 commit 619d53b
Show file tree
Hide file tree
Showing 32 changed files with 874 additions and 183 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pnpm wrangler d1 execute dev-certifine --local --file=db/schema/schema.sql
pnpm nx serve api-auth

VITE_GOOGLE_REDIRECT_URI=http://localhost:8788/api/auth/google/callback pnpm nx build web
$Env:VITE_GOOGLE_REDIRECT_URI=http://localhost:8788/api/auth/google/callback pnpm nx build web
pnpm wrangler pages dev dist/apps/web/deploy
```

Expand Down
204 changes: 187 additions & 17 deletions apps/api/auth/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { Hono } from 'hono';
import { D1Database } from '@cloudflare/workers-types';
import { D1Database, R2Bucket } from '@cloudflare/workers-types';
import { typeid } from 'typeid-js';

interface ResponseWrapper<T, E> {
data: T;
error: E;
}

const response = <T, E> (data: T, error ?: E): ResponseWrapper<T, E> => {
const response = <T, E>(data: T, error?: E): ResponseWrapper<T, E> => {
return {
data,
error
error,
};
};

type Bindings = {
DB: D1Database;
}
BUCKET: R2Bucket;
};

const app = new Hono<{ Bindings: Bindings }>();

Expand Down Expand Up @@ -45,7 +46,7 @@ app.get('/users', async (c) => {
op.name 'provider',
oa.created_at 'createdAt',
oa.updated_at 'updatedAt'
FROM oauth_account as oa
FROM oauth_account as oa
JOIN user as u ON (oa.user_id = u.id)
JOIN oauth_provider as op ON (oa.oauth_provider_id = op.id)
WHERE u.id = ?1 AND oa.deleted_at IS NULL
Expand Down Expand Up @@ -74,11 +75,7 @@ interface User {
deleted_at: number;
}

type CreateUserParams = Pick<User,
| 'username'
| 'firstName'
| 'lastName'
>;
type CreateUserParams = Pick<User, 'username' | 'firstName' | 'lastName'>;

interface CreateOAuthParams {
oaid: string;
Expand All @@ -105,10 +102,7 @@ app.post('/users', async (c) => {

const id = typeid('user').toString();

const results = await c.env.DB.batch([
createUserStatement.bind(id, body.username, body.firstName, body.lastName, Date.now()),
createOAuthAccountStatement.bind(body.oaid, id, body.provider, body.email, Date.now()),
]);
const results = await c.env.DB.batch([createUserStatement.bind(id, body.username, body.firstName, body.lastName, Date.now()), createOAuthAccountStatement.bind(body.oaid, id, body.provider, body.email, Date.now())]);

return c.json(response(results));
});
Expand All @@ -121,9 +115,7 @@ interface OAuthProvider {
deleted_at: number;
}

type CreateOAuthProviderParams = Pick<OAuthProvider,
| 'name'
>;
type CreateOAuthProviderParams = Pick<OAuthProvider, 'name'>;

app.get('/providers', async (c) => {
const findOAuthProviderStatement = c.env.DB.prepare(`
Expand Down Expand Up @@ -155,4 +147,182 @@ app.post('/providers', async (c) => {
return c.json(response(result));
});

interface Template {
id: string;
userId: string;
name: string;
createdAt: number;
updatedAt: number;
deletedAt: number;
}

type CreateTemplateParams = Pick<Template, 'name' | 'userId'>;

type FindTemplateParams = Pick<Template, 'userId'>;

interface TemplateDataParams {
data: JSON;
}

type UpdateTemplateParams = Pick<Template, 'name'>;

type CreateTemplateRequest = CreateTemplateParams & TemplateDataParams;
type UpdateTemplateRequest = UpdateTemplateParams & TemplateDataParams;

app.post('/templates', async (c) => {
const body = await c.req.json<CreateTemplateRequest>();

const id = typeid('tmpl').toString();

const key = ['templates', body.userId, id].join('/');

const createTemplateStatement = c.env.DB.prepare(`
INSERT INTO template (id, user_id, name, created_at)
VALUES (?1, ?2, ?3, ?4)
`);

try {
await c.env.BUCKET.put(key, JSON.stringify(body.data));

const { results } = await createTemplateStatement.bind(id, body.userId, body.name, Date.now()).run();

return c.json(response(results));
} catch (e) {
return c.json(response(null, e));
}
});

app.get('/templates/:userId', async (c) => {
const { userId } = c.req.param() as FindTemplateParams;

const getTemplateStatement = c.env.DB.prepare(`
SELECT
t.id,
t.user_id 'userId',
t.key,
t.created_at 'createdAt',
t.updated_at 'updatedAt'
FROM template as t
WHERE t.user_id = ?1 AND t.deleted_at NOT NULL
`);

const { results } = await getTemplateStatement.bind(userId).all<Template>();

results.map((template) => {
template.id;
});

return c.json(response(results));
});

app.get('/templates/:userId/:id', async (c) => {
const { userId, id } = c.req.param();
const key = ['templates', userId, id].join('/');

try {
const objectRef = await c.env.BUCKET.get(key);
const data = objectRef.json();

return c.json(response(data));
} catch (e) {
return c.json(response(null, e));
}
});

app.put('/templates/:userId/:id', async (c) => {
const { userId, id } = c.req.param();
const { data, name } = (await c.req.json()) as UpdateTemplateRequest;

const key = ['templates', userId, id].join('/');

const updateTemplateStatement = c.env.DB.prepare(`
UPDATE template
SET name = ?1
WHERE id = ?2 AND deleted_at NOT NULL
`);

try {
await c.env.BUCKET.put(key, JSON.stringify(data));

const { results } = await updateTemplateStatement.bind(name, id).run();

return c.json(response(results));
} catch (e) {
return c.json(response(null, e));
}
});

interface Project {
id: string;
userId: string;
templateId: string;
name: string;
createdAt: number;
updatedAt: number;
deletedAt: number;
}

type CreateProjectRequest = Pick<Project, 'userId' | 'templateId' | 'name'>;

type FindProjectRequest = Pick<Project, 'userId'>;

type UpdateProjectRequest = Pick<Project, 'id' | 'name'>;

app.post('/projects', async (c) => {
const body = await c.req.json<CreateProjectRequest>();

const createProjectStatement = c.env.DB.prepare(`
INSERT INTO project (id, user_id, template_id, name, created_at)
VALUES (?1, ?2, ?3, ?4, ?5)
`);

const id = typeid('proj').toString();

const result = createProjectStatement.bind(id, body.userId, body.templateId, body.name, Date.now()).run();

return c.json(response(result));
});

app.get('/projects', async (c) => {
const { userId } = c.req.query() as FindProjectRequest;

const getProjectStatement = c.env.DB.prepare(`
SELECT
p.id,
p.user_id 'userId',
p.template_id 'templateId',
p.created_at 'createdAt',
p.updated_at 'updatedAt'
FROM project as p
WHERE p.user_id = ?1 AND p.deleted_at NOT NULL
`);

const { results } = await getProjectStatement.bind(userId).all<Project>();

return c.json(response(results));
});

app.patch('/projects', async (c) => {
const body = await c.req.json<UpdateProjectRequest>();

const updateProjectStatement = c.env.DB.prepare(`
UPDATE project
SET name = ?1
WHERE id = ?2 AND deleted_at NOT NULL
`);

const { results } = await updateProjectStatement.bind(body.name, body.id).run();

return c.json(response(results));
});

// interface Generate {
// id: string;
// projectId: string;
// key: string;
// args: string;
// createdAt: number;
// deletedAt: number;
// }

export default app;
8 changes: 7 additions & 1 deletion apps/web/src/root.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { component$, useServerData, useStyles$ } from '@builder.io/qwik';
import { component$, useServerData, useStyles$, useVisibleTask$ } from '@builder.io/qwik';
import { RouterHead } from './components/base';

import styles from '@producktivity/ui/style.css?inline';
import { initFlowbite } from 'flowbite';

import { QwikCityProvider, RouterOutlet, ServiceWorkerRegister } from '@builder.io/qwik-city';

export default component$(() => {
useStyles$(styles);

useVisibleTask$(() => {
initFlowbite();
});

const nonce = useServerData<string | undefined>('nonce');

return (
Expand Down
13 changes: 10 additions & 3 deletions apps/web/src/routes/dashboard/[slug]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { Box } from '@producktivity/ui';
import { DashboardTab } from '../components/dashboard-tab';
import { ProjectTab } from '../components/project-tab';
import { DashboardTab } from '../components/dashboard/dashboard-tab';
import { ProjectTab } from '../components/project/project-tab';
import { TemplateTab } from '../components/template-tab';
import { useLocation } from '@builder.io/qwik-city';
import { routeLoader$, useLocation } from '@builder.io/qwik-city';
import { component$ } from '@builder.io/qwik';
import { ProjectFormProps } from '../components/project/create-project-modal';
import { type InitialValues } from '@modular-forms/qwik';

export const useFormLoader = routeLoader$<InitialValues<ProjectFormProps>>(() => ({
projectName: '',
templateId: '',
}));

export default component$(() => {
const loc = useLocation();
Expand Down
Loading

0 comments on commit 619d53b

Please sign in to comment.