diff --git a/package.json b/package.json index 5dc02a2..5e43122 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "format": "prettier --write \"./src/**/*.{ts,tsx}\"", "lint": "eslint", "stylelint": "stylelint \"./src/**/*.css\" --fix", - "seed": "node prisma/seed/init.mjs" + "seed": "npx prisma migrate reset --force & npx tsx ./prisma/seed/init.ts" }, "dependencies": { "@auth/prisma-adapter": "^2.7.4", diff --git a/prisma/README.md b/prisma/README.md index e22b785..e5548d5 100644 --- a/prisma/README.md +++ b/prisma/README.md @@ -1,6 +1,20 @@ # Prisma -TODO: 他のPRで`ts-node`が追加されるので、マージされ次第`package.json`の`seed`scriptコマンドを`node`から`ts-node`に変更し、`seed/init.mjs`を`seed/init.ts`にリネームする +## データベースに初期データを入れるとき + +同時にデータベースのリセットが行われます。 + +```bash +pnpm seed +``` + +## データベースの状態を確認するとき + +Web UIでデータベースに投入されているデータを確認することができます。 + +```bash +npx prisma studio +``` ## スキーマに変更を加えるとき @@ -18,15 +32,3 @@ TODO: 他のPRで`ts-node`が追加されるので、マージされ次第`packa ```bash npx prisma migrate reset ``` - -## データベースに初期データを入れるとき - -```bash -pnpm run seed -``` - -## データベースの状態を確認するとき - -```bash -npx prisma studio -``` diff --git a/prisma/seed/GFM.txt b/prisma/seed/GFM.txt new file mode 100644 index 0000000..2afa568 --- /dev/null +++ b/prisma/seed/GFM.txt @@ -0,0 +1,317 @@ +### Features + +- Support Standard Markdown / CommonMark and GFM(GitHub Flavored Markdown); +- Full-featured: Real-time Preview, Image (cross-domain) upload, Preformatted text/Code blocks/Tables insert, Code fold, Search replace, Read only, Themes, Multi-languages, L18n, HTML entities, Code syntax highlighting...; +- Markdown Extras : Support ToC (Table of Contents), Emoji, Task lists, @Links...; +- Compatible with all major browsers (IE8+), compatible Zepto.js and iPad; +- Support identification, interpretation, fliter of the HTML tags; +- Support TeX (LaTeX expressions, Based on KaTeX), Flowchart and Sequence Diagram of Markdown extended syntax; +- Support AMD/CMD (Require.js & Sea.js) Module Loader, and Custom/define editor plugins; + +# Editor.md + +![](https://pandao.github.io/editor.md/images/logos/editormd-logo-180x180.png) + +![](https://img.shields.io/github/stars/pandao/editor.md.svg) ![](https://img.shields.io/github/forks/pandao/editor.md.svg) ![](https://img.shields.io/github/tag/pandao/editor.md.svg) ![](https://img.shields.io/github/release/pandao/editor.md.svg) ![](https://img.shields.io/github/issues/pandao/editor.md.svg) ![](https://img.shields.io/bower/v/editor.md.svg) + + +**Table of Contents** + +[TOCM] + +[TOC] + +# H1 header +## H2 header +### H3 header +#### H4 header +##### H5 header +###### H6 header +# Heading 1 link [Heading link](https://github.com/pandao/editor.md "Heading link") +## Heading 2 link [Heading link](https://github.com/pandao/editor.md "Heading link") +### Heading 3 link [Heading link](https://github.com/pandao/editor.md "Heading link") +#### Heading 4 link [Heading link](https://github.com/pandao/editor.md "Heading link") Heading link [Heading link](https://github.com/pandao/editor.md "Heading link") +##### Heading 5 link [Heading link](https://github.com/pandao/editor.md "Heading link") +###### Heading 6 link [Heading link](https://github.com/pandao/editor.md "Heading link") + +## Headers (Underline) + +H1 Header (Underline) +============= + +H2 Header (Underline) +------------- + +### Characters + +---- + +~~Strikethrough~~ Strikethrough (when enable html tag decode.) +*Italic* _Italic_ +**Emphasis** __Emphasis__ +***Emphasis Italic*** ___Emphasis Italic___ + +Superscript: X2,Subscript: O2 + +**Abbreviation(link HTML abbr tag)** + +The HTML specification is maintained by the W3C. + +### Blockquotes + +> Blockquotes + +Paragraphs and Line Breaks + +> "Blockquotes Blockquotes", [Link](http://localhost/)。 + +### Links + +[Links](http://localhost/) + +[Links with title](http://localhost/ "link title") + +`` : + +[Reference link][id/name] + +[id/name]: http://link-url/ + +GFM a-tail link @pandao + +### Code Blocks (multi-language) & highlighting + +#### Inline code + +`$ npm install marked` + +#### Code Blocks (Indented style) + +Indented 4 spaces, like `
` (Preformatted Text).
+
+    
+    
+Code Blocks (Preformatted text):
+
+    | First Header  | Second Header |
+    | ------------- | ------------- |
+    | Content Cell  | Content Cell  |
+    | Content Cell  | Content Cell  |
+
+#### Javascript
+
+```javascript
+function test(){
+	console.log("Hello world!");
+}
+ 
+(function(){
+    var box = function(){
+        return box.fn.init();
+    };
+
+    box.prototype = box.fn = {
+        init : function(){
+            console.log('box.init()');
+
+			return this;
+        },
+
+		add : function(str){
+			alert("add", str);
+
+			return this;
+		},
+
+		remove : function(str){
+			alert("remove", str);
+
+			return this;
+		}
+    };
+    
+    box.fn.init.prototype = box.fn;
+    
+    window.box =box;
+})();
+
+var testBox = box();
+testBox.add("jQuery").remove("jQuery");
+```
+
+#### HTML code
+
+```html
+
+
+    
+        
+        Hello world!
+    
+    
+        

Hello world!

+ + +``` + +### Images + +Image: + +![](https://pandao.github.io/editor.md/examples/images/4.jpg) + +> Follow your heart. + +![](https://pandao.github.io/editor.md/examples/images/8.jpg) + +> 图为:厦门白城沙滩 Xiamen + +图片加链接 (Image + Link): + +[![](https://pandao.github.io/editor.md/examples/images/7.jpg)](https://pandao.github.io/editor.md/examples/images/7.jpg "李健首张专辑《似水流年》封面") + +> 图为:李健首张专辑《似水流年》封面 + +---- + +### Lists + +#### Unordered list (-) + +- Item A +- Item B +- Item C + +#### Unordered list (*) + +* Item A +* Item B +* Item C + +#### Unordered list (plus sign and nested) + ++ Item A ++ Item B + + Item B 1 + + Item B 2 + + Item B 3 ++ Item C + * Item C 1 + * Item C 2 + * Item C 3 + +#### Ordered list + +1. Item A +2. Item B +3. Item C + +---- + +### Tables + +First Header | Second Header +------------- | ------------- +Content Cell | Content Cell +Content Cell | Content Cell + +| First Header | Second Header | +| ------------- | ------------- | +| Content Cell | Content Cell | +| Content Cell | Content Cell | + +| Function name | Description | +| ------------- | ------------------------------ | +| `help()` | Display the help window. | +| `destroy()` | **Destroy your computer!** | + +| Item | Value | +| --------- | -----:| +| Computer | $1600 | +| Phone | $12 | +| Pipe | $1 | + +| Left-Aligned | Center Aligned | Right Aligned | +| :------------ |:---------------:| -----:| +| col 3 is | some wordy text | $1600 | +| col 2 is | centered | $12 | +| zebra stripes | are neat | $1 | + +---- + +#### HTML entities + +© & ¨ ™ ¡ £ +& < > ¥ € ® ± ¶ § ¦ ¯ « · + +X² Y³ ¾ ¼ × ÷ » + +18ºC " ' + +## Escaping for Special Characters + +\*literal asterisks\* + +## Markdown extras + +### GFM task list + +- [x] GFM task list 1 +- [x] GFM task list 2 +- [ ] GFM task list 3 + - [ ] GFM task list 3-1 + - [ ] GFM task list 3-2 + - [ ] GFM task list 3-3 +- [ ] GFM task list 4 + - [ ] GFM task list 4-1 + - [ ] GFM task list 4-2 + +### Emoji mixed :smiley: + +> Blockquotes :star: + +#### GFM task lists & Emoji & fontAwesome icon emoji & editormd logo emoji :editormd-logo-5x: + +- [x] :smiley: @mentions, :smiley: #refs, [links](), **formatting**, and tags supported :editormd-logo:; +- [x] list syntax required (any unordered or ordered list supported) :editormd-logo-3x:; +- [x] [ ] :smiley: this is a complete item :smiley:; +- [ ] []this is an incomplete item [test link](#) :fa-star: @pandao; +- [ ] [ ]this is an incomplete item :fa-star: :fa-gear:; + - [ ] :smiley: this is an incomplete item [test link](#) :fa-star: :fa-gear:; + - [ ] :smiley: this is :fa-star: :fa-gear: an incomplete item [test link](#); + +### TeX(LaTeX) + +$$E=mc^2$$ + +Inline $$E=mc^2$$ Inline,Inline $$E=mc^2$$ Inline。 + +$$\(\sqrt{3x-1}+(1+x)^2\)$$ + +$$\sin(\alpha)^{\theta}=\sum_{i=0}^{n}(x^i + \cos(f))$$ + +### FlowChart + +```flow +st=>start: Login +op=>operation: Login operation +cond=>condition: Successful Yes or No? +e=>end: To admin + +st->op->cond +cond(yes)->e +cond(no)->op +``` + +### Sequence Diagram + +```seq +Andrew->China: Says Hello +Note right of China: China thinks\nabout it +China-->Andrew: How are you? +Andrew->>China: I am good thanks! +``` + +### End diff --git a/prisma/seed/init.mjs b/prisma/seed/init.mjs deleted file mode 100644 index 86fd7d8..0000000 --- a/prisma/seed/init.mjs +++ /dev/null @@ -1,55 +0,0 @@ -import { PrismaClient } from "@prisma/client"; - -const prisma = new PrismaClient(); - -async function main() { - const workspace = await prisma.workspace.create({ - data: { - name: "Test", - description: "A workspace for development", - }, - }); - const adminRole = await prisma.userRole.create({ - data: { - name: "admin", - permissions: { - create: true, - read: true, - update: true, - delete: true, - }, - }, - }); - const user = await prisma.user.create({ - data: { - name: "テスト管理者", - slug: "admin", - email: "admin@exmaple.com", - image: "https://with.koeni.dev/identicon/admin", - status: "ONLINE", - roleId: adminRole.id, - }, - }); - const channel = await prisma.channel.create({ - data: { - slug: "general", - name: "general", - workspaceId: workspace.id, - type: "PUBLIC", - }, - }); - await prisma.message.create({ - data: { - content: "Hello, World!", - channelId: channel.id, - userId: user.id, - type: "NORMAL", - }, - }); -} - -main() - .catch((e) => console.error(e)) - .finally(async () => { - await prisma.$disconnect(); - }); diff --git a/prisma/seed/init.ts b/prisma/seed/init.ts new file mode 100644 index 0000000..260128c --- /dev/null +++ b/prisma/seed/init.ts @@ -0,0 +1,295 @@ +import fs from "fs"; +import path from "path"; + +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); + +async function main() { + // ワークスペース作成 + const workspace = await prisma.workspace.create({ + data: { + name: "Digichat for Insider", + description: "テスト用のワークスペースです", + }, + }); + + // ロール作成 + const adminRole = await prisma.userRole.create({ + data: { + name: "admin", + permissions: { + create: true, + read: true, + update: true, + delete: true, + }, + }, + }); + const moderatorRole = await prisma.userRole.create({ + data: { + name: "moderator", + permissions: { + create: true, + read: true, + update: true, + delete: false, + }, + }, + }); + const memberRole = await prisma.userRole.create({ + data: { + name: "member", + permissions: { + create: false, + read: true, + update: false, + delete: false, + }, + }, + }); + + // ユーザー作成 + const adminUser = await prisma.user.create({ + data: { + name: "テスト管理者", + slug: "admin", + email: "admin@example.com", + image: "https://with.koeni.dev/identicon/admin", + status: "ONLINE", + roleId: adminRole.id, + }, + }); + + const modUser = await prisma.user.create({ + data: { + name: "モデレーター太郎", + slug: "mod-taro", + email: "taro@example.com", + image: "https://with.koeni.dev/identicon/mod-taro", + status: "AWAY", + roleId: moderatorRole.id, + }, + }); + + const memberUser = await prisma.user.create({ + data: { + name: "一般ユーザー花子", + slug: "member-hanako", + email: "hanako@example.com", + image: "https://with.koeni.dev/identicon/hanako", + status: "OFFLINE", + roleId: memberRole.id, + }, + }); + + const anotherMemberUser = await prisma.user.create({ + data: { + name: "一般ユーザー次郎", + slug: "member-jiro", + email: "jiro@example.com", + image: "https://with.koeni.dev/identicon/jiro", + status: "BUSY", + roleId: memberRole.id, + }, + }); + + // チャンネル作成 + const generalChannel = await prisma.channel.create({ + data: { + slug: "general", + name: "general", + workspaceId: workspace.id, + type: "PUBLIC", + creatorId: adminUser.id, + description: "全体向けの一般チャンネル", + }, + }); + + const randomChannel = await prisma.channel.create({ + data: { + slug: "random", + name: "random", + workspaceId: workspace.id, + type: "PUBLIC", + creatorId: modUser.id, + description: "雑談用チャンネル", + }, + }); + + const privateChannel = await prisma.channel.create({ + data: { + slug: "private", + name: "private", + workspaceId: workspace.id, + type: "PRIVATE", + creatorId: adminUser.id, + description: "管理者専用チャンネル", + }, + }); + + // ----- general チャンネルのメッセージ ----- + await prisma.message.create({ + data: { + content: "Hello, World!", + channelId: generalChannel.id, + userId: adminUser.id, + type: "NORMAL", + }, + }); + + await prisma.message.create({ + data: { + content: + "This is a *markdown* message with **bold text** and [a link](https://example.com).", + channelId: generalChannel.id, + userId: modUser.id, + type: "IMPORTANT", + }, + }); + + await prisma.message.create({ + data: { + content: + "Here is some TeX: \\(E = mc^2\\) which explains the famous equation.", + channelId: generalChannel.id, + userId: memberUser.id, + type: "NORMAL", + }, + }); + + await prisma.message.create({ + data: { + content: + "

This is a rich text message with HTML content and an image: sample

", + channelId: generalChannel.id, + userId: anotherMemberUser.id, + type: "PROJECT", + }, + }); + + // URL を含むメッセージを作成し、MessageLink テーブルにもレコードを追加 + const msgWithURL = await prisma.message.create({ + data: { + content: "Check out our new website: https://digicre.net/", + channelId: generalChannel.id, + userId: adminUser.id, + type: "NORMAL", + }, + }); + + await prisma.messageLink.create({ + data: { + messageId: msgWithURL.id, + url: "https://digicre.net/", + title: "芝浦工業大学 デジクリ", + description: "芝浦工業大学の公認サークル『デジクリ』の Web サイトです。", + ogImageUrl: "https://digicre.net/ogp.png", + }, + }); + + // 様々なパターンが入ったメッセージ + const filePath = path.join(__dirname, "GFM.txt"); + const content = fs.readFileSync(filePath, "utf8"); + await prisma.message.create({ + data: { + content: content, + channelId: generalChannel.id, + userId: memberUser.id, + type: "NORMAL", + }, + }); + + // ----- random チャンネルのメッセージ ----- + await prisma.message.create({ + data: { + content: "Random talk: Did you see the latest news?", + channelId: randomChannel.id, + userId: modUser.id, + type: "NORMAL", + }, + }); + + await prisma.message.create({ + data: { + content: "Another random message with **markdown** and _italic_ style.", + channelId: randomChannel.id, + userId: memberUser.id, + type: "IMPORTANT", + }, + }); + + // メンションを含むメッセージ作成(内容中は @ユーザーID と記載)し、Mention テーブルへレコードを追加 + const mentionMsg = await prisma.message.create({ + data: { + content: `Hello @${adminUser.id}, please review the latest update.`, + channelId: randomChannel.id, + userId: modUser.id, + type: "NORMAL", + }, + }); + + await prisma.mention.create({ + data: { + messageId: mentionMsg.id, + mentionedUserId: adminUser.id, + }, + }); + + // ----- private チャンネルのメッセージ ----- + await prisma.message.create({ + data: { + content: "管理者専用のシークレットなメッセージです。", + channelId: privateChannel.id, + userId: adminUser.id, + type: "NORMAL", + }, + }); + + await prisma.message.create({ + data: { + content: + "Another private message with TeX: \\(\\int_0^1 x^2 dx = \\frac{1}{3}\\)", + channelId: privateChannel.id, + userId: modUser.id, + type: "NORMAL", + }, + }); + + // ----- 各チャンネルでメッセージを投稿しているユーザーを ChannelMember テーブルに登録 ----- + // general チャンネル + await prisma.channelMember.createMany({ + data: [ + { channelId: generalChannel.id, userId: adminUser.id, role: "ADMIN" }, + { channelId: generalChannel.id, userId: modUser.id, role: "MEMBER" }, + { channelId: generalChannel.id, userId: memberUser.id, role: "MEMBER" }, + { + channelId: generalChannel.id, + userId: anotherMemberUser.id, + role: "MEMBER", + }, + ], + }); + + // random チャンネル + await prisma.channelMember.createMany({ + data: [ + { channelId: randomChannel.id, userId: modUser.id, role: "MEMBER" }, + { channelId: randomChannel.id, userId: memberUser.id, role: "MEMBER" }, + ], + }); + + // private チャンネル + await prisma.channelMember.createMany({ + data: [ + { channelId: privateChannel.id, userId: adminUser.id, role: "ADMIN" }, + { channelId: privateChannel.id, userId: modUser.id, role: "MEMBER" }, + ], + }); +} + +main() + .catch((e) => console.error(e)) + .finally(async () => { + await prisma.$disconnect(); + });