Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ module.exports = {
'no-console': 'warn',
'@typescript-eslint/no-inferrable-types': 'off',
'unused-imports/no-unused-vars': 'off',
'@typescript-eslint/require-await': 'off',
},
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-terser": "^0.4.1",
"@rollup/plugin-typescript": "^11.0.0",
"@types/chai": "^4.3.4",
"@types/mocha": "^10.0.1",
Expand All @@ -64,6 +65,7 @@
"reflect-metadata": "^0.1.13",
"rimraf": "^4.4.1",
"rollup": "^3.20.2",
"rollup-plugin-cleanup": "^3.2.1",
"serve": "^14.2.0",
"shelljs": "^0.8.5",
"simple-git-hooks": "^2.8.1",
Expand Down
109 changes: 108 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 37 additions & 17 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,44 @@ import json from '@rollup/plugin-json'
import typescript from '@rollup/plugin-typescript'
import commonjs from '@rollup/plugin-commonjs'
import resolve from '@rollup/plugin-node-resolve'
import cleanup from 'rollup-plugin-cleanup'
import terser from '@rollup/plugin-terser'

import pkg from './package.json' assert { type: 'json' }

/* @type {import('rollup').RollupOptions} */
export default {
input: 'src/index.ts',
output: [
{ file: pkg.main, name: pkg.name, format: 'umd', sourcemap: true },
{ file: pkg.module, format: 'es', sourcemap: true },
],
external: [],
watch: {
include: 'src/**',
},
plugins: [
json(),
typescript({ declaration: true, declarationDir: 'types', module: 'ESNext' }),
commonjs(),
resolve(),
],
/**
* @param {boolean} minify
* @returns {import('rollup').RollupOptions}
*/
function getConfig(minify) {
let umdFile = pkg.main
let esFile = pkg.module
if (minify) {
umdFile = umdFile.replace(/\.js$/, '.min.js')
esFile = esFile.replace(/\.js$/, '.min.js')
}

return {
input: 'src/index.ts',
output: [
{ file: umdFile, name: pkg.name, format: 'umd', sourcemap: true },
{ file: esFile, format: 'es', sourcemap: true },
],
external: [],
watch: {
include: 'src/**',
},
plugins: [
json(),
typescript({ declaration: true, declarationDir: 'types', module: 'ESNext' }),
commonjs(),
resolve(),
minify ? terser() : cleanup({ extensions: ['js', 'ts'] }),
],
}
}

export default [
getConfig(false),
getConfig(true),
]
20 changes: 20 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export class WormError extends Error {
constructor(message: string) {
super(message)
this.name = 'WormError'
}
}

export class ConnectionError extends WormError {
constructor(message: string) {
super(message)
this.name = 'ConnectionError'
}
}

export class ModelError extends WormError {
constructor(message: string) {
super(message)
this.name = 'ModelError'
}
}
31 changes: 26 additions & 5 deletions src/fields.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { FieldOptions } from './types'
import type { Constructor, FieldOptions, TableDefinition } from './types'
import { _addFieldToMetadata, _handleTableData } from './metadata'
import { ModelError, WormError } from './errors'
import type { Model } from './models'

/**
* Describes a field on a model.
Expand Down Expand Up @@ -39,24 +41,43 @@ import { _addFieldToMetadata, _handleTableData } from './metadata'
export function Field<T>(options: Partial<FieldOptions<T>> = {}): PropertyDecorator {
return function (object, propertyName) {
if (typeof propertyName === 'symbol')
throw new Error('Field decorator doesn\'t support symbols')
throw new WormError('Field decorator doesn\'t support symbols')

// Use "emitDecoratorMetadata" to get the type of the field
const type = Reflect.getMetadata('design:type', object, propertyName) as () => T
let t: () => T
try {
t = (Reflect.getMetadata('design:type', object, propertyName) || Object) as () => T
}
catch {
t = Object
}

if (options.primaryKey && options.nullable)
throw new Error('Primary key cannot be nullable')
throw new ModelError('Primary key cannot be nullable')

// Merge options with default values
const newOptions: FieldOptions<T> = {
primaryKey: false,
unique: false,
nullable: !options.primaryKey,
type,
type: t,
...options,
}

_handleTableData(object)
_addFieldToMetadata(object.constructor.name, propertyName, newOptions)
}
}

/**
* Create a new model from a definition.
* @param name - The name of the model
* @param definition - The definition of the model
* @returns - The new model
*/
export function defineModel<T extends Model>(modelClass: Constructor<T>, definition: TableDefinition) {
for (const field in definition) {
const fieldOpts = definition[field]
Field(fieldOpts)(modelClass.prototype as T, field)
}
}
Loading