mirror of
https://github.com/pawelmalak/snippet-box.git
synced 2025-12-21 13:23:05 +01:00
Removed tags column. Added tags and snippets_tags tables
This commit is contained in:
@@ -1,19 +1,90 @@
|
||||
import { DataTypes, QueryInterface, QueryTypes } from 'sequelize';
|
||||
import { sequelize } from '../';
|
||||
const { STRING } = DataTypes;
|
||||
import { Logger } from '../../utils';
|
||||
import { DataTypes, QueryInterface } from 'sequelize';
|
||||
import {
|
||||
SnippetModel,
|
||||
Snippet_TagModel,
|
||||
TagInstance,
|
||||
TagModel
|
||||
} from '../../models';
|
||||
|
||||
const { STRING, INTEGER } = DataTypes;
|
||||
const logger = new Logger('migration[02]');
|
||||
|
||||
export const up = async (queryInterface: QueryInterface): Promise<void> => {
|
||||
await queryInterface.addColumn('snippets', 'tags', {
|
||||
type: STRING,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
await queryInterface.createTable('tags', {
|
||||
id: {
|
||||
type: INTEGER,
|
||||
allowNull: false,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
name: {
|
||||
type: STRING,
|
||||
allowNull: false
|
||||
}
|
||||
});
|
||||
|
||||
await sequelize.query(`UPDATE snippets SET tags = language`, {
|
||||
type: QueryTypes.UPDATE
|
||||
await queryInterface.createTable('snippets_tags', {
|
||||
id: {
|
||||
type: INTEGER,
|
||||
allowNull: false,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
snippet_id: {
|
||||
type: INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
tag_id: {
|
||||
type: INTEGER,
|
||||
allowNull: false
|
||||
}
|
||||
});
|
||||
|
||||
// Create new tags from language column
|
||||
const snippets = await SnippetModel.findAll();
|
||||
const languages = snippets.map(snippet => snippet.language);
|
||||
const uniqueLanguages = [...new Set(languages)];
|
||||
const tags: TagInstance[] = [];
|
||||
|
||||
await new Promise<void>(resolve => {
|
||||
uniqueLanguages.forEach(async language => {
|
||||
try {
|
||||
const tag = await TagModel.create({ name: language });
|
||||
tags.push(tag);
|
||||
} catch (err) {
|
||||
logger.log('Error while creating new tags');
|
||||
} finally {
|
||||
if (uniqueLanguages.length == tags.length) {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Assign tag to snippet
|
||||
await new Promise<void>(resolve => {
|
||||
snippets.forEach(async snippet => {
|
||||
try {
|
||||
const tag = tags.find(tag => tag.name == snippet.language);
|
||||
|
||||
if (tag) {
|
||||
await Snippet_TagModel.create({
|
||||
snippet_id: snippet.id,
|
||||
tag_id: tag.id
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
logger.log('Error while assigning tags to snippets');
|
||||
console.log(err);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const down = async (queryInterface: QueryInterface): Promise<void> => {
|
||||
await queryInterface.removeColumn('snippets', 'tags');
|
||||
await queryInterface.dropTable('tags');
|
||||
await queryInterface.dropTable('snippets_tags');
|
||||
};
|
||||
|
||||
@@ -4,52 +4,53 @@ import { Snippet, SnippetCreationAttributes } from '../typescript/interfaces';
|
||||
|
||||
const { INTEGER, STRING, DATE, TEXT } = DataTypes;
|
||||
|
||||
interface SnippetInstance
|
||||
export interface SnippetInstance
|
||||
extends Model<Snippet, SnippetCreationAttributes>,
|
||||
Snippet {}
|
||||
|
||||
export const SnippetModel = sequelize.define<SnippetInstance>('Snippet', {
|
||||
id: {
|
||||
type: INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
export const SnippetModel = sequelize.define<SnippetInstance>(
|
||||
'Snippet',
|
||||
{
|
||||
id: {
|
||||
type: INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
title: {
|
||||
type: STRING,
|
||||
allowNull: false
|
||||
},
|
||||
description: {
|
||||
type: TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
language: {
|
||||
type: STRING,
|
||||
allowNull: false
|
||||
},
|
||||
code: {
|
||||
type: TEXT,
|
||||
allowNull: false
|
||||
},
|
||||
docs: {
|
||||
type: TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
isPinned: {
|
||||
type: INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
createdAt: {
|
||||
type: DATE
|
||||
},
|
||||
updatedAt: {
|
||||
type: DATE
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: STRING,
|
||||
allowNull: false
|
||||
},
|
||||
description: {
|
||||
type: TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
language: {
|
||||
type: STRING,
|
||||
allowNull: false
|
||||
},
|
||||
code: {
|
||||
type: TEXT,
|
||||
allowNull: false
|
||||
},
|
||||
docs: {
|
||||
type: TEXT,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
isPinned: {
|
||||
type: INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: 0
|
||||
},
|
||||
tags: {
|
||||
type: STRING,
|
||||
allowNull: true,
|
||||
defaultValue: ''
|
||||
},
|
||||
createdAt: {
|
||||
type: DATE
|
||||
},
|
||||
updatedAt: {
|
||||
type: DATE
|
||||
{
|
||||
tableName: 'snippets'
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
35
src/models/Snippet_Tag.ts
Normal file
35
src/models/Snippet_Tag.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
import { sequelize } from '../db';
|
||||
import {
|
||||
Snippet_Tag,
|
||||
Snippet_TagCreationAttributes
|
||||
} from '../typescript/interfaces';
|
||||
|
||||
const { INTEGER } = DataTypes;
|
||||
|
||||
export interface Snippet_TagInstance
|
||||
extends Model<Snippet_Tag, Snippet_TagCreationAttributes>,
|
||||
Snippet_Tag {}
|
||||
|
||||
export const Snippet_TagModel = sequelize.define<Snippet_TagInstance>(
|
||||
'Snippet_Tag',
|
||||
{
|
||||
id: {
|
||||
type: INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
snippet_id: {
|
||||
type: INTEGER,
|
||||
allowNull: false
|
||||
},
|
||||
tag_id: {
|
||||
type: INTEGER,
|
||||
allowNull: false
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: false,
|
||||
tableName: 'snippets_tags'
|
||||
}
|
||||
);
|
||||
26
src/models/Tag.ts
Normal file
26
src/models/Tag.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Model, DataTypes } from 'sequelize';
|
||||
import { sequelize } from '../db';
|
||||
import { Tag, TagCreationAttributes } from '../typescript/interfaces';
|
||||
|
||||
const { INTEGER, STRING } = DataTypes;
|
||||
|
||||
export interface TagInstance extends Model<Tag, TagCreationAttributes>, Tag {}
|
||||
|
||||
export const TagModel = sequelize.define<TagInstance>(
|
||||
'Tag',
|
||||
{
|
||||
id: {
|
||||
type: INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
name: {
|
||||
type: STRING,
|
||||
allowNull: false
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: false,
|
||||
tableName: 'tags'
|
||||
}
|
||||
);
|
||||
@@ -1 +1,3 @@
|
||||
export * from './Snippet';
|
||||
export * from './Tag';
|
||||
export * from './Snippet_Tag';
|
||||
|
||||
@@ -8,7 +8,6 @@ export interface Snippet extends Model {
|
||||
code: string;
|
||||
docs: string;
|
||||
isPinned: number;
|
||||
tags: string;
|
||||
}
|
||||
|
||||
export interface SnippetCreationAttributes
|
||||
|
||||
10
src/typescript/interfaces/Snippet_Tag.ts
Normal file
10
src/typescript/interfaces/Snippet_Tag.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Optional } from 'sequelize';
|
||||
|
||||
export interface Snippet_Tag {
|
||||
id: number;
|
||||
snippet_id: number;
|
||||
tag_id: number;
|
||||
}
|
||||
|
||||
export interface Snippet_TagCreationAttributes
|
||||
extends Optional<Snippet_Tag, 'id'> {}
|
||||
8
src/typescript/interfaces/Tag.ts
Normal file
8
src/typescript/interfaces/Tag.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Optional } from 'sequelize';
|
||||
|
||||
export interface Tag {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface TagCreationAttributes extends Optional<Tag, 'id'> {}
|
||||
@@ -1,2 +1,4 @@
|
||||
export * from './Model';
|
||||
export * from './Snippet';
|
||||
export * from './Tag';
|
||||
export * from './Snippet_Tag';
|
||||
|
||||
Reference in New Issue
Block a user