Skip to content

Commit

Permalink
Migrate to Nuxt-bridge (#480)
Browse files Browse the repository at this point in the history
* Start playing with nuxt-bridge

* Follow migration docs

* Replace nuxt composition api by @vue/composition-api

* Temporarily disable lint

* Regenerate lock file

* Remove usage of nuxt/composition-api

* Use latest nuxt + nuxt-bridge

* Add output to gitignore

* Fix apollo plugin

* Add how to add vite support

* Disable broken SSR for now

* Disable tailwind config view for now

* Remove nitro config again (not needed)

* Fix types of `#app` import

* Use nuxi everywhere

* Fix esm problems for prisma

* Update nuxt

* Fix imports of commonjs style, and fix backend

* Update deps

* Fix tsyringe

* Update deps

* Fix prisma imports

* Fix decorator error

* Update deps

* Update deps

* Don't update all packaes, only nuxt

* Fix pinia/nuxt

* Upate nuxt bridge

* Use new shiny config feature

* Fix merge issue

* Fix lint errors

* Link issue for config improvements

* Remove old workaround that is no longer necessary

* Only import type to be on safe side

* Improve apollo plugin

* Update nuxt

* Convert to es module

* Fix user password

* Disable missing middleware

* Try to fix eslint

* Increase memory for eslint

* Fix directory imports

* Rename tailwind to cjs

* Update patches for new apollo version

* Fix build error due to missing babel plugin

* Fix import for config

* Fix logo

* Upgrade nuxt

* Upgrade nuxt

* Upgrade nuxt

* Run prepare as postinstall

* Fix eslint

* Fix uuid esm error

* Fix tests

* Remove lint workaround on ci again

* Update nuxt.config.ts

* Upgrade graphql mock for esm compat

* Better error message

* Upgrade nuxt bridge

* Fix storybook

* Opt-in for node 17 compat

* Try without reload in extend Routes

* Fix storybook

* Update pinia patch

* Add patch for missing vueApp properties

* Improve plugins

* Fix plugins for storybook

* Fix tailwindcss

* Fix tailwind

* Upgrade nuxt

* Upgrade bridge

* Update patches

* Fix tyess for config

* Use old-style way to register vue plugins

* Remove noExternal for vue-demi

* Switch to different rollup plugin to fix import errors

* Upgrade bridge

* Disable legacy composition API support

* Upgrade bridge

* Path vue-tailwind for esm compat

* Don't use redis for sessions for now

* Use workaround for top-level await

* Another workaround for the dynamic vue import

* Use nuxi preview

* Deactivate login check for now

* Exclude build files from search

* Specify ts for scripts to fix storybook
  • Loading branch information
tobiasdiez authored Jan 8, 2022
1 parent 8b8d006 commit d00e1ab
Show file tree
Hide file tree
Showing 57 changed files with 4,058 additions and 1,269 deletions.
File renamed without changes.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ typings/
.next

# Nuxt.js build / generate output
.nuxt
dist
.nuxt/
.output/
dist/

# Gatsby files
.cache/
Expand Down
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,13 @@
".vue",
]
},
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.code-search": true,
"**/coverage": true,
"**/.output": true,
"**/.nuxt": true,
},
"vscode-graphql.useSchemaFileDefinitions": true
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Now close and re-open the workspace.
| yarn dev | Start ExpressJS server in development with Nuxt.js in dev mode with hot reloading enabled. Listen on [http://localhost:3000](http://localhost:3000). The GraphQL API is then accessible at [http://localhost:3000/api](http://localhost:3000/api) |
| yarn test | Execute all tests. Pass `-u` to update all Jest snapshots.|
| yarn build | Build the nuxt.js web application for production. |
| yarn start | Start ExpressJS server in production. |
| yarn start | Start ExpressJS server (for testing purposes). |
| yarn prisma:studio | Explore data in the database using a visual editor. |
| yarn storybook | Start [Storybook](#ui-workflow-storybook) in your browser. |

Expand Down
2 changes: 1 addition & 1 deletion api/database/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async function seedInternal(prisma: PrismaClientT): Promise<void> {
id: 'ckn4oul7100004cv7y3t94n8j',
email: '[email protected]',
password:
'saltsaltsaltsaltsaltsaltsaltsalt63f7e072b6a9faf6e77616c098c4bb3ac69c58d249e620e1dd51257018ac7fcb40b576e9f69e9c556c70a980327dac12b1ee76a76f22b249d585fe2de10b365a', // EBNPXY35TYkYXHs
'19184d8c1c1e9b483d8347f8da0d53ad92170233100d32c3a0d748725948c28d09a060d7f02962b7b93320c72a2cdd94f21b16b08bf8bd1cba0c5f77afeffddbb24df527c4f16f1fca6eb5480159b56df3d818b4b3c74ead04227a78b3d810b8', // EBNPXY35TYkYXHs
name: 'Alice',
},
})
Expand Down
4 changes: 2 additions & 2 deletions api/documents/user.document.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { PrismaClient } from '@prisma/client'
import {
import type {
PrismaClient,
UserDocument as PlainUserDocument,
Prisma,
User,
Expand Down
9 changes: 2 additions & 7 deletions api/groups/service.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import type {
PrismaClient as PrismaClientT,
Group,
User,
Prisma,
} from '@prisma/client'
import type { Group, Prisma, PrismaClient, User } from '@prisma/client'
import { inject, injectable } from 'tsyringe'

@injectable()
export class GroupService {
constructor(@inject('PrismaClient') private prisma: PrismaClientT) {}
constructor(@inject('PrismaClient') private prisma: PrismaClient) {}

async getGroupById(id: string): Promise<Group | null> {
return await this.prisma.group.findUnique({
Expand Down
49 changes: 27 additions & 22 deletions api/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import http from 'http'
import express from 'express'
import { ApolloServer } from 'apollo-server-express'
import './tsyringe.config'
import 'reflect-metadata' // Needed for tsyringe
import { container } from 'tsyringe'
import {
ApolloServerPluginDrainHttpServer,
ApolloServerPluginLandingPageLocalDefault,
} from 'apollo-server-core'
import { config, Environment } from '../config'
import { Environment } from '../config'
import { configure as configureTsyringe } from './tsyringe.config'
import { buildContext } from './context'
import { loadSchema } from './schema'
import PassportInitializer from './user/passport-initializer'
import config from '#config'

// Create express instance
const app = express()
Expand All @@ -21,26 +23,29 @@ if (config.environment === Environment.Production) {
}
const httpServer = http.createServer(app)

const passportInitializer = container.resolve(PassportInitializer)
passportInitializer.initialize()
passportInitializer.install(app)
// TODO: Replace this with await, once esbuild supports top-level await
void configureTsyringe().then(() => {
const passportInitializer = container.resolve(PassportInitializer)
passportInitializer.initialize()
passportInitializer.install(app)

const server = new ApolloServer({
schema: loadSchema(),
context: buildContext,
introspection: true,
plugins: [
// Enable Apollo Studio in development, and also in production (at least for now)
ApolloServerPluginLandingPageLocalDefault({ footer: false }),
// Gracefully shutdown HTTP server when Apollo server terminates
ApolloServerPluginDrainHttpServer({ httpServer }),
],
})
const server = new ApolloServer({
schema: loadSchema(),
context: buildContext,
introspection: true,
plugins: [
// Enable Apollo Studio in development, and also in production (at least for now)
ApolloServerPluginLandingPageLocalDefault({ footer: false }),
// Gracefully shutdown HTTP server when Apollo server terminates
ApolloServerPluginDrainHttpServer({ httpServer }),
],
})

async function startServer() {
await server.start()
server.applyMiddleware({ app, path: '/' })
}
void startServer()
async function startServer() {
await server.start()
server.applyMiddleware({ app, path: '/' })
}
void startServer()
})

module.exports = app
export default app
20 changes: 11 additions & 9 deletions api/tsyringe.config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import 'reflect-metadata'
import { PrismaClient } from '@prisma/client'

import prisma from '@prisma/client'
import { container, instanceCachingFactory } from 'tsyringe'
import { createRedisClient } from './utils/services.factory'

container.register<PrismaClient>('PrismaClient', {
useFactory: instanceCachingFactory<PrismaClient>(() => new PrismaClient()),
})
const { PrismaClient } = prisma

export async function configure(): Promise<void> {
container.register('PrismaClient', {
useFactory: instanceCachingFactory(() => new PrismaClient()),
})

container.register('RedisClient', {
useValue: await createRedisClient(),
})
container.register('RedisClient', {
useValue: await createRedisClient(),
})
}
21 changes: 15 additions & 6 deletions api/user/passport-initializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import session from 'express-session'
import passport from 'passport'
import { RedisClientType } from 'redis'
import { inject, injectable } from 'tsyringe'
import { config, Environment } from '../../config'
import { AuthService } from './auth.service'
import EmailStrategy from './auth.email.strategy'
import config from '#config'
import { Environment } from '~/config'

@injectable()
export default class PassportInitializer {
Expand All @@ -26,15 +27,23 @@ export default class PassportInitializer {
}

install(app: Express): void {
// TODO: Use redis store also for development as soon as https://github.com/tj/connect-redis/issues/336 is fixed (and mock-redis is compatible with redis v4)
let store
if (config.environment === Environment.Production) {
const RedisStore = connectRedis(session)
store = new RedisStore({
client: this.redisClient,
disableTouch: true,
})
} else {
store = new session.MemoryStore()
}

// Add middleware that sends and receives the session ID using cookies
// See https://github.com/expressjs/session#readme
const RedisStore = connectRedis(session)
app.use(
session({
store: new RedisStore({
client: this.redisClient,
disableTouch: true,
}),
store,
// The secret used to sign the session cookie
secret: [config.session.primarySecret, config.session.secondarySecret],
// Don't force session to be saved back to the session store unless it was modified
Expand Down
4 changes: 3 additions & 1 deletion api/user/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ export class Mutation {
problems: [
{
path: 'Email or Password',
message: (typeof info === 'string' ? info : info?.message) || 'Unknown error while logging in.',
message:
(typeof info === 'string' ? info : info?.message) ||
'Unknown error while logging in.',
},
],
}
Expand Down
3 changes: 2 additions & 1 deletion api/utils/services.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import { promisify } from 'util'
import redis, { RedisClientType } from 'redis'
import redisMock from 'redis-mock'
import { config, Environment } from '~/config'
import { Environment } from '~/config'
import config from '#config'

export async function createRedisClient(): Promise<RedisClientType<any, any>> {
if (config.environment === Environment.LocalDevelopment) {
Expand Down
2 changes: 1 addition & 1 deletion components/DetailPane.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</div>
</template>
<script lang="ts">
import { computed, defineComponent } from '@nuxtjs/composition-api'
import { defineComponent, computed } from '@vue/composition-api'
import { useUiStore } from './../store'
export default defineComponent({
Expand Down
4 changes: 2 additions & 2 deletions components/DocumentEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@
</div>
</template>

<script>
import { defineComponent, computed } from '@nuxtjs/composition-api'
<script lang="ts">
import { defineComponent, computed } from '@vue/composition-api'
import { useResult, useQuery } from '@vue/apollo-composable'
import Tags from './tagify.vue'
import { gql } from '~/apollo'
Expand Down
4 changes: 2 additions & 2 deletions components/DocumentEditorHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
{{ heading }}
</p>
</template>
<script>
import { defineComponent } from '@nuxtjs/composition-api'
<script lang="ts">
import { defineComponent } from '@vue/composition-api'
export default defineComponent({
props: { heading: { type: String, default: '' } },
Expand Down
4 changes: 2 additions & 2 deletions components/DocumentEditorInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
</span>
</template>

<script>
import { defineComponent } from '@nuxtjs/composition-api'
<script lang="ts">
import { defineComponent } from '@vue/composition-api'
export default defineComponent({
props: ['value'],
methods: {
Expand Down
4 changes: 3 additions & 1 deletion components/DocumentView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ import {
ref,
computed,
toRefs,
} from '@nuxtjs/composition-api'
} from '@vue/composition-api'
import { gql, DocumentType } from '~/apollo'
import { useUiStore } from '~/store'
Expand Down Expand Up @@ -171,6 +171,8 @@ export default defineComponent({
return 'Conference Paper'
case 'Thesis':
return 'PhD Thesis'
default:
return document.value.__typename
}
})
Expand Down
2 changes: 1 addition & 1 deletion components/HorizontalRule.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
style="--bg: white; --p: 0 10px; --trans-x: -50%; --trans-y: -50%"
/>
</template>
<script>
<script lang="ts">
export default {
props: {
content: {
Expand Down
File renamed without changes.
3 changes: 2 additions & 1 deletion components/NavBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@

<script lang="ts">
import { useApolloClient, useMutation } from '@vue/apollo-composable'
import { defineComponent, useRouter, ref, watch } from '@nuxtjs/composition-api'
import { defineComponent, ref, watch } from '@vue/composition-api'
import { useRouter } from '#app'
import { gql } from '~/apollo'
import { useUiStore } from '~/store'
import { cacheCurrentUser } from '~/apollo/cache'
Expand Down
2 changes: 1 addition & 1 deletion components/PasswordInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</div>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from '@nuxtjs/composition-api'
import { computed, defineComponent, ref } from '@vue/composition-api'
export default defineComponent({
props: {
Expand Down
2 changes: 1 addition & 1 deletion components/SideBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from '@nuxtjs/composition-api'
import { defineComponent } from '@vue/composition-api'
import { useResult, useQuery } from '@vue/apollo-composable'
import { BaseTree } from '@he-tree/vue2'
import { gql } from '~/apollo'
Expand Down
2 changes: 1 addition & 1 deletion components/tagify.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<script lang="ts">
import Tagify from '@yaireo/tagify'
import '@yaireo/tagify/dist/tagify.css'
import { defineComponent, PropType } from '@nuxtjs/composition-api'
import { defineComponent, PropType } from '@vue/composition-api'
export default defineComponent({
name: 'TagsInput',
Expand Down
26 changes: 15 additions & 11 deletions config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { PrivateRuntimeConfig } from '@nuxt/schema'

export enum Environment {
/**
* Locally, on the developers machine.
Expand Down Expand Up @@ -31,15 +33,17 @@ function getEnvironment(): Environment {
: Environment.LocalDevelopment
}

export const config = {
environment: getEnvironment(),
redis: {
port: Number(process.env.REDIS_PORT) || 6380,
host: process.env.REDIS_HOST || 'localhost',
password: process.env.REDIS_PASSWORD || 'jabref',
},
session: {
primarySecret: process.env.SESSION_SECRET_PRIMARY || 'session_secret',
secondarySecret: process.env.SESSION_SECRET_SECONDARY || 'session_secret',
},
export function constructPrivateConfig(): PrivateRuntimeConfig {
return {
environment: getEnvironment(),
redis: {
port: Number(process.env.REDIS_PORT) || 6380,
host: process.env.REDIS_HOST || 'localhost',
password: process.env.REDIS_PASSWORD || 'jabref',
},
session: {
primarySecret: process.env.SESSION_SECRET_PRIMARY || 'session_secret',
secondarySecret: process.env.SESSION_SECRET_SECONDARY || 'session_secret',
},
}
}
19 changes: 19 additions & 0 deletions config.types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Environment } from './config'

// Provide custom type information for config, overriding the default empty types.
// TODO: Remove this as soon as https://github.com/nuxt/framework/issues/1785 is resolved.
declare module '@nuxt/schema' {
interface PrivateRuntimeConfig {
environment: Environment
redis: {
port: number
host: string
password: string
}
session: {
primarySecret: string
secondarySecret: string
}
}
}
export {}
Loading

0 comments on commit d00e1ab

Please sign in to comment.