@d-mok/quasar-app-extension-quasar-axe 2.2.13 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/install.js +1 -1
- package/src/templates/src/utils/index.ts +1 -2
- package/src/templates/src/utils/puppets/index.ts +1 -2
- package/src/templates/src/utils/puppets/entity.ts +0 -39
- package/src/templates/src/utils/puppets/table.ts +0 -226
- package/src/templates/src/utils/puppets2/builder/index.ts +0 -226
- package/src/templates/src/utils/puppets2/builder/ui.ts +0 -31
- package/src/templates/src/utils/puppets2/core/db.ts +0 -127
- package/src/templates/src/utils/puppets2/core/index.ts +0 -44
- package/src/templates/src/utils/puppets2/index.ts +0 -1
- package/src/templates/src/utils/puppets2/type.ts +0 -15
- /package/src/templates/src/utils/{puppets2 → puppets}/ORM.ts +0 -0
- /package/src/templates/src/utils/{puppets2 → puppets}/test.ts +0 -0
package/package.json
CHANGED
package/src/install.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = function (api) {
|
|
2
2
|
api.compatibleWith('quasar', '^2.0.0')
|
|
3
|
-
api.compatibleWith('@quasar/app-vite', '^1.0.0')
|
|
3
|
+
api.compatibleWith('@quasar/app-vite', '^1.0.0 || ^2.0.0')
|
|
4
4
|
api.render('./templates')
|
|
5
5
|
api.onExitLog('Thanks for installing quasar-axe!')
|
|
6
6
|
}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { TABLE } from './table'
|
|
1
|
+
export { ORM } from './ORM'
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { DeleteBuilder, UpdateBuilder } from './builder'
|
|
2
|
-
import { Constructor, BooleanKeys } from './type'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @deprecated
|
|
6
|
-
*/
|
|
7
|
-
export function ENTITY<
|
|
8
|
-
TBase extends Constructor,
|
|
9
|
-
K extends string & keyof R,
|
|
10
|
-
R extends InstanceType<TBase> = InstanceType<TBase>
|
|
11
|
-
>(RowClass: TBase, tableName: string, idKey: K) {
|
|
12
|
-
return class extends RowClass {
|
|
13
|
-
static _RowClass = RowClass
|
|
14
|
-
static _tableName = tableName
|
|
15
|
-
static _idKey: K = idKey
|
|
16
|
-
static _fields: any[] = Object.keys(new RowClass())
|
|
17
|
-
|
|
18
|
-
constructor(...args: any[]) {
|
|
19
|
-
super(...args)
|
|
20
|
-
let template = args[0] ?? {}
|
|
21
|
-
Object.assign(this, template)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
update(row: Partial<R>): UpdateBuilder<any, R> {
|
|
25
|
-
// @ts-ignore
|
|
26
|
-
return this._hostTable.update(this[idKey], row)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
delete(): DeleteBuilder<any, R> {
|
|
30
|
-
// @ts-ignore
|
|
31
|
-
return this._hostTable.delete(this[idKey])
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
toggle(key: BooleanKeys<R>): UpdateBuilder<any, R> {
|
|
35
|
-
// @ts-ignore
|
|
36
|
-
return this._hostTable.update(this[idKey], { [key]: !this[key] })
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DeleteBuilder,
|
|
3
|
-
InsertBuilder,
|
|
4
|
-
SelectBuilder,
|
|
5
|
-
SelectInBuilder,
|
|
6
|
-
SelectRPCBuilder,
|
|
7
|
-
UpdateBuilder,
|
|
8
|
-
UpsertBuilder,
|
|
9
|
-
} from './builder'
|
|
10
|
-
import { Constructor, Key } from './type'
|
|
11
|
-
import { Core } from './core'
|
|
12
|
-
import { reactive } from 'vue'
|
|
13
|
-
|
|
14
|
-
type imprinted<R extends object> = {
|
|
15
|
-
_RowClass: Constructor
|
|
16
|
-
_tableName: string
|
|
17
|
-
_idKey: string & keyof R
|
|
18
|
-
_fields: any[]
|
|
19
|
-
}
|
|
20
|
-
type EntityClass<T extends R, R extends object> = Constructor<T> & imprinted<R>
|
|
21
|
-
type RowOf<E extends EntityClass<any, any>> = InstanceType<E['_RowClass']>
|
|
22
|
-
|
|
23
|
-
function logCreate(tableName: string, idKey: string, entityName: string) {
|
|
24
|
-
console.dev(
|
|
25
|
-
`Create Table [${tableName}] idKey [${idKey}] entity [${entityName}]`
|
|
26
|
-
)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (process.env.DEBUGGING) {
|
|
30
|
-
// @ts-ignore
|
|
31
|
-
globalThis.TABLES = []
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @deprecated
|
|
36
|
-
*/
|
|
37
|
-
export function TABLE<
|
|
38
|
-
ClassT extends EntityClass<T, R>,
|
|
39
|
-
R extends RowOf<ClassT> = RowOf<ClassT>,
|
|
40
|
-
T extends R = InstanceType<ClassT>
|
|
41
|
-
>(EntityClass: ClassT) {
|
|
42
|
-
const tableName: string = EntityClass._tableName
|
|
43
|
-
const idKey: ClassT['_idKey'] = EntityClass._idKey
|
|
44
|
-
const fields: any[] = EntityClass._fields
|
|
45
|
-
|
|
46
|
-
logCreate(tableName, idKey, EntityClass.name)
|
|
47
|
-
|
|
48
|
-
function convertor(host: any) {
|
|
49
|
-
return ($: R) => {
|
|
50
|
-
let T = new EntityClass($)
|
|
51
|
-
// @ts-ignore
|
|
52
|
-
T._hostTable = host
|
|
53
|
-
return T
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function core(host: any) {
|
|
58
|
-
return new Core<T, R>(tableName, idKey, fields, convertor(host))
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return class extends Array<T> {
|
|
62
|
-
/** make reactive */
|
|
63
|
-
reactive(): this {
|
|
64
|
-
const rec = reactive(this) as this
|
|
65
|
-
if (process.env.DEBUGGING) {
|
|
66
|
-
// @ts-ignore
|
|
67
|
-
globalThis.TABLES.push(rec)
|
|
68
|
-
}
|
|
69
|
-
return rec
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
protected onChange(): any {}
|
|
73
|
-
protected onEdit(): any {}
|
|
74
|
-
protected onSanitize(row: Partial<R>): Partial<R> {
|
|
75
|
-
return row
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
select() {
|
|
79
|
-
let callback = ($: T[]) => {
|
|
80
|
-
this.set($)
|
|
81
|
-
this.onChange()
|
|
82
|
-
}
|
|
83
|
-
return new SelectBuilder(core(this), callback)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
patch() {
|
|
87
|
-
let callback = ($: T[]) => {
|
|
88
|
-
this.absorb($, idKey)
|
|
89
|
-
this.onChange()
|
|
90
|
-
}
|
|
91
|
-
return new SelectBuilder(core(this), callback)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
selectIn<K extends Key<R>>(key: K, vals: R[K][]) {
|
|
95
|
-
let callback = ($: T[]) => {
|
|
96
|
-
this.set($)
|
|
97
|
-
this.sortBy($ => vals.indexOf($[key]))
|
|
98
|
-
this.onChange()
|
|
99
|
-
}
|
|
100
|
-
return new SelectInBuilder(key, vals, core(this), callback)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
patchIn<K extends Key<R>>(key: K, vals: R[K][]) {
|
|
104
|
-
let callback = ($: T[]) => {
|
|
105
|
-
this.absorb($, idKey)
|
|
106
|
-
this.sortBy($ => vals.indexOf($[key]))
|
|
107
|
-
this.onChange()
|
|
108
|
-
}
|
|
109
|
-
return new SelectInBuilder(key, vals, core(this), callback)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
selectRPC(param: object = {}) {
|
|
113
|
-
let callback = ($: T[]) => {
|
|
114
|
-
this.set($)
|
|
115
|
-
this.onChange()
|
|
116
|
-
}
|
|
117
|
-
return new SelectRPCBuilder(param, core(this), callback)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
patchRPC(param: object = {}) {
|
|
121
|
-
let callback = ($: T[]) => {
|
|
122
|
-
this.absorb($, idKey)
|
|
123
|
-
this.onChange()
|
|
124
|
-
}
|
|
125
|
-
return new SelectRPCBuilder(param, core(this), callback)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
selectCustom(rows: R[]) {
|
|
129
|
-
let convert = core(this).convertor
|
|
130
|
-
let entities = rows.map(convert)
|
|
131
|
-
this.set(entities)
|
|
132
|
-
this.onChange()
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
insert(row: Partial<R>) {
|
|
136
|
-
row = this.onSanitize(row)
|
|
137
|
-
let callback = ($: T[]) => {
|
|
138
|
-
this.push(...$)
|
|
139
|
-
this.onChange()
|
|
140
|
-
this.onEdit()
|
|
141
|
-
}
|
|
142
|
-
return new InsertBuilder([row], core(this), callback).notify(
|
|
143
|
-
'Created!'
|
|
144
|
-
)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
insertMany(rows: Partial<R>[]) {
|
|
148
|
-
rows = rows.map(this.onSanitize)
|
|
149
|
-
let callback = ($: T[]) => {
|
|
150
|
-
this.push(...$)
|
|
151
|
-
this.onChange()
|
|
152
|
-
this.onEdit()
|
|
153
|
-
}
|
|
154
|
-
return new InsertBuilder(rows, core(this), callback).notify(
|
|
155
|
-
'Created!'
|
|
156
|
-
)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
update(idVal: R[ClassT['_idKey']], row: Partial<R>) {
|
|
160
|
-
row = this.onSanitize(row)
|
|
161
|
-
let callback = ($: T[]) => {
|
|
162
|
-
this.merge($, idKey)
|
|
163
|
-
this.onChange()
|
|
164
|
-
this.onEdit()
|
|
165
|
-
}
|
|
166
|
-
return new UpdateBuilder(idVal, row, core(this), callback).notify(
|
|
167
|
-
'Updated!'
|
|
168
|
-
)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
delete(idVal: R[ClassT['_idKey']]) {
|
|
172
|
-
let callback = ($: T[]) => {
|
|
173
|
-
this.remove($ => $[idKey] === idVal)
|
|
174
|
-
this.onChange()
|
|
175
|
-
this.onEdit()
|
|
176
|
-
}
|
|
177
|
-
return new DeleteBuilder(idVal, core(this), callback).notify(
|
|
178
|
-
'Deleted!'
|
|
179
|
-
)
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
upsert(row: Partial<R>, conflictKeys: Key<R>[]) {
|
|
183
|
-
row = this.onSanitize(row)
|
|
184
|
-
let callback = ($: T[]) => {
|
|
185
|
-
this.absorb($, idKey)
|
|
186
|
-
this.onChange()
|
|
187
|
-
this.onEdit()
|
|
188
|
-
}
|
|
189
|
-
return new UpsertBuilder(
|
|
190
|
-
row,
|
|
191
|
-
conflictKeys,
|
|
192
|
-
core(this),
|
|
193
|
-
callback
|
|
194
|
-
).notify('Updated!')
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// // example
|
|
200
|
-
|
|
201
|
-
// class StudentRow {
|
|
202
|
-
// public name: string = ''
|
|
203
|
-
// public class: string = ''
|
|
204
|
-
// public num: number = 0
|
|
205
|
-
// public pass: boolean = false
|
|
206
|
-
// public pasds: boolean = false
|
|
207
|
-
// }
|
|
208
|
-
|
|
209
|
-
// class Student extends ENTITY(StudentRow, 'student', 'num') {
|
|
210
|
-
// public full = this.class + this.name
|
|
211
|
-
// }
|
|
212
|
-
|
|
213
|
-
// let s = new Student()
|
|
214
|
-
// // s.ful
|
|
215
|
-
// s.toggle('pass')
|
|
216
|
-
|
|
217
|
-
// class StudentsCollection extends TABLE(Student) {
|
|
218
|
-
// protected override onChange() {
|
|
219
|
-
// return 1
|
|
220
|
-
// }
|
|
221
|
-
// }
|
|
222
|
-
|
|
223
|
-
// let ss = new StudentsCollection()
|
|
224
|
-
// ss.select().eq('name', 'a')
|
|
225
|
-
// ss.insert({ name: 'a' })
|
|
226
|
-
// ss.delete(1)
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
import { Core } from '../core'
|
|
2
|
-
import { Filter, Key } from '../type'
|
|
3
|
-
import { ui } from './ui'
|
|
4
|
-
|
|
5
|
-
type Promisable<T> = T | PromiseLike<T>
|
|
6
|
-
|
|
7
|
-
type onfulfilled<T, U> = ((value: T) => Promisable<U>) | undefined | null
|
|
8
|
-
|
|
9
|
-
type onrejected<U> = ((reason: any) => Promisable<U>) | undefined | null
|
|
10
|
-
|
|
11
|
-
abstract class BuilderUI {
|
|
12
|
-
private isSlience: boolean = false
|
|
13
|
-
private isConfirm: boolean = false
|
|
14
|
-
private confirmContent: { title: string; msg: string } = {
|
|
15
|
-
title: '',
|
|
16
|
-
msg: '',
|
|
17
|
-
}
|
|
18
|
-
private isNotify: boolean = false
|
|
19
|
-
private notifyContent: string = ''
|
|
20
|
-
|
|
21
|
-
protected abstract dataLogic(): Promise<void>
|
|
22
|
-
|
|
23
|
-
protected async run() {
|
|
24
|
-
if (this.isSlience) ui.loadingOff()
|
|
25
|
-
|
|
26
|
-
if (this.isConfirm) {
|
|
27
|
-
let { title, msg } = this.confirmContent
|
|
28
|
-
await ui.onConfirm(title, msg)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
await this.dataLogic()
|
|
32
|
-
|
|
33
|
-
if (this.isNotify) ui.onNotify(this.notifyContent)
|
|
34
|
-
|
|
35
|
-
if (this.isSlience) ui.loadingOn()
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
confirm(title: string, ...msgs: string[]): this {
|
|
39
|
-
this.isConfirm = true
|
|
40
|
-
this.confirmContent = { title, msg: msgs.join('<br/>') }
|
|
41
|
-
return this
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
notify(msg: string): this {
|
|
45
|
-
this.isNotify = true
|
|
46
|
-
this.notifyContent = msg
|
|
47
|
-
return this
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
mute(): this {
|
|
51
|
-
this.isNotify = false
|
|
52
|
-
return this
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
slience(): this {
|
|
56
|
-
this.isSlience = true
|
|
57
|
-
this.isNotify = false
|
|
58
|
-
return this
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
abstract class Builder<T, R> extends BuilderUI implements PromiseLike<void> {
|
|
63
|
-
constructor(
|
|
64
|
-
protected core: Core<T, R>,
|
|
65
|
-
private callback: (objs: T[]) => void
|
|
66
|
-
) {
|
|
67
|
-
super()
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
protected abstract logType: string
|
|
71
|
-
|
|
72
|
-
protected abstract fetch(): Promise<R[]>
|
|
73
|
-
|
|
74
|
-
protected override async dataLogic(): Promise<void> {
|
|
75
|
-
let data = await this.fetch()
|
|
76
|
-
let entities = data.map($ => this.core.convertor($))
|
|
77
|
-
this.callback(entities)
|
|
78
|
-
ui.log(this.core.tableName, this.logType, entities)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async then<Y, N>(
|
|
82
|
-
onfulfilled?: onfulfilled<void, Y>,
|
|
83
|
-
onrejected?: onrejected<N>
|
|
84
|
-
): Promise<Y | N> {
|
|
85
|
-
return this.run().then(onfulfilled, onrejected)
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
abstract class FilterBuilder<T, R> extends Builder<T, R> {
|
|
90
|
-
protected filters: Filter<R>[] = []
|
|
91
|
-
|
|
92
|
-
eq<K extends Key<R>>(key: K, val: R[K]): this {
|
|
93
|
-
this.filters.push({ type: 'eq', payload: { key, val } })
|
|
94
|
-
return this
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
in<K extends Key<R>>(key: K, vals: R[K][]): this {
|
|
98
|
-
this.filters.push({ type: 'in', payload: { key, vals } })
|
|
99
|
-
return this
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
like<K extends Key<R>>(key: K, pattern: string): this {
|
|
103
|
-
this.filters.push({ type: 'like', payload: { key, pattern } })
|
|
104
|
-
return this
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
limit(count: number): this {
|
|
108
|
-
this.filters.push({ type: 'limit', payload: count })
|
|
109
|
-
return this
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
order<K extends Key<R>>(key: K, ascending: boolean = true): this {
|
|
113
|
-
this.filters.push({ type: 'order', payload: { key, asc: ascending } })
|
|
114
|
-
return this
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export class SelectBuilder<T, R> extends FilterBuilder<T, R> {
|
|
119
|
-
protected logType = 'select'
|
|
120
|
-
|
|
121
|
-
protected override async fetch() {
|
|
122
|
-
return this.core.fetchSelect(this.filters)
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export class SelectInBuilder<T, R, K extends Key<R>> extends FilterBuilder<
|
|
127
|
-
T,
|
|
128
|
-
R
|
|
129
|
-
> {
|
|
130
|
-
protected logType = 'selectIn'
|
|
131
|
-
|
|
132
|
-
constructor(
|
|
133
|
-
private key: K,
|
|
134
|
-
private vals: R[K][],
|
|
135
|
-
core: Core<T, R>,
|
|
136
|
-
callback: (objs: T[]) => void
|
|
137
|
-
) {
|
|
138
|
-
super(core, callback)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
protected override async fetch() {
|
|
142
|
-
return this.core.fetchSelectIn(this.key, this.vals, this.filters)
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export class SelectRPCBuilder<T, R> extends FilterBuilder<T, R> {
|
|
147
|
-
protected logType = 'rpc'
|
|
148
|
-
|
|
149
|
-
constructor(
|
|
150
|
-
private param: object,
|
|
151
|
-
core: Core<T, R>,
|
|
152
|
-
callback: (objs: T[]) => void
|
|
153
|
-
) {
|
|
154
|
-
super(core, callback)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
protected override async fetch() {
|
|
158
|
-
return this.core.fetchRPC(this.param, this.filters)
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export class InsertBuilder<T, R> extends Builder<T, R> {
|
|
163
|
-
protected logType = 'insert'
|
|
164
|
-
|
|
165
|
-
constructor(
|
|
166
|
-
private rows: Partial<R>[],
|
|
167
|
-
core: Core<T, R>,
|
|
168
|
-
callback: (objs: T[]) => void
|
|
169
|
-
) {
|
|
170
|
-
super(core, callback)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
protected override async fetch() {
|
|
174
|
-
return this.core.fetchInsert(this.rows)
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export class UpdateBuilder<T, R> extends Builder<T, R> {
|
|
179
|
-
protected logType = 'update'
|
|
180
|
-
|
|
181
|
-
constructor(
|
|
182
|
-
private idVal: R[keyof R],
|
|
183
|
-
private row: Partial<R>,
|
|
184
|
-
core: Core<T, R>,
|
|
185
|
-
callback: (objs: T[]) => void
|
|
186
|
-
) {
|
|
187
|
-
super(core, callback)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
protected override async fetch() {
|
|
191
|
-
return this.core.fetchUpdate(this.idVal, this.row)
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export class DeleteBuilder<T, R> extends Builder<T, R> {
|
|
196
|
-
protected logType = 'delete'
|
|
197
|
-
|
|
198
|
-
constructor(
|
|
199
|
-
private idVal: R[keyof R],
|
|
200
|
-
core: Core<T, R>,
|
|
201
|
-
callback: (objs: T[]) => void
|
|
202
|
-
) {
|
|
203
|
-
super(core, callback)
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
protected override async fetch() {
|
|
207
|
-
return this.core.fetchDelete(this.idVal)
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export class UpsertBuilder<T, R> extends Builder<T, R> {
|
|
212
|
-
protected logType = 'upsert'
|
|
213
|
-
|
|
214
|
-
constructor(
|
|
215
|
-
private row: Partial<R>,
|
|
216
|
-
private conflictKeys: Key<R>[],
|
|
217
|
-
core: Core<T, R>,
|
|
218
|
-
callback: (objs: T[]) => void
|
|
219
|
-
) {
|
|
220
|
-
super(core, callback)
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
protected override async fetch() {
|
|
224
|
-
return this.core.fetchUpsert(this.row, this.conflictKeys)
|
|
225
|
-
}
|
|
226
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { qDialog } from '../..'
|
|
2
|
-
import { qNotify } from '../..'
|
|
3
|
-
import { LoadingBar } from 'quasar'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* I am responsible for providing UI interaction functions using Quasar.
|
|
7
|
-
* Purely functional.
|
|
8
|
-
*/
|
|
9
|
-
class UI {
|
|
10
|
-
loadingOff(): void {
|
|
11
|
-
LoadingBar.setDefaults({ size: '0px' })
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
loadingOn(): void {
|
|
15
|
-
setTimeout(() => LoadingBar.setDefaults({ size: '5px' }), 3000)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
onConfirm(title: string, msg: string): Promise<void> {
|
|
19
|
-
return qDialog.confirm(title, msg)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
onNotify(msg: string): void {
|
|
23
|
-
qNotify.toast(msg)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
log(table: string, type: string, data: any[]): void {
|
|
27
|
-
console.dev(`[${table}] ${type}`, data)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const ui = new UI()
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
supabase,
|
|
3
|
-
HANDLE_ERROR,
|
|
4
|
-
PostgrestFilterBuilder,
|
|
5
|
-
} from '../../supabase'
|
|
6
|
-
import { Filter } from '../type'
|
|
7
|
-
|
|
8
|
-
type FilterBuilder = PostgrestFilterBuilder<any, any, any, any>
|
|
9
|
-
|
|
10
|
-
async function send(q: any): Promise<any[]> {
|
|
11
|
-
let { data, error } = await q
|
|
12
|
-
HANDLE_ERROR(data, error)
|
|
13
|
-
return Array.isArray(data) ? data : [data]
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function parseFilters(q: FilterBuilder, filters: Filter[]): FilterBuilder {
|
|
17
|
-
let sortedFilters = filters.sortedBy(f =>
|
|
18
|
-
['eq', 'in', 'like', 'limit', 'order'].indexOf(f.type)
|
|
19
|
-
)
|
|
20
|
-
for (const { type: t, payload: p } of sortedFilters) {
|
|
21
|
-
if (t === 'eq') q = q.eq(p.key, p.val)
|
|
22
|
-
if (t === 'in') q = q.in(p.key, p.vals)
|
|
23
|
-
if (t === 'like') q = q.like(p.key, p.pattern)
|
|
24
|
-
if (t === 'limit') q = q.limit(p)
|
|
25
|
-
if (t === 'order') q = q.order(p.key, { ascending: p.asc })
|
|
26
|
-
}
|
|
27
|
-
return q
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* I am responsible for providing database operation.
|
|
32
|
-
* Purely functional.
|
|
33
|
-
*/
|
|
34
|
-
class DB {
|
|
35
|
-
async select(
|
|
36
|
-
table: string,
|
|
37
|
-
fields: string[],
|
|
38
|
-
filters: Filter[]
|
|
39
|
-
): Promise<any[]> {
|
|
40
|
-
let q = supabase.from(table).select(fields.join(','))
|
|
41
|
-
q = parseFilters(q, filters)
|
|
42
|
-
return send(q)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async selectIn(
|
|
46
|
-
table: string,
|
|
47
|
-
fields: string[],
|
|
48
|
-
key: string,
|
|
49
|
-
vals: any[],
|
|
50
|
-
filters: Filter[]
|
|
51
|
-
): Promise<any[]> {
|
|
52
|
-
let getRows = (chunkPiece: any[]): Promise<any[]> => {
|
|
53
|
-
let q = supabase
|
|
54
|
-
.from(table)
|
|
55
|
-
.select(fields.join(','))
|
|
56
|
-
.in(key, chunkPiece)
|
|
57
|
-
q = parseFilters(q, filters)
|
|
58
|
-
return send(q)
|
|
59
|
-
}
|
|
60
|
-
let promises = vals.chunk(100).map(getRows)
|
|
61
|
-
let result = await Promise.all(promises)
|
|
62
|
-
return result.flat()
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async rpc(fn: string, param: any, filters: Filter[]): Promise<any[]> {
|
|
66
|
-
let q = supabase.rpc(fn, param)
|
|
67
|
-
q = parseFilters(q, filters)
|
|
68
|
-
return send(q)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async insert(table: string, rows: any[]): Promise<any[]> {
|
|
72
|
-
let q = supabase.from(table).insert(rows).select('*')
|
|
73
|
-
return send(q)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async update(
|
|
77
|
-
table: string,
|
|
78
|
-
idKey: string,
|
|
79
|
-
idVal: any,
|
|
80
|
-
row: any
|
|
81
|
-
): Promise<any[]> {
|
|
82
|
-
let q = supabase
|
|
83
|
-
.from(table)
|
|
84
|
-
.update(row)
|
|
85
|
-
.eq(idKey, idVal)
|
|
86
|
-
.select('*')
|
|
87
|
-
.single()
|
|
88
|
-
return send(q)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async delete(table: string, idKey: string, idVal: any): Promise<any[]> {
|
|
92
|
-
let q = supabase
|
|
93
|
-
.from(table)
|
|
94
|
-
.delete()
|
|
95
|
-
.eq(idKey, idVal)
|
|
96
|
-
.select('*')
|
|
97
|
-
.single()
|
|
98
|
-
return send(q)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async upsert(
|
|
102
|
-
table: string,
|
|
103
|
-
idKey: string,
|
|
104
|
-
row: any,
|
|
105
|
-
conflictKeys: (string & keyof typeof row)[]
|
|
106
|
-
): Promise<any[]> {
|
|
107
|
-
let conflict: any = {}
|
|
108
|
-
for (let f of conflictKeys) {
|
|
109
|
-
conflict[f] = row[f]
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
let q = supabase.from(table).select('*').match(conflict)
|
|
113
|
-
let data = await send(q)
|
|
114
|
-
|
|
115
|
-
if (data.length > 1)
|
|
116
|
-
throw 'Fail to upsert! More than 1 rows matching the conflictKeys are found!'
|
|
117
|
-
|
|
118
|
-
if (data.length === 1) {
|
|
119
|
-
let id = data[0][idKey as keyof (typeof data)[0]]
|
|
120
|
-
return await this.update(table, idKey, id, row)
|
|
121
|
-
} else {
|
|
122
|
-
return await this.insert(table, [row])
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export const db = new DB()
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Filter, Key } from '../type'
|
|
2
|
-
import { db } from './db'
|
|
3
|
-
|
|
4
|
-
/** I am responsible for transfering the state from Table to Builders.*/
|
|
5
|
-
export class Core<T, R> {
|
|
6
|
-
constructor(
|
|
7
|
-
public tableName: string,
|
|
8
|
-
public idKey: Key<R>,
|
|
9
|
-
public fields: Key<R>[],
|
|
10
|
-
public convertor: ($: R) => T
|
|
11
|
-
) {}
|
|
12
|
-
|
|
13
|
-
async fetchSelect(filters: Filter<R>[]): Promise<R[]> {
|
|
14
|
-
return db.select(this.tableName, this.fields, filters)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async fetchSelectIn<K extends Key<R>>(
|
|
18
|
-
key: K,
|
|
19
|
-
vals: R[K][],
|
|
20
|
-
filters: Filter<R>[]
|
|
21
|
-
): Promise<R[]> {
|
|
22
|
-
return db.selectIn(this.tableName, this.fields, key, vals, filters)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async fetchRPC(param: object, filters: Filter<R>[]): Promise<R[]> {
|
|
26
|
-
return db.rpc(this.tableName, param, filters)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async fetchInsert(rows: Partial<R>[]): Promise<R[]> {
|
|
30
|
-
return db.insert(this.tableName, rows)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async fetchUpdate(idVal: R[keyof R], row: Partial<R>): Promise<R[]> {
|
|
34
|
-
return db.update(this.tableName, this.idKey, idVal, row)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async fetchDelete(idVal: R[keyof R]): Promise<R[]> {
|
|
38
|
-
return db.delete(this.tableName, this.idKey, idVal)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async fetchUpsert(row: Partial<R>, conflictKeys: Key<R>[]): Promise<R[]> {
|
|
42
|
-
return db.upsert(this.tableName, this.idKey, row, conflictKeys)
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { ORM } from './ORM'
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type Filter<R = any> =
|
|
2
|
-
| { type: 'eq'; payload: { key: Key<R>; val: any } }
|
|
3
|
-
| { type: 'in'; payload: { key: Key<R>; vals: any[] } }
|
|
4
|
-
| { type: 'like'; payload: { key: Key<R>; pattern: string } }
|
|
5
|
-
| { type: 'limit'; payload: number }
|
|
6
|
-
| { type: 'order'; payload: { key: Key<R>; asc: boolean } }
|
|
7
|
-
|
|
8
|
-
export type Constructor<T extends object = {}> = new (...args: any[]) => T
|
|
9
|
-
|
|
10
|
-
export type BooleanKeys<T> = {
|
|
11
|
-
[k in keyof T]: T[k] extends boolean ? k : never
|
|
12
|
-
}[keyof T]
|
|
13
|
-
// type OnlyBoolean<T> = { [k in BooleanKeys<T>]: boolean }
|
|
14
|
-
|
|
15
|
-
export type Key<R> = string & keyof R
|
|
File without changes
|
|
File without changes
|