mirror of
https://framagit.org/les/gancio.git
synced 2025-01-31 16:42:22 +01:00
validator, i18n, start with auth, locale loader, sequelize7 with ts, announcement
This commit is contained in:
parent
fa60a667ea
commit
1ed0fa4fd4
15 changed files with 424 additions and 63 deletions
|
@ -17,7 +17,7 @@ const config = useRuntimeConfig()
|
||||||
</v-main>
|
</v-main>
|
||||||
<!-- <CoreDialog /> -->
|
<!-- <CoreDialog /> -->
|
||||||
<!-- <CoreNotification /> -->
|
<!-- <CoreNotification /> -->
|
||||||
<v-footer app height="40"><v-spacer />v.{{config.public.version}} © 2023 Trialsh, made with ❤️ for a better world</v-footer>
|
<v-footer app height="40"><v-spacer />v.{{config.public.version}}</v-footer>
|
||||||
</v-app>
|
</v-app>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module.exports = {
|
export default {
|
||||||
ca: 'Català',
|
ca: 'Català',
|
||||||
cs: 'Czech',
|
cs: 'Czech',
|
||||||
de: 'Deutsch',
|
de: 'Deutsch',
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
export default async (context, locale) => {
|
|
||||||
try {
|
|
||||||
if (process.server) {
|
|
||||||
return context.$axios.$get(`locale/${locale}`)
|
|
||||||
} else {
|
|
||||||
// cannot use $axios here as plugins have not yet been loaded
|
|
||||||
return fetch(`${window.location.origin}/api/locale/${locale}`).then(ret => ret.json())
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Error loading locale ${locale}`, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {}
|
|
||||||
}
|
|
16
locales/loader.ts
Normal file
16
locales/loader.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
export default defineI18nLocale(locale => $fetch(`api/locale/${locale}`))
|
||||||
|
|
||||||
|
// export default async (context: any, locale: string) => {
|
||||||
|
// try {
|
||||||
|
// if (process.server) {
|
||||||
|
// return context.$axios.$get(`locale/${locale}`)
|
||||||
|
// } else {
|
||||||
|
// // cannot use $axios here as plugins have not yet been loaded
|
||||||
|
// return fetch(`${window.location.origin}/api/locale/${locale}`).then(ret => ret.json())
|
||||||
|
// }
|
||||||
|
// } catch (e) {
|
||||||
|
// console.error(`Error loading locale ${locale}`, e)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return {}
|
||||||
|
// }
|
|
@ -1,6 +1,39 @@
|
||||||
|
import { version } from './package.json'
|
||||||
|
import locales from './locales/index'
|
||||||
|
|
||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-04-03',
|
compatibilityDate: '2024-04-03',
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
modules: ["vuetify-nuxt-module" ],
|
modules: ["vuetify-nuxt-module", '@nuxtjs/i18n'],
|
||||||
|
runtimeConfig: {
|
||||||
|
public: {
|
||||||
|
version
|
||||||
|
}
|
||||||
|
},
|
||||||
|
i18n: {
|
||||||
|
locales: Object.keys(locales).map((key: string) => ({
|
||||||
|
code: key,
|
||||||
|
// name: locales[key],
|
||||||
|
file: 'loader.ts',
|
||||||
|
iso: key
|
||||||
|
})),
|
||||||
|
langDir: 'locales',
|
||||||
|
lazy: true,
|
||||||
|
strategy: 'no_prefix',
|
||||||
|
skipSettingLocaleOnNavigate: true,
|
||||||
|
},
|
||||||
|
nitro: {
|
||||||
|
esbuild: {
|
||||||
|
options: {
|
||||||
|
tsconfigRaw: {
|
||||||
|
// See https://github.com/nuxt/nuxt/issues/14126
|
||||||
|
// https://github.com/unjs/nitro/issues/273
|
||||||
|
compilerOptions: {
|
||||||
|
experimentalDecorators: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
34
package.json
34
package.json
|
@ -1,6 +1,29 @@
|
||||||
{
|
{
|
||||||
"name": "nuxt-app",
|
"name": "gancio",
|
||||||
"private": true,
|
"version": "2.0.0-alpha",
|
||||||
|
"description": "A shared agenda for local communities",
|
||||||
|
"author": "lesion",
|
||||||
|
"bugs": {
|
||||||
|
"email": "lesion@autistici.org",
|
||||||
|
"url": "https://framagit.org/les/gancio/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://gancio.org",
|
||||||
|
"keywords": [
|
||||||
|
"AP",
|
||||||
|
"gancio",
|
||||||
|
"events",
|
||||||
|
"federation",
|
||||||
|
"activitypub",
|
||||||
|
"event",
|
||||||
|
"server",
|
||||||
|
"self-host",
|
||||||
|
"app"
|
||||||
|
],
|
||||||
|
"license": "AGPL-3.0",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://framagit.org/les/gancio"
|
||||||
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
|
@ -10,19 +33,22 @@
|
||||||
"postinstall": "nuxt prepare"
|
"postinstall": "nuxt prepare"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@nuxtjs/i18n": "^8.5.0",
|
||||||
"@sequelize/core": "^7.0.0-alpha.37",
|
"@sequelize/core": "^7.0.0-alpha.37",
|
||||||
"@sequelize/sqlite3": "^7.0.0-alpha.41",
|
"@sequelize/sqlite3": "^7.0.0-alpha.41",
|
||||||
"nuxt": "^3.12.4",
|
"nuxt": "^3.12.4",
|
||||||
"sequelize": "^6.37.3",
|
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
"vuetify-nuxt-module": "^0.16.1"
|
"vuetify-nuxt-module": "^0.16.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/eslint-config": "^0.5.0",
|
"@nuxt/eslint-config": "^0.5.0",
|
||||||
"@nuxtjs/eslint-module": "^4.1.0",
|
"@nuxtjs/eslint-module": "^4.1.0",
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
"eslint": "^9.9.0",
|
"eslint": "^9.9.0",
|
||||||
"eslint-plugin-nuxt": "^4.0.0",
|
"eslint-plugin-nuxt": "^4.0.0",
|
||||||
|
"linkifyjs": "^4.1.3",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"sqlite3": "^5.1.7"
|
"sqlite3": "^5.1.7"
|
||||||
}
|
},
|
||||||
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||||
}
|
}
|
||||||
|
|
52
pages/Login.vue
Normal file
52
pages/Login.vue
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<template>
|
||||||
|
<v-container class='pa-0 pa-md-3'>
|
||||||
|
<v-row class="mt-md-5 ma-0" justify='center'>
|
||||||
|
<v-col class='pa-0 pa-md-3' cols='12' md="6" lg="5" xl="4">
|
||||||
|
<v-form v-model='valid' ref='form' lazy-validation @submit.prevent='submit'>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title>{{$t('common.login')}}</v-card-title>
|
||||||
|
<v-card-subtitle v-text="$t('login.description')" />
|
||||||
|
<v-card-text>
|
||||||
|
<span>{{ email }}</span>
|
||||||
|
<v-text-field v-model='email' validate-on-blur :rules='$valid.email'
|
||||||
|
autofocus :label='$t("common.email")' />
|
||||||
|
|
||||||
|
<v-text-field v-model='password' :rules='$valid.password'
|
||||||
|
type='password' :label='$t("common.password")' />
|
||||||
|
</v-card-text>
|
||||||
|
|
||||||
|
<v-card-actions>
|
||||||
|
<v-btn text
|
||||||
|
tabindex="1"
|
||||||
|
@click='forgot' small>{{$t('login.forgot_password')}}</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer/>
|
||||||
|
|
||||||
|
<v-btn v-if='settings?.allow_registration'
|
||||||
|
to='/register'
|
||||||
|
text
|
||||||
|
color='orange'>{{$t('login.not_registered')}}</v-btn>
|
||||||
|
|
||||||
|
<v-btn color='success'
|
||||||
|
type='submit' outlined
|
||||||
|
:disabled='!valid || loading' :loading='loading'>{{$t('common.login')}}</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
</v-form>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const valid = ref('')
|
||||||
|
const email = ref('')
|
||||||
|
const password = ref('')
|
||||||
|
|
||||||
|
function submit () {
|
||||||
|
console.error('submit')
|
||||||
|
}
|
||||||
|
</script>
|
28
plugins/validators.ts
Normal file
28
plugins/validators.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
|
||||||
|
import { test }from "linkifyjs"
|
||||||
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
|
|
||||||
|
const $t = nuxtApp.vueApp.$nuxt.$i18n.t.bind(nuxtApp.vueApp.$nuxt.$i18n)
|
||||||
|
const validators = {
|
||||||
|
required (fieldName: string) {
|
||||||
|
return (v: string) => !(v===undefined || v===null || v.length <= 0) || $t('validators.required', { fieldName: $t(fieldName) })
|
||||||
|
},
|
||||||
|
email: [
|
||||||
|
(v: string) => !!v || $t('validators.required', { fieldName: $t('common.email') }),
|
||||||
|
(v: string) => (v && (v === 'admin' || !!test(v, 'email')) || $t('validators.email'))
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
(v: string) => !!v || $t('validators.required', { fieldName: $t('common.password') })
|
||||||
|
],
|
||||||
|
latitude: [
|
||||||
|
(v: number) => (v < 90 && v > -90) || $t('validators.latitude')
|
||||||
|
],
|
||||||
|
longitude: [
|
||||||
|
(v: number) => (v < 180 && v > -180) || $t('validators.longitude')
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
nuxtApp.provide("valid", validators)
|
||||||
|
|
||||||
|
})
|
|
@ -1,3 +1,4 @@
|
||||||
|
// import { Announcement } from "~/server/utils/sequelize"
|
||||||
// return an announcement
|
// return an announcement
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler((event) => {
|
||||||
return Announcement.findByPk(event.context.params?.id)
|
return Announcement.findByPk(event.context.params?.id)
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
import { Event } from "~/server/utils/sequelize"
|
||||||
|
|
||||||
export default defineEventHandler((event) => {
|
export default defineEventHandler((event) => {
|
||||||
return Events.findAll()
|
return Event.findAll()
|
||||||
})
|
})
|
||||||
|
|
37
server/api/locale/[locale].get.ts
Normal file
37
server/api/locale/[locale].get.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import locales from '~/locales/index'
|
||||||
|
import fs from 'fs'
|
||||||
|
export default defineEventHandler(async event => {
|
||||||
|
// const merge = require('lodash/merge')
|
||||||
|
// const config = require('../../config')
|
||||||
|
// const path = require('path')
|
||||||
|
// const fs = require('fs')
|
||||||
|
// const log = require('../../log')
|
||||||
|
|
||||||
|
const locale = event.context.params?.locale
|
||||||
|
// check if this locale exists
|
||||||
|
// if (!locales[locale]) {
|
||||||
|
// return res.sendStatus(404)
|
||||||
|
// }
|
||||||
|
// const defaultLocaleMessages = await import(`../../locales/${locale}.json`, { with: { type: "json" }}) ;
|
||||||
|
const fileContent = fs.readFileSync(`./locales/${locale}.json`, 'utf-8');
|
||||||
|
return fileContent
|
||||||
|
// return defaultLocaleMessages
|
||||||
|
// // check if we have a user custom messages
|
||||||
|
// let customLocaleMessages = {}
|
||||||
|
|
||||||
|
// const customLocalePath = config.user_locale && path.resolve(config.user_locale, `${locale}.json`)
|
||||||
|
// if (config.user_locale && fs.existsSync(customLocalePath)) {
|
||||||
|
// try {
|
||||||
|
// customLocaleMessages = require(customLocalePath)
|
||||||
|
// } catch (e) {
|
||||||
|
// log.error(`Error reading custom locale messages: ${e}`)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const ret = merge(defaultLocaleMessages, customLocaleMessages)
|
||||||
|
// return res.json(ret)
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
})
|
|
@ -1,12 +0,0 @@
|
||||||
export default (sequelize: any, DataTypes: any) => {
|
|
||||||
|
|
||||||
const Announcement = sequelize.define('announcement', {
|
|
||||||
title: DataTypes.STRING,
|
|
||||||
announcement: DataTypes.STRING,
|
|
||||||
visible: DataTypes.BOOLEAN
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
return Announcement
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
{
|
{
|
||||||
"extends": "../.nuxt/tsconfig.server.json"
|
"extends": "../.nuxt/tsconfig.server.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"esModuleInterop": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,217 @@
|
||||||
import { DataTypes, Sequelize, Model,
|
import bcrypt from 'bcrypt'
|
||||||
InferAttributes,
|
import {
|
||||||
InferCreationAttributes } from '@sequelize/core'
|
Sequelize,
|
||||||
import { SqliteDialect } from '@sequelize/sqlite3'
|
type HasManyCreateAssociationMixin,
|
||||||
|
type InferAttributes,
|
||||||
|
type InferCreationAttributes,
|
||||||
|
type Options,
|
||||||
|
} from "@sequelize/core"
|
||||||
|
|
||||||
// import AnnouncementModel from '../models/announcement'
|
import {
|
||||||
// import EventModel from '../models/event'
|
DataTypes,
|
||||||
|
Model,
|
||||||
|
type CreationOptional,
|
||||||
|
type NonAttribute,
|
||||||
|
} from "@sequelize/core"
|
||||||
|
|
||||||
class Announcement extends Model<InferAttributes<Announcement>, InferCreationAttributes<Announcement>> {
|
import {
|
||||||
|
Attribute,
|
||||||
|
HasMany,
|
||||||
|
NotNull,
|
||||||
|
Table,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
PrimaryKey,
|
||||||
|
AutoIncrement,
|
||||||
|
BeforeCreate,
|
||||||
|
BeforeUpsert,
|
||||||
|
Index,
|
||||||
|
Unique,
|
||||||
|
BeforeSave,
|
||||||
|
} from "@sequelize/core/decorators-legacy"
|
||||||
|
|
||||||
|
// import type { SqliteDialect } from "@sequelize/sqlite3";
|
||||||
|
// import bcrypt from "bcrypt";
|
||||||
|
const environment = process.env.NODE_ENV || "development";
|
||||||
|
|
||||||
|
// const options = config[environment as keyof typeof config];
|
||||||
|
// export const sequelize = new Sequelize({
|
||||||
|
// ...options,
|
||||||
|
// } as Options<SqliteDialect>);
|
||||||
|
|
||||||
|
const sequelize = new Sequelize({
|
||||||
|
dialect: 'sqlite',
|
||||||
|
storage: './gancio2.sqlite'
|
||||||
|
})
|
||||||
|
|
||||||
|
export default sequelize
|
||||||
|
|
||||||
|
@Table({
|
||||||
|
tableName: 'announcements',
|
||||||
|
})
|
||||||
|
export class Announcement extends Model<
|
||||||
|
InferAttributes<Announcement>,
|
||||||
|
InferCreationAttributes<Announcement>
|
||||||
|
> {
|
||||||
|
@Attribute(DataTypes.INTEGER.UNSIGNED)
|
||||||
|
@PrimaryKey
|
||||||
|
@AutoIncrement
|
||||||
|
declare readonly id: CreationOptional<number>;
|
||||||
|
|
||||||
|
@Attribute(DataTypes.STRING)
|
||||||
|
@NotNull
|
||||||
|
declare title: string;
|
||||||
|
|
||||||
|
@Attribute(DataTypes.STRING)
|
||||||
|
declare announcement: string;
|
||||||
|
|
||||||
|
@Attribute(DataTypes.BOOLEAN)
|
||||||
|
declare visible: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Table({
|
||||||
|
tableName: 'events'
|
||||||
|
})
|
||||||
|
export class Event extends Model<
|
||||||
|
InferAttributes<Event>,
|
||||||
|
InferCreationAttributes<Event>
|
||||||
|
> {
|
||||||
|
@Attribute(DataTypes.INTEGER.UNSIGNED)
|
||||||
|
@PrimaryKey
|
||||||
|
@AutoIncrement
|
||||||
|
declare readonly id: CreationOptional<number>
|
||||||
|
|
||||||
|
@Attribute(DataTypes.STRING)
|
||||||
|
@NotNull
|
||||||
declare title: string
|
declare title: string
|
||||||
declare announcement: string | null
|
|
||||||
declare visible: boolean
|
@Attribute(DataTypes.STRING)
|
||||||
|
@Index
|
||||||
|
@Unique
|
||||||
|
declare slug: string
|
||||||
|
|
||||||
|
@Attribute(DataTypes.TEXT)
|
||||||
|
declare description: string
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Announcement = sequelize.define('announcement', {
|
type Role = "admin" | "editor" | "user"
|
||||||
title: DataTypes.STRING,
|
|
||||||
announcement: DataTypes.STRING,
|
@Table({
|
||||||
visible: DataTypes.BOOLEAN
|
tableName: "Users",
|
||||||
|
indexes: [{ fields: ["email"], unique: true }],
|
||||||
})
|
})
|
||||||
|
export class User extends Model<
|
||||||
|
InferAttributes<User>,
|
||||||
|
InferCreationAttributes<User>
|
||||||
|
> {
|
||||||
|
@Attribute(DataTypes.INTEGER.UNSIGNED)
|
||||||
|
@PrimaryKey
|
||||||
|
@AutoIncrement
|
||||||
|
declare readonly id: CreationOptional<number>;
|
||||||
|
|
||||||
const db = new Sequelize({
|
@Attribute(DataTypes.STRING)
|
||||||
dialect: "sqlite",
|
declare display_name: string;
|
||||||
storage: "./gancio2.sqlite",
|
|
||||||
models: [Announcement]
|
|
||||||
})
|
|
||||||
|
|
||||||
// export const Announcement = AnnouncementModel(db, DataTypes)
|
@Attribute(DataTypes.STRING)
|
||||||
// export const Events = EventModel(db, DataTypes)
|
@NotNull
|
||||||
|
declare email: string;
|
||||||
|
|
||||||
try {
|
@Attribute(DataTypes.STRING)
|
||||||
db.authenticate()
|
@NotNull
|
||||||
} catch (e) {
|
declare password: string
|
||||||
console.error(e)
|
|
||||||
|
@Attribute(DataTypes.STRING)
|
||||||
|
declare recover_code: string
|
||||||
|
|
||||||
|
@Attribute(DataTypes.BOOLEAN)
|
||||||
|
declare is_active: Boolean
|
||||||
|
|
||||||
|
@Attribute(DataTypes.STRING)
|
||||||
|
declare description: string
|
||||||
|
|
||||||
|
@Attribute(DataTypes.ENUM(['admin','editor', 'user']))
|
||||||
|
declare role: Role
|
||||||
|
|
||||||
|
|
||||||
|
@CreatedAt
|
||||||
|
declare readonly createdAt: CreationOptional<Date>;
|
||||||
|
|
||||||
|
@UpdatedAt
|
||||||
|
declare readonly updatedAt: CreationOptional<Date>;
|
||||||
|
|
||||||
|
|
||||||
|
async comparePassword (pwd: string) {
|
||||||
|
if (!this.password) { return false }
|
||||||
|
return bcrypt.compare(pwd, this.password)
|
||||||
|
}
|
||||||
|
// @HasMany(() => Post, {
|
||||||
|
// foreignKey: "userId",
|
||||||
|
// inverse: {
|
||||||
|
// as: "author",
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// declare posts?: NonAttribute<Post[]>;
|
||||||
|
|
||||||
|
// declare createPost: HasManyCreateAssociationMixin<Post, "userId">;
|
||||||
|
|
||||||
|
@BeforeSave
|
||||||
|
static async hashPassword(instance: User) {
|
||||||
|
if(instance.changed('password')) {
|
||||||
|
const password = instance.getDataValue('password')
|
||||||
|
if (password) {
|
||||||
|
const hashedPassword = bcrypt.hashSync(password, 10)
|
||||||
|
instance.setDataValue("password", hashedPassword)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @BeforeCreate
|
||||||
|
// static async hashPassword(instance: User) {
|
||||||
|
// const password = instance.getDataValue("password");
|
||||||
|
// if (password) {
|
||||||
|
// const hashedPassword = bcrypt.hashSync(password, 10);
|
||||||
|
// instance.setDataValue("password", hashedPassword);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default db
|
// @Table({
|
||||||
|
// tableName: "Posts",
|
||||||
|
// })
|
||||||
|
// export class Post extends Model<
|
||||||
|
// InferAttributes<Post>,
|
||||||
|
// InferCreationAttributes<Post>
|
||||||
|
// > {
|
||||||
|
// @Attribute(DataTypes.INTEGER.UNSIGNED)
|
||||||
|
// @PrimaryKey
|
||||||
|
// @AutoIncrement
|
||||||
|
// declare readonly id: CreationOptional<number>;
|
||||||
|
|
||||||
|
// @Attribute(DataTypes.STRING)
|
||||||
|
// @NotNull
|
||||||
|
// declare title: string;
|
||||||
|
|
||||||
|
// @Attribute(DataTypes.STRING)
|
||||||
|
// @NotNull
|
||||||
|
// declare content: string;
|
||||||
|
|
||||||
|
// @Attribute({
|
||||||
|
// type: DataTypes.INTEGER.UNSIGNED,
|
||||||
|
// references: { table: "Users", key: "id" },
|
||||||
|
// onUpdate: "CASCADE",
|
||||||
|
// onDelete: "CASCADE",
|
||||||
|
// })
|
||||||
|
// declare userId: number;
|
||||||
|
|
||||||
|
// @CreatedAt
|
||||||
|
// declare readonly createdAt: CreationOptional<Date>;
|
||||||
|
|
||||||
|
// @UpdatedAt
|
||||||
|
// declare readonly updatedAt: CreationOptional<Date>;
|
||||||
|
|
||||||
|
// /** Declared by {@link User#posts} */
|
||||||
|
// declare author?: NonAttribute<User>;
|
||||||
|
// }
|
||||||
|
|
||||||
|
sequelize.addModels([Announcement, Event]);
|
|
@ -1,4 +1,10 @@
|
||||||
{
|
{
|
||||||
// https://nuxt.com/docs/guide/concepts/typescript
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
"extends": "./.nuxt/tsconfig.json",
|
"extends": "./.nuxt/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"esModuleInterop": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue