Skip to content

Commit

Permalink
refactor: error with enum types (#123)
Browse files Browse the repository at this point in the history
* refactor error with enum codes

* fix lint

* rename error 'code' to 'type'

* refactor

* remove INVALID_ROUTE_MATCH

* fix: lint

* fix: remove ErrorTypeMessages in production build

* fix: types

* fix: add interface NavigationRedirectError

* build: use similar config to vue

* refactor: errors

* build: add banner

* refactor: delete old errors.ts

* refactor: rename errors-new

Co-authored-by: Eduardo San Martin Morote <posva13@gmail.com>
  • Loading branch information
fnlctrl and posva authored Mar 18, 2020
1 parent e480383 commit 44486bc
Show file tree
Hide file tree
Showing 12 changed files with 342 additions and 349 deletions.
15 changes: 10 additions & 5 deletions __tests__/errors.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createRouter as newRouter, createMemoryHistory } from '../src'
import { NavigationAborted, NavigationGuardRedirect } from '../src/errors'
import { ErrorTypes } from '../src/errors'
import { components, tick } from './utils'
import { RouteRecord } from '../src/types'

Expand Down Expand Up @@ -47,9 +47,11 @@ describe('Errors', () => {
try {
await router.push('/foo')
} catch (err) {
expect(err).toBeInstanceOf(NavigationAborted)
expect(err.type).toBe(ErrorTypes.NAVIGATION_ABORTED)
}
expect(onError).toHaveBeenCalledWith(expect.any(NavigationAborted))
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({ type: ErrorTypes.NAVIGATION_ABORTED })
)
})

it('triggers erros caused by new navigations of a next(redirect) trigered by history', async () => {
Expand All @@ -69,12 +71,15 @@ describe('Errors', () => {
expect(onError).toHaveBeenCalledTimes(2)
expect(onError).toHaveBeenNthCalledWith(
1,
expect.any(NavigationGuardRedirect)
expect.objectContaining({ type: ErrorTypes.NAVIGATION_GUARD_REDIRECT })
)
expect(onError.mock.calls[0]).toMatchObject([
{ to: { params: { p: '1' } }, from: { fullPath: '/p/0' } },
])
expect(onError).toHaveBeenNthCalledWith(2, expect.any(NavigationAborted))
expect(onError).toHaveBeenNthCalledWith(
2,
expect.objectContaining({ type: ErrorTypes.NAVIGATION_ABORTED })
)
expect(onError.mock.calls[1]).toMatchObject([
{ to: { params: { p: '1' } }, from: { params: { p: 'other' } } },
])
Expand Down
8 changes: 4 additions & 4 deletions __tests__/matcher/__snapshots__/resolve.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Router Matcher resolve LocationAsName throws if the named route does not exists 1`] = `
[NoRouteMatchError: No match for
{"name":"Home"}]
[Error: No match for
{"name":"Home"}]
`;

exports[`Router Matcher resolve LocationAsRelative throws if the current named route does not exists 1`] = `
[NoRouteMatchError: No match for
{"params":{"a":"foo"}}
[Error: No match for
{"params":{"a":"foo"}}
while being at
{"name":"home","params":{},"path":"/","meta":{}}]
`;
4 changes: 2 additions & 2 deletions __tests__/router.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fakePromise from 'faked-promise'
import { createRouter, createMemoryHistory, createWebHistory } from '../src'
import { NavigationCancelled } from '../src/errors'
import { ErrorTypes } from '../src/errors'
import { createDom, components, tick } from './utils'
import {
RouteRecord,
Expand Down Expand Up @@ -225,7 +225,7 @@ describe('Router', () => {
try {
await pA
} catch (err) {
expect(err).toBeInstanceOf(NavigationCancelled)
expect(err.type).toBe(ErrorTypes.NAVIGATION_CANCELLED)
}
expect(router.currentRoute.value.fullPath).toBe('/p/b')
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "4.0.0-alpha.3",
"main": "dist/vue-router.cjs.js",
"browser": "dist/vue-router.esm.js",
"unpkg": "dist/vue-router.js",
"unpkg": "dist/vue-router.global.js",
"module": "dist/vue-router.esm-bundler.js",
"typings": "dist/vue-router.d.ts",
"sideEffects": false,
Expand Down
263 changes: 166 additions & 97 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,119 +1,188 @@
import path from 'path'
import ts from 'rollup-plugin-typescript2'
import replace from '@rollup/plugin-replace'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import ts from 'rollup-plugin-typescript2'
import alias from '@rollup/plugin-alias'
import { terser } from 'rollup-plugin-terser'
import pkg from './package.json'

const pkg = require('./package.json')
const name = pkg.name

const banner = `/*!
* ${pkg.name} v${pkg.version}
* (c) ${new Date().getFullYear()} Eduardo San Martin Morote
* @license MIT
*/`

const exportName = 'VueRouter'

function createEntry(
{
format, // Rollup format (iife, umd, cjs, es)
external = ['vue', '@vue/reactivity', '@vue/runtime-core'], // Rollup external option
input = 'src/index.ts', // entry point
env = 'development', // NODE_ENV variable
minify = false,
isBrowser = false, // produce a browser module version or not
} = {
input: 'src/index.ts',
env: 'development',
minify: false,
isBrowser: false,
}
) {
// force production mode when minifying
if (minify) env = 'production'
const isProductionBuild =
process.env.__DEV__ === 'false' || env === 'production'
// ensure TS checks only once for each build
let hasTSChecked = false

const config = {
input,
plugins: [
replace({
__VERSION__: JSON.stringify(pkg.version),
__DEV__:
(format === 'es' && !isBrowser) || format === 'cjs'
? // preserve to be handled by bundlers
`process.env.NODE_ENV !== 'production'`
: // hard coded dev/prod builds
!isProductionBuild,
}),
alias({
resolve: ['ts'],
}),
],
output: {
banner,
file: 'dist/vue-router.other.js',
format,
globals: {
'@vue/reactivity': 'Vue',
'@vue/runtime-core': 'Vue',
vue: 'Vue',
},
},
}
const outputConfigs = {
// each file name has the format: `dist/${name}.${format}.js`
// format being a key of this object
'esm-bundler': {
file: pkg.module,
format: `es`,
},
cjs: {
file: pkg.main,
format: `cjs`,
},
global: {
file: pkg.unpkg,
format: `iife`,
},
esm: {
file: pkg.browser,
format: `es`,
},
}

if (format === 'iife') {
// config.input = 'src/entries/iife.ts'
config.output.file = pkg.unpkg
config.output.name = exportName
} else if (format === 'es') {
config.output.file = isBrowser ? pkg.browser : pkg.module
} else if (format === 'cjs') {
config.output.file = 'dist/vue-router.cjs.js'
const allFormats = Object.keys(outputConfigs)
// in vue-router there are not that many
const packageFormats = allFormats
const packageConfigs = packageFormats.map(format =>
createConfig(format, outputConfigs[format])
)

// only add the production ready if we are bundling the options
packageFormats.forEach(format => {
if (format === 'cjs') {
packageConfigs.push(createProductionConfig(format))
} else if (format === 'global') {
packageConfigs.push(createMinifiedConfig(format))
}
})

export default packageConfigs

if (!external) {
config.plugins.push(resolve(), commonjs())
} else {
config.external = external
function createConfig(format, output, plugins = []) {
if (!output) {
console.log(require('chalk').yellow(`invalid format: "${format}"`))
process.exit(1)
}

config.plugins.push(
ts({
// only check once, during the es version with browser (it includes external libs)
check: format === 'es' && isBrowser && !minify,
tsconfigOverride: {
compilerOptions: {
// same for d.ts files
declaration: format === 'es' && isBrowser && !minify,
module: 'esnext', // we need to override it because mocha requires this value to be commonjs
target: format === 'iife' || format === 'cjs' ? 'es5' : 'esnext',
},
output.sourcemap = true
output.banner = banner
output.externalLiveBindings = false
output.globals = { vue: 'Vue' }

const isProductionBuild = /\.prod\.js$/.test(output.file)
const isGlobalBuild = format === 'global'
const isRawESMBuild = format === 'esm'
const isNodeBuild = format === 'cjs'
const isBundlerESMBuild = /esm-bundler/.test(format)

if (isGlobalBuild) output.name = 'VueRouter'

const shouldEmitDeclarations = !hasTSChecked

const tsPlugin = ts({
check: !hasTSChecked,
tsconfig: path.resolve(__dirname, 'tsconfig.json'),
cacheRoot: path.resolve(__dirname, 'node_modules/.rts2_cache'),
tsconfigOverride: {
compilerOptions: {
sourceMap: output.sourcemap,
declaration: shouldEmitDeclarations,
declarationMap: shouldEmitDeclarations,
},
})
)
exclude: ['__tests__', 'test-dts'],
},
})
// we only need to check TS and generate declarations once for each build.
// it also seems to run into weird issues when checking multiple times
// during a single build.
hasTSChecked = true

if (minify) {
config.plugins.push(
terser({
module: format === 'es',
// output: {
// preamble: banner,
// },
})
)
config.output.file = config.output.file.replace(/\.js$/i, '.min.js')
const external = ['vue']

const nodePlugins = [resolve(), commonjs()]

return {
input: `src/index.ts`,
// Global and Browser ESM builds inlines everything so that they can be
// used alone.
external,
plugins: [
tsPlugin,
createReplacePlugin(
isProductionBuild,
isBundlerESMBuild,
// isBrowserBuild?
isGlobalBuild || isRawESMBuild || isBundlerESMBuild,
isGlobalBuild,
isNodeBuild
),
...nodePlugins,
...plugins,
],
output,
// onwarn: (msg, warn) => {
// if (!/Circular/.test(msg)) {
// warn(msg)
// }
// },
}
}

return config
function createReplacePlugin(
isProduction,
isBundlerESMBuild,
isBrowserBuild,
isGlobalBuild,
isNodeBuild
) {
const replacements = {
__COMMIT__: `"${process.env.COMMIT}"`,
__VERSION__: `"${pkg.version}"`,
__DEV__: isBundlerESMBuild
? // preserve to be handled by bundlers
`(process.env.NODE_ENV !== 'production')`
: // hard coded dev/prod builds
!isProduction,
// this is only used during tests
__TEST__: isBundlerESMBuild ? `(process.env.NODE_ENV === 'test')` : false,
// If the build is expected to run directly in the browser (global / esm builds)
__BROWSER__: isBrowserBuild,
// is targeting bundlers?
__BUNDLER__: isBundlerESMBuild,
__GLOBAL__: isGlobalBuild,
// is targeting Node (SSR)?
__NODE_JS__: isNodeBuild,
}
// allow inline overrides like
//__RUNTIME_COMPILE__=true yarn build
Object.keys(replacements).forEach(key => {
if (key in process.env) {
replacements[key] = process.env[key]
}
})
return replace(replacements)
}

function createProductionConfig(format) {
return createConfig(format, {
file: `dist/${name}.${format}.prod.js`,
format: outputConfigs[format].format,
})
}

export default [
// browser-friendly UMD build
createEntry({ format: 'iife' }),
createEntry({ format: 'iife', minify: true }),
createEntry({ format: 'cjs' }),
// TODO: prod vs env
createEntry({ format: 'es' }),
createEntry({ format: 'es', isBrowser: true }),
]
function createMinifiedConfig(format) {
const { terser } = require('rollup-plugin-terser')
return createConfig(
format,
{
file: `dist/${name}.${format}.prod.js`,
format: outputConfigs[format].format,
},
[
terser({
module: /^esm/.test(format),
compress: {
ecma: 2015,
pure_getters: true,
},
}),
]
)
}
Loading

0 comments on commit 44486bc

Please sign in to comment.