Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Area API + getDoc without markdown contents #75

Merged
merged 20 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"plugins": ["@typescript-eslint", "prettier"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"rules": {
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": "off"
},
Expand Down
82 changes: 66 additions & 16 deletions lib/wiki.stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import * as lambda from 'aws-cdk-lib/aws-lambda';
import { config } from 'dotenv';
import { LPStack, StackInfo } from './util/LPStack';
import { ApiService, IApiResources } from './templates/apigateway';
import * as s3 from 'aws-cdk-lib/aws-s3';
// import * as s3 from 'aws-cdk-lib/aws-s3';
import { Role, ServicePrincipal, PolicyStatement } from 'aws-cdk-lib/aws-iam';
config();

export const WIKI_STACK_INFO: StackInfo = { NAME: 'wiki-stack' };
export const WIKI_STACK_INFO: StackInfo = { NAME: 'hub-wiki-stack' };

export class WikiStack extends LPStack {
public STACK_INFO: StackInfo = WIKI_STACK_INFO;
Expand All @@ -27,16 +27,21 @@ export class WikiStack extends LPStack {
policyStatement.addResources('arn:aws:s3:::lp-doc');
role.addToPolicy(policyStatement);

const myBucket = new s3.Bucket(this, 'MyBucket', {
// S3 bucket configuration
});
// const myBucket = new s3.Bucket(this, 'MyBucket', {
// // S3 bucket configuration
// });

const lambdaConfigs = {
runtime: lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
environment: {
BUCKET_NAME: myBucket.bucketName,
BUCKET_ARN: myBucket.bucketArn,
BUCKET_NAME: process.env.BUCKET_NAME || '',
BUCKET_ARN: process.env.BUCKET_NAME || '',
ACCESS_KEY: process.env.IAM_ACCESS_KEY || '',
SECRET_ACCESS_KEY: process.env.IAM_SECRET_ACCESS_KEY || '',
DATABASE_USERNAME: process.env.DATABASE_USERNAME || '',
DATABASE_PASSWORD: process.env.DATABASE_PASSWORD || '',
DATABASE_HOST: process.env.DATABASE_HOST || '',
},
role: role,
};
Expand All @@ -45,15 +50,61 @@ export class WikiStack extends LPStack {

const apiResources: IApiResources = {
subresources: {
docs: {
areas: {
endpoints: {
GET: {
id: 'getAreas',
path: `${baseLambdaDir}/getAreas`,
},
POST: {
id: 'createArea',
path: `${baseLambdaDir}/createArea`,
},
},
subresources: {
'{area}': {
'{areaid}': {
endpoints: {
GET: {
id: 'getArea',
path: `${baseLambdaDir}/getArea`,
},
DELETE: {
id: 'deleteArea',
path: `${baseLambdaDir}/deleteArea`,
},
PATCH: {
id: 'updateArea',
path: `${baseLambdaDir}/updateArea`,
},
},
subresources: {
'{doc}': {
endpoints: {
GET: {
id: 'getDoc',
path: `${baseLambdaDir}/getdoc`,
doc: {
subresources: {
'{docid}': {
endpoints: {
DELETE: {
armintalaie marked this conversation as resolved.
Show resolved Hide resolved
id: 'deleteDoc',
path: `${baseLambdaDir}/deletedoc`,
},
GET: {
id: 'getDoc',
path: `${baseLambdaDir}/getdoc`,
},
PUT: {
id: 'putDoc',
path: `${baseLambdaDir}/putdoc`,
},
},
// subresources: {
// 'content': {
// endpoints: {
// GET: {
// id: 'getContent',
// path: `${baseLambdaDir}/getContent`,
// },
// },
// },
// },
},
},
},
Expand All @@ -68,8 +119,7 @@ export class WikiStack extends LPStack {
this,
apiResources,
`${WIKI_STACK_INFO.NAME}-API`,
lambdaConfigs,
myBucket
lambdaConfigs
);
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"start:local:api": "sam local start-api -t ./cdk.out/team-stack.template.json --port 3003 ",
"invoke:lambda": "sam local invoke -t ./cdk.out/$npm_config_stack.template.json -e $npm_config_event ${npm_config_warm-containers=LAZY}",
"start:local:lambdas": "sam local start-lambda -t ./cdk.out/$npm_config_stack.template.json ${npm_config_port:3000} ${npm_config_warm-containers=LAZY}",
"db:up": "esbuild ./resources/**/*.ts --entry-names=[dir]/[name]/index --bundle --platform=node --target=node16.14 --outdir=./dist/migrations && node ./dist/migrations/setup/index.js"
"db:up": "esbuild resources/database/setup.ts --entry-names=[dir]/[name]/index --bundle --platform=node --target=node16.14 --outdir=./dist/migrations && node ./dist/migrations/setup/index.js"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.363.0",
Expand Down
37 changes: 37 additions & 0 deletions resources/database/migrations/1710395365.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
-- Create Area table
CREATE TABLE IF NOT EXISTS Area (
armintalaie marked this conversation as resolved.
Show resolved Hide resolved
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
description VARCHAR(255),
numberOfDocs INT,
armintalaie marked this conversation as resolved.
Show resolved Hide resolved
lastUpdatedDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
parentAreaID INT
);

-- Create Documents table
CREATE TABLE IF NOT EXISTS Documents (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
areaID INT,
armintalaie marked this conversation as resolved.
Show resolved Hide resolved
title VARCHAR(255),
docLink VARCHAR(255),
lastEditedUser VARCHAR(255),
creationDate DATE,
lastUpdatedDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
-- FOREIGN KEY (areaID) REFERENCES Area(id)
);

-- Create Tags table
CREATE TABLE IF NOT EXISTS Tags (
id INT AUTO_INCREMENT PRIMARY KEY,
tagName VARCHAR(255) UNIQUE
);

-- Create junction table to represent the many-to-many relationship between Documents and Tags
CREATE TABLE IF NOT EXISTS DocumentTags (
docID INT,
tagID INT,
PRIMARY KEY (docID, tagID)
-- FOREIGN KEY (docID) REFERENCES Documents(id),
-- FOREIGN KEY (tagID) REFERENCES Tags(id)
KeveenWong marked this conversation as resolved.
Show resolved Hide resolved
);
46 changes: 37 additions & 9 deletions resources/database/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import * as path from 'path';
import * as fs from 'fs';
import dotenv from 'dotenv';
import mysql, { Connection } from 'mysql2';
console.log('Connected to PlanetScale!');
dotenv.config();

const DATABASE_META_NAME = 'meta';
const DATABASE_NAME = 'cosmic-dev';
const MIGRATION_PATH = './resources/database/migrations';

Expand Down Expand Up @@ -63,11 +63,10 @@ const resetDatabase = async (connection: Connection): Promise<void> => {
const tables = await query(connection, `SHOW TABLES IN ??`, [
database.Database,
]);
console.log(tables);
for (const table of tables) {
const tableName = Object.values(table)[0];
await query(connection, `DROP TABLE ??`, [tableName]);
}

const tableNames = tables.map((table) => Object.values(table)[0]);
const queryStr = `DROP TABLE ${tableNames.join(', ')}`;
await query(connection, queryStr);
}
}
};
Expand All @@ -85,21 +84,50 @@ async function runMigrations(connection: Connection): Promise<void> {
const lastMigration = res || [];

if (lastMigration.length > 0) {
const lastMigrationTimestamp = lastMigration[0].timestamp;
const lastMigrationTimestamp = Math.floor(
lastMigration[0].timestamp.getTime() / 1000
);
console.log(
chalk.blue('INFO: ') +
'Last migration timestamp: ' +
chalk.bold.underline(lastMigrationTimestamp)
);

files = files.filter((file) => {
const fileParts = file.split('.');
const fileTimestamp = fileParts[0];
return fileTimestamp > lastMigrationTimestamp;
return Number(fileTimestamp) > lastMigrationTimestamp;
});
}

if (files.length === 0) {
console.log(chalk.blue('INFO: ') + 'No new migrations to run');
return;
}

console.log(
chalk.blue('INFO: ') +
'Number of migrations to run: ' +
chalk.bold.underline(files.length)
);

const currentDB = await query(connection, 'SELECT database() AS db');
console.log(
chalk.blue('INFO: ') +
'Database selected: ' +
chalk.bold.underline(currentDB[0].db)
);
await migrate(connection, files);
console.log(chalk.greenBright('SUCCESS: ') + 'Migrations complete');
await query(
connection,
`INSERT INTO migrations (status) VALUES ('success')`
);

console.log(
chalk.greenBright('SUCCESS: ') +
'Migrations table updated with new migrations'
);
}

async function migrate(connection: Connection, files: string[]): Promise<void> {
Expand Down Expand Up @@ -167,7 +195,7 @@ const run = (): void => {
return;
}
const connection = mysql.createConnection(connectionUrl);
setUpDatabase(connection, true)
setUpDatabase(connection, false)
.then(() => {
console.log(chalk.bgGreen('Database setup completed'));
})
Expand Down
47 changes: 47 additions & 0 deletions src/util/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export interface Database {
team_term: TeamTermTable;
post: PostTable;
team_member: team_member;
Area: AreaTable;
Documents: DocumentsTable;
Tags: TagsTable;
DocumentTags: DocumentTagsTable;
}

export function getDatabase() {
Expand Down Expand Up @@ -188,3 +192,46 @@ export interface team_member {
export type TeamMember = Selectable<team_member>;
export type NewTeamMember = Insertable<team_member>;
export type UpdateTeamMember = Updateable<team_member>;

export type AreaTable = {
id: Generated<number>;
name: string;
description: string;
accessLevel: number;
numberOfDocs: number;
lastUpdatedDate: Generated<Date>;
parentAreaID: number;
};

export type Area = Selectable<AreaTable>;
export type NewArea = Insertable<AreaTable>;
export type UpdateArea = Updateable<AreaTable>;

export type DocumentsTable = {
id: Generated<number>;
name: string;
areaID: number;
title: string;
docLink: string;
lastEditedUser: string;
creationDate: Date;
lastUpdatedDate: Generated<Date>;
};

export type Documents = Selectable<DocumentsTable>;
export type NewDocuments = Insertable<DocumentsTable>;
export type UpdateDocuments = Updateable<DocumentsTable>;

export type TagsTable = DictTable<string>;
export type Tags = Selectable<TagsTable>;
export type NewTags = Insertable<TagsTable>;
export type UpdateTags = Updateable<TagsTable>;

export type DocumentTagsTable = {
docID: number;
tagID: number;
};

export type DocumentTags = Selectable<DocumentTagsTable>;
export type NewDocumentTags = Insertable<DocumentTagsTable>;
export type UpdateDocumentTags = Updateable<DocumentTagsTable>;
3 changes: 2 additions & 1 deletion src/util/types/general.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Person } from '../db';
import { Person, Area } from '../db';

export interface IPagination {
limit: number;
offset: number;
}

export type IPersonQuery = Partial<Person> & IPagination;
export type IAreaQuery = Partial<Area> & IPagination;

export type Link = {
label: string;
Expand Down
11 changes: 11 additions & 0 deletions src/wiki/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## Example GET:

curl -X GET http://127.0.0.1:8000/docs/area/75504261:handbook/doc/objectives/

## Example PUT:

curl -X PUT -H "Content-Type: text/plain" --data-binary @docs/src/docs/handbook/objectives.md http://127.0.0.1:8000/docs/area/75504261:handbook/doc/objectives/

## Example DELETE:

curl -X DELETE http://127.0.0.1:8000/docs/area/75504261:handbook/doc/objectives/
Loading
Loading