@d-mok/quasar-app-extension-quasar-axe 2.1.7 → 2.1.9
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 +2 -2
- package/src/templates/src/utils/index.ts +0 -2
- package/src/templates/src/utils/puppets/builder/index.ts +7 -7
- package/src/templates/src/utils/puppets/core/db.ts +59 -88
- package/src/templates/src/utils/puppets/core/index.ts +5 -8
- package/src/templates/src/utils/puppets/entity.ts +4 -10
- package/src/templates/src/utils/puppets/table.ts +11 -39
- package/src/templates/src/utils/puppets/type.ts +7 -5
- package/src/templates/src/utils/supabase.ts +45 -60
- package/src/templates/src/utils/settings.ts +0 -20
- package/src/templates/src/utils/supabase2.ts +0 -128
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@d-mok/quasar-app-extension-quasar-axe",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.9",
|
|
4
4
|
"description": "A Quasar App Extension",
|
|
5
5
|
"author": "d-mok <49301824+d-mok@users.noreply.github.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@handsontable/vue3": "^12.1.0",
|
|
18
|
-
"@supabase/supabase-js": "^
|
|
18
|
+
"@supabase/supabase-js": "^2.24.0",
|
|
19
19
|
"@types/lodash": "^4.14.182",
|
|
20
20
|
"@types/papaparse": "^5.3.2",
|
|
21
21
|
"@types/webpack-env": "^1.17.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Core } from '../core'
|
|
2
|
-
import { Filter } from '../type'
|
|
2
|
+
import { Filter, Key } from '../type'
|
|
3
3
|
import { ui } from './ui'
|
|
4
4
|
|
|
5
5
|
type Promisable<T> = T | PromiseLike<T>
|
|
@@ -89,17 +89,17 @@ abstract class Builder<T, R> extends BuilderUI implements PromiseLike<void> {
|
|
|
89
89
|
abstract class FilterBuilder<T, R> extends Builder<T, R> {
|
|
90
90
|
protected filters: Filter<R>[] = []
|
|
91
91
|
|
|
92
|
-
eq<K extends
|
|
92
|
+
eq<K extends Key<R>>(key: K, val: R[K]): this {
|
|
93
93
|
this.filters.push({ type: 'eq', payload: { key, val } })
|
|
94
94
|
return this
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
in<K extends
|
|
97
|
+
in<K extends Key<R>>(key: K, vals: R[K][]): this {
|
|
98
98
|
this.filters.push({ type: 'in', payload: { key, vals } })
|
|
99
99
|
return this
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
like<K extends
|
|
102
|
+
like<K extends Key<R>>(key: K, pattern: string): this {
|
|
103
103
|
this.filters.push({ type: 'like', payload: { key, pattern } })
|
|
104
104
|
return this
|
|
105
105
|
}
|
|
@@ -109,7 +109,7 @@ abstract class FilterBuilder<T, R> extends Builder<T, R> {
|
|
|
109
109
|
return this
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
order<K extends
|
|
112
|
+
order<K extends Key<R>>(key: K, ascending: boolean = true): this {
|
|
113
113
|
this.filters.push({ type: 'order', payload: { key, asc: ascending } })
|
|
114
114
|
return this
|
|
115
115
|
}
|
|
@@ -123,7 +123,7 @@ export class SelectBuilder<T, R> extends FilterBuilder<T, R> {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
export class SelectInBuilder<T, R, K extends
|
|
126
|
+
export class SelectInBuilder<T, R, K extends Key<R>> extends FilterBuilder<
|
|
127
127
|
T,
|
|
128
128
|
R
|
|
129
129
|
> {
|
|
@@ -213,7 +213,7 @@ export class UpsertBuilder<T, R> extends Builder<T, R> {
|
|
|
213
213
|
|
|
214
214
|
constructor(
|
|
215
215
|
private row: Partial<R>,
|
|
216
|
-
private conflictKeys:
|
|
216
|
+
private conflictKeys: Key<R>[],
|
|
217
217
|
core: Core<T, R>,
|
|
218
218
|
callback: (objs: T[]) => void
|
|
219
219
|
) {
|
|
@@ -5,57 +5,26 @@ import {
|
|
|
5
5
|
PostgrestSingleResponse,
|
|
6
6
|
} from '../../supabase'
|
|
7
7
|
import { Filter } from '../type'
|
|
8
|
-
import _ from 'lodash'
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
let { data, error } = await q
|
|
12
|
-
HANDLE_ERROR(data, error)
|
|
13
|
-
return data
|
|
14
|
-
}
|
|
9
|
+
type FilterBuilder = PostgrestFilterBuilder<any, any, any, any>
|
|
15
10
|
|
|
16
|
-
async function
|
|
17
|
-
q: PromiseLike<PostgrestSingleResponse<R>>
|
|
18
|
-
): Promise<R[]> {
|
|
11
|
+
async function send(q: any): Promise<any[]> {
|
|
19
12
|
let { data, error } = await q
|
|
20
13
|
HANDLE_ERROR(data, error)
|
|
21
|
-
return [data]
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function parseFilter<R>(
|
|
25
|
-
q: PostgrestFilterBuilder<R>,
|
|
26
|
-
filter: Filter<R>
|
|
27
|
-
): PostgrestFilterBuilder<R> {
|
|
28
|
-
if (filter.type === 'eq') q = q.eq(filter.payload.key, filter.payload.val)
|
|
29
|
-
if (filter.type === 'in') q = q.in(filter.payload.key, filter.payload.vals)
|
|
30
|
-
if (filter.type === 'like')
|
|
31
|
-
q = q.like(filter.payload.key, filter.payload.pattern)
|
|
32
|
-
return q
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function parseLimit<R>(
|
|
36
|
-
q: PostgrestFilterBuilder<R>,
|
|
37
|
-
filter: Filter<R>
|
|
38
|
-
): PostgrestFilterBuilder<R> {
|
|
39
|
-
if (filter.type === 'limit') q = q.limit(filter.payload)
|
|
40
|
-
return q
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function parseOrder<R>(
|
|
44
|
-
q: PostgrestFilterBuilder<R>,
|
|
45
|
-
filter: Filter<R>
|
|
46
|
-
): PostgrestFilterBuilder<R> {
|
|
47
|
-
if (filter.type === 'order')
|
|
48
|
-
q = q.order(filter.payload.key, { ascending: filter.payload.asc })
|
|
49
|
-
return q
|
|
14
|
+
return Array.isArray(data) ? data : [data]
|
|
50
15
|
}
|
|
51
16
|
|
|
52
|
-
function parseFilters
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
)
|
|
56
|
-
for (const
|
|
57
|
-
|
|
58
|
-
|
|
17
|
+
function parseFilters(q: FilterBuilder, filters: Filter[]): FilterBuilder {
|
|
18
|
+
let sortedFilters = filters.sortedBy(f =>
|
|
19
|
+
['eq', 'in', 'like', 'limit', 'order'].indexOf(f.type)
|
|
20
|
+
)
|
|
21
|
+
for (const { type: t, payload: p } of sortedFilters) {
|
|
22
|
+
if (t === 'eq') q = q.eq(p.key, p.val)
|
|
23
|
+
if (t === 'in') q = q.in(p.key, p.vals)
|
|
24
|
+
if (t === 'like') q = q.like(p.key, p.pattern)
|
|
25
|
+
if (t === 'limit') q = q.limit(p)
|
|
26
|
+
if (t === 'order') q = q.order(p.key, { ascending: p.asc })
|
|
27
|
+
}
|
|
59
28
|
return q
|
|
60
29
|
}
|
|
61
30
|
|
|
@@ -64,89 +33,91 @@ function parseFilters<R>(
|
|
|
64
33
|
* Purely functional.
|
|
65
34
|
*/
|
|
66
35
|
class DB {
|
|
67
|
-
async select
|
|
36
|
+
async select(
|
|
68
37
|
table: string,
|
|
69
|
-
fields:
|
|
70
|
-
filters: Filter
|
|
71
|
-
): Promise<
|
|
72
|
-
let q = supabase.from
|
|
38
|
+
fields: string[],
|
|
39
|
+
filters: Filter[]
|
|
40
|
+
): Promise<any[]> {
|
|
41
|
+
let q = supabase.from(table).select(fields.join(','))
|
|
73
42
|
q = parseFilters(q, filters)
|
|
74
43
|
return send(q)
|
|
75
44
|
}
|
|
76
45
|
|
|
77
|
-
async selectIn
|
|
46
|
+
async selectIn(
|
|
78
47
|
table: string,
|
|
79
|
-
fields:
|
|
80
|
-
key:
|
|
81
|
-
vals:
|
|
82
|
-
filters: Filter
|
|
83
|
-
): Promise<
|
|
84
|
-
let getRows = (chunkPiece:
|
|
48
|
+
fields: string[],
|
|
49
|
+
key: string,
|
|
50
|
+
vals: any[],
|
|
51
|
+
filters: Filter[]
|
|
52
|
+
): Promise<any[]> {
|
|
53
|
+
let getRows = (chunkPiece: any[]): Promise<any[]> => {
|
|
85
54
|
let q = supabase
|
|
86
|
-
.from
|
|
55
|
+
.from(table)
|
|
87
56
|
.select(fields.join(','))
|
|
88
57
|
.in(key, chunkPiece)
|
|
89
58
|
q = parseFilters(q, filters)
|
|
90
59
|
return send(q)
|
|
91
60
|
}
|
|
92
|
-
let promises =
|
|
61
|
+
let promises = vals.chunk(100).map(getRows)
|
|
93
62
|
let result = await Promise.all(promises)
|
|
94
63
|
return result.flat()
|
|
95
64
|
}
|
|
96
65
|
|
|
97
|
-
async rpc<
|
|
98
|
-
fn
|
|
99
|
-
param: object,
|
|
100
|
-
filters: Filter<R>[]
|
|
101
|
-
): Promise<R[]> {
|
|
102
|
-
let q = supabase.rpc<R>(fn, param)
|
|
66
|
+
async rpc(fn: string, param: any, filters: Filter[]): Promise<any[]> {
|
|
67
|
+
let q = supabase.rpc(fn, param)
|
|
103
68
|
q = parseFilters(q, filters)
|
|
104
69
|
return send(q)
|
|
105
70
|
}
|
|
106
71
|
|
|
107
|
-
async insert
|
|
108
|
-
let q = supabase.from
|
|
72
|
+
async insert(table: string, rows: any[]): Promise<any[]> {
|
|
73
|
+
let q = supabase.from(table).insert(rows).select('*')
|
|
109
74
|
return send(q)
|
|
110
75
|
}
|
|
111
76
|
|
|
112
|
-
async update
|
|
77
|
+
async update(
|
|
113
78
|
table: string,
|
|
114
|
-
idKey:
|
|
115
|
-
idVal:
|
|
116
|
-
row:
|
|
117
|
-
): Promise<
|
|
118
|
-
let q = supabase
|
|
119
|
-
|
|
79
|
+
idKey: string,
|
|
80
|
+
idVal: any,
|
|
81
|
+
row: any
|
|
82
|
+
): Promise<any[]> {
|
|
83
|
+
let q = supabase
|
|
84
|
+
.from(table)
|
|
85
|
+
.update(row)
|
|
86
|
+
.eq(idKey, idVal)
|
|
87
|
+
.select('*')
|
|
88
|
+
.single()
|
|
89
|
+
return send(q)
|
|
120
90
|
}
|
|
121
91
|
|
|
122
|
-
async delete
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
92
|
+
async delete(table: string, idKey: string, idVal: any): Promise<any[]> {
|
|
93
|
+
let q = supabase
|
|
94
|
+
.from(table)
|
|
95
|
+
.delete()
|
|
96
|
+
.eq(idKey, idVal)
|
|
97
|
+
.select('*')
|
|
98
|
+
.single()
|
|
99
|
+
return send(q)
|
|
129
100
|
}
|
|
130
101
|
|
|
131
|
-
async upsert
|
|
102
|
+
async upsert(
|
|
132
103
|
table: string,
|
|
133
|
-
idKey:
|
|
134
|
-
row:
|
|
135
|
-
conflictKeys: (keyof
|
|
136
|
-
): Promise<
|
|
104
|
+
idKey: string,
|
|
105
|
+
row: any,
|
|
106
|
+
conflictKeys: (string & keyof typeof row)[]
|
|
107
|
+
): Promise<any[]> {
|
|
137
108
|
let conflict: any = {}
|
|
138
109
|
for (let f of conflictKeys) {
|
|
139
110
|
conflict[f] = row[f]
|
|
140
111
|
}
|
|
141
112
|
|
|
142
|
-
let q = supabase.from
|
|
113
|
+
let q = supabase.from(table).select('*').match(conflict)
|
|
143
114
|
let data = await send(q)
|
|
144
115
|
|
|
145
116
|
if (data.length > 1)
|
|
146
117
|
throw 'Fail to upsert! More than 1 rows matching the conflictKeys are found!'
|
|
147
118
|
|
|
148
119
|
if (data.length === 1) {
|
|
149
|
-
let id = data[0][idKey]
|
|
120
|
+
let id = data[0][idKey as keyof (typeof data)[0]]
|
|
150
121
|
return await this.update(table, idKey, id, row)
|
|
151
122
|
} else {
|
|
152
123
|
return await this.insert(table, [row])
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { Filter } from '../type'
|
|
1
|
+
import { Filter, Key } from '../type'
|
|
2
2
|
import { db } from './db'
|
|
3
3
|
|
|
4
4
|
/** I am responsible for transfering the state from Table to Builders.*/
|
|
5
5
|
export class Core<T, R> {
|
|
6
6
|
constructor(
|
|
7
7
|
public tableName: string,
|
|
8
|
-
public idKey:
|
|
9
|
-
public fields:
|
|
8
|
+
public idKey: Key<R>,
|
|
9
|
+
public fields: Key<R>[],
|
|
10
10
|
public convertor: ($: R) => T
|
|
11
11
|
) {}
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ export class Core<T, R> {
|
|
|
14
14
|
return db.select(this.tableName, this.fields, filters)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
async fetchSelectIn<K extends
|
|
17
|
+
async fetchSelectIn<K extends Key<R>>(
|
|
18
18
|
key: K,
|
|
19
19
|
vals: R[K][],
|
|
20
20
|
filters: Filter<R>[]
|
|
@@ -38,10 +38,7 @@ export class Core<T, R> {
|
|
|
38
38
|
return db.delete(this.tableName, this.idKey, idVal)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
async fetchUpsert(
|
|
42
|
-
row: Partial<R>,
|
|
43
|
-
conflictKeys: (keyof R)[]
|
|
44
|
-
): Promise<R[]> {
|
|
41
|
+
async fetchUpsert(row: Partial<R>, conflictKeys: Key<R>[]): Promise<R[]> {
|
|
45
42
|
return db.upsert(this.tableName, this.idKey, row, conflictKeys)
|
|
46
43
|
}
|
|
47
44
|
}
|
|
@@ -6,7 +6,7 @@ export function ENTITY<
|
|
|
6
6
|
K extends string & keyof R,
|
|
7
7
|
R extends InstanceType<TBase> = InstanceType<TBase>
|
|
8
8
|
>(RowClass: TBase, tableName: string, idKey: K) {
|
|
9
|
-
class
|
|
9
|
+
return class extends RowClass {
|
|
10
10
|
constructor(...args: any[]) {
|
|
11
11
|
super(...args)
|
|
12
12
|
let template = args[0] ?? {}
|
|
@@ -20,26 +20,20 @@ export function ENTITY<
|
|
|
20
20
|
static _idKey: K = idKey
|
|
21
21
|
|
|
22
22
|
static _fields: any[] = Object.keys(new RowClass())
|
|
23
|
-
}
|
|
24
23
|
|
|
25
|
-
class EDIT extends VIEW {
|
|
26
24
|
update(row: Partial<R>): UpdateBuilder<any, R> {
|
|
27
25
|
// @ts-ignore
|
|
28
|
-
return this._hostTable.
|
|
26
|
+
return this._hostTable.update(this[idKey], row)
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
delete(): DeleteBuilder<any, R> {
|
|
32
30
|
// @ts-ignore
|
|
33
|
-
return this._hostTable.
|
|
31
|
+
return this._hostTable.delete(this[idKey])
|
|
34
32
|
}
|
|
35
33
|
|
|
36
34
|
toggle(key: BooleanKeys<R>): UpdateBuilder<any, R> {
|
|
37
35
|
// @ts-ignore
|
|
38
|
-
return this._hostTable.
|
|
36
|
+
return this._hostTable.update(this[idKey], { [key]: !this[key] })
|
|
39
37
|
}
|
|
40
38
|
}
|
|
41
|
-
return {
|
|
42
|
-
EDIT,
|
|
43
|
-
VIEW,
|
|
44
|
-
}
|
|
45
39
|
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
UpdateBuilder,
|
|
8
8
|
UpsertBuilder,
|
|
9
9
|
} from './builder'
|
|
10
|
-
import { Constructor } from './type'
|
|
10
|
+
import { Constructor, Key } from './type'
|
|
11
11
|
import { Core } from './core'
|
|
12
12
|
import { ENTITY } from './entity'
|
|
13
13
|
import { reactive } from 'vue'
|
|
@@ -58,7 +58,7 @@ export function TABLE<
|
|
|
58
58
|
return new Core<T, R>(tableName, idKey, fields, convertor(host))
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
class
|
|
61
|
+
return class extends Array<T> {
|
|
62
62
|
/** make reactive */
|
|
63
63
|
reactive(): this {
|
|
64
64
|
const rec = reactive(this) as this
|
|
@@ -71,9 +71,7 @@ export function TABLE<
|
|
|
71
71
|
|
|
72
72
|
protected onChange(): any {}
|
|
73
73
|
protected onEdit(): any {}
|
|
74
|
-
}
|
|
75
74
|
|
|
76
|
-
class TableView extends Base {
|
|
77
75
|
select() {
|
|
78
76
|
let callback = ($: T[]) => {
|
|
79
77
|
this.set($)
|
|
@@ -90,7 +88,7 @@ export function TABLE<
|
|
|
90
88
|
return new SelectBuilder(core(this), callback)
|
|
91
89
|
}
|
|
92
90
|
|
|
93
|
-
selectIn<K extends
|
|
91
|
+
selectIn<K extends Key<R>>(key: K, vals: R[K][]) {
|
|
94
92
|
let callback = ($: T[]) => {
|
|
95
93
|
this.set($)
|
|
96
94
|
this.sortBy($ => vals.indexOf($[key]))
|
|
@@ -99,7 +97,7 @@ export function TABLE<
|
|
|
99
97
|
return new SelectInBuilder(key, vals, core(this), callback)
|
|
100
98
|
}
|
|
101
99
|
|
|
102
|
-
patchIn<K extends
|
|
100
|
+
patchIn<K extends Key<R>>(key: K, vals: R[K][]) {
|
|
103
101
|
let callback = ($: T[]) => {
|
|
104
102
|
this.absorb($, idKey)
|
|
105
103
|
this.sortBy($ => vals.indexOf($[key]))
|
|
@@ -107,9 +105,7 @@ export function TABLE<
|
|
|
107
105
|
}
|
|
108
106
|
return new SelectInBuilder(key, vals, core(this), callback)
|
|
109
107
|
}
|
|
110
|
-
}
|
|
111
108
|
|
|
112
|
-
class TableRPC extends Base {
|
|
113
109
|
selectRPC(param: object = {}) {
|
|
114
110
|
let callback = ($: T[]) => {
|
|
115
111
|
this.set($)
|
|
@@ -125,9 +121,7 @@ export function TABLE<
|
|
|
125
121
|
}
|
|
126
122
|
return new SelectRPCBuilder(param, core(this), callback)
|
|
127
123
|
}
|
|
128
|
-
}
|
|
129
124
|
|
|
130
|
-
class TableEdit extends TableView {
|
|
131
125
|
insert(row: Partial<R>) {
|
|
132
126
|
let callback = ($: T[]) => {
|
|
133
127
|
this.push(...$)
|
|
@@ -150,11 +144,6 @@ export function TABLE<
|
|
|
150
144
|
)
|
|
151
145
|
}
|
|
152
146
|
|
|
153
|
-
updateRow(oldRow: R, updatedRow: Partial<R>) {
|
|
154
|
-
let idVal = oldRow[idKey]
|
|
155
|
-
return this.update(idVal, updatedRow)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
147
|
delete(idVal: R[ClassT['_idKey']]) {
|
|
159
148
|
let callback = ($: T[]) => {
|
|
160
149
|
_.remove(this, $ => $[idKey] === idVal)
|
|
@@ -166,12 +155,7 @@ export function TABLE<
|
|
|
166
155
|
)
|
|
167
156
|
}
|
|
168
157
|
|
|
169
|
-
|
|
170
|
-
let idVal = rowToDelete[idKey]
|
|
171
|
-
return this.delete(idVal)
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
upsert(row: Partial<R>, conflictKeys: (keyof R)[]) {
|
|
158
|
+
upsert(row: Partial<R>, conflictKeys: Key<R>[]) {
|
|
175
159
|
let callback = ($: T[]) => {
|
|
176
160
|
this.absorb($, idKey)
|
|
177
161
|
this.onChange()
|
|
@@ -185,45 +169,33 @@ export function TABLE<
|
|
|
185
169
|
).notify('Updated!')
|
|
186
170
|
}
|
|
187
171
|
}
|
|
188
|
-
|
|
189
|
-
return {
|
|
190
|
-
EDIT: TableEdit,
|
|
191
|
-
VIEW: TableView,
|
|
192
|
-
RPC: TableRPC,
|
|
193
|
-
}
|
|
194
172
|
}
|
|
195
173
|
|
|
196
174
|
// // example
|
|
197
175
|
|
|
198
176
|
// class StudentRow {
|
|
199
|
-
|
|
200
|
-
// public
|
|
201
|
-
// public class: string = ""
|
|
177
|
+
// public name: string = ''
|
|
178
|
+
// public class: string = ''
|
|
202
179
|
// public num: number = 0
|
|
203
180
|
// public pass: boolean = false
|
|
204
181
|
// public pasds: boolean = false
|
|
205
|
-
|
|
206
182
|
// }
|
|
207
183
|
|
|
208
|
-
// class Student extends
|
|
209
|
-
|
|
184
|
+
// class Student extends ENTITY(StudentRow, 'student', 'num') {
|
|
210
185
|
// public full = this.class + this.name
|
|
211
|
-
|
|
212
186
|
// }
|
|
213
187
|
|
|
214
188
|
// let s = new Student()
|
|
215
189
|
// // s.ful
|
|
216
190
|
// s.toggle('pass')
|
|
217
191
|
|
|
218
|
-
// class StudentsCollection extends
|
|
219
|
-
|
|
192
|
+
// class StudentsCollection extends TABLE(Student) {
|
|
220
193
|
// protected override onChange() {
|
|
221
194
|
// return 1
|
|
222
195
|
// }
|
|
223
|
-
|
|
224
196
|
// }
|
|
225
197
|
|
|
226
198
|
// let ss = new StudentsCollection()
|
|
227
|
-
// ss.select().eq('
|
|
228
|
-
// ss.insert()
|
|
199
|
+
// ss.select().eq('name', 'a')
|
|
200
|
+
// ss.insert({ name: 'a' })
|
|
229
201
|
// ss.delete(1)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export type Filter<R> =
|
|
2
|
-
| { type: 'eq'; payload: { key:
|
|
3
|
-
| { type: 'in'; payload: { key:
|
|
4
|
-
| { type: 'like'; payload: { key:
|
|
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
5
|
| { type: 'limit'; payload: number }
|
|
6
|
-
| { type: 'order'; payload: { key:
|
|
6
|
+
| { type: 'order'; payload: { key: Key<R>; asc: boolean } }
|
|
7
7
|
|
|
8
8
|
export type Constructor<T extends object = {}> = new (...args: any[]) => T
|
|
9
9
|
|
|
@@ -11,3 +11,5 @@ export type BooleanKeys<T> = {
|
|
|
11
11
|
[k in keyof T]: T[k] extends boolean ? k : never
|
|
12
12
|
}[keyof T]
|
|
13
13
|
// type OnlyBoolean<T> = { [k in BooleanKeys<T>]: boolean }
|
|
14
|
+
|
|
15
|
+
export type Key<R> = string & keyof R
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
createClient,
|
|
3
3
|
PostgrestError,
|
|
4
4
|
SupabaseClient,
|
|
5
|
+
Session,
|
|
5
6
|
} from '@supabase/supabase-js'
|
|
6
7
|
import { qDialog } from './dialog'
|
|
7
8
|
|
|
@@ -10,80 +11,64 @@ export type {
|
|
|
10
11
|
PostgrestSingleResponse,
|
|
11
12
|
} from '@supabase/postgrest-js'
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
signIn: () => void
|
|
16
|
-
accessTokenLife: () => number
|
|
17
|
-
waitForSignin: () => Promise<void>
|
|
18
|
-
email: () => string
|
|
19
|
-
call: <T>(fn: string, params?: object | undefined) => Promise<T[]>
|
|
20
|
-
callSingle: <T>(fn: string, params?: object | undefined) => Promise<T>
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export let supabase: SupabaseClient
|
|
25
|
-
let SUPABASE_URL = process.env.SUPABASE_URL
|
|
26
|
-
let SUPABASE_KEY = process.env.SUPABASE_KEY
|
|
14
|
+
let SUPABASE_URL = process.env.SUPABASE_URL ?? ''
|
|
15
|
+
let SUPABASE_KEY = process.env.SUPABASE_KEY ?? ''
|
|
27
16
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
})
|
|
17
|
+
export class MySupabaseClient extends SupabaseClient {
|
|
18
|
+
email: string = 'unauthenticated'
|
|
19
|
+
session: Session | null = null
|
|
32
20
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
21
|
+
constructor() {
|
|
22
|
+
super(SUPABASE_URL, SUPABASE_KEY, {
|
|
23
|
+
auth: {
|
|
24
|
+
autoRefreshToken: true,
|
|
25
|
+
persistSession: true,
|
|
26
|
+
detectSessionInUrl: true,
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
this.auth.onAuthStateChange((event, session) => {
|
|
30
|
+
console.log('[SUPABASE AUTH]', event, session?.user?.email)
|
|
31
|
+
this.session = session
|
|
32
|
+
this.email = session?.user?.email ?? 'unauthenticated'
|
|
33
|
+
})
|
|
39
34
|
}
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
async signIn() {
|
|
37
|
+
await this.auth.signOut()
|
|
38
|
+
await this.auth.signInWithOAuth({
|
|
39
|
+
provider: 'google',
|
|
40
|
+
options: {
|
|
41
|
+
redirectTo: window.location.href,
|
|
42
|
+
},
|
|
43
|
+
})
|
|
47
44
|
}
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
supabase.waitForSignin = async function (): Promise<void> {
|
|
54
|
-
setInterval(() => {
|
|
55
|
-
if (supabase.auth.session() === null) supabase.signIn()
|
|
56
|
-
}, 1000)
|
|
57
|
-
await waitFor(
|
|
58
|
-
() => supabase.auth.session() !== null,
|
|
59
|
-
'[Wait for SignIn] waiting...',
|
|
60
|
-
'[Wait for SignIn] DONE!'
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
supabase.call = async function <T>(
|
|
65
|
-
fn: string,
|
|
66
|
-
params?: object | undefined
|
|
67
|
-
): Promise<T[]> {
|
|
68
|
-
let { data, error } = await supabase.rpc<T>(fn, params)
|
|
46
|
+
async call<T>(fn: string, params?: object | undefined): Promise<T[]> {
|
|
47
|
+
let { data, error } = await this.rpc<string, any>(fn, params)
|
|
69
48
|
HANDLE_ERROR(data, error)
|
|
70
49
|
return data
|
|
71
50
|
}
|
|
72
51
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
params?: object | undefined
|
|
76
|
-
): Promise<T> {
|
|
77
|
-
let { data, error } = await supabase.rpc<T>(fn, params).single()
|
|
52
|
+
async callSingle<T>(fn: string, params?: object | undefined): Promise<T> {
|
|
53
|
+
let { data, error } = await this.rpc<string, any>(fn, params).single()
|
|
78
54
|
HANDLE_ERROR(data, error)
|
|
79
|
-
return data
|
|
55
|
+
return data as T
|
|
80
56
|
}
|
|
81
57
|
|
|
82
|
-
|
|
83
|
-
|
|
58
|
+
async waitForSignin(): Promise<void> {
|
|
59
|
+
setInterval(() => {
|
|
60
|
+
if (this.session === null) this.signIn()
|
|
61
|
+
}, 1000)
|
|
62
|
+
waitFor(
|
|
63
|
+
() => this.session !== null,
|
|
64
|
+
'[Wait for SignIn] waiting...',
|
|
65
|
+
'[Wait for SignIn] DONE!'
|
|
66
|
+
)
|
|
84
67
|
}
|
|
85
68
|
}
|
|
86
69
|
|
|
70
|
+
export let supabase = new MySupabaseClient()
|
|
71
|
+
|
|
87
72
|
export function HANDLE_ERROR<T>(
|
|
88
73
|
data: T[] | T | null,
|
|
89
74
|
error: PostgrestError | null
|
|
@@ -116,13 +101,13 @@ async function waitFor(
|
|
|
116
101
|
doneMsg: string
|
|
117
102
|
) {
|
|
118
103
|
return new Promise(resolve => {
|
|
119
|
-
function checker() {
|
|
104
|
+
async function checker() {
|
|
120
105
|
if (predicate()) {
|
|
121
106
|
console.log(doneMsg)
|
|
122
107
|
resolve(true)
|
|
123
108
|
} else {
|
|
124
109
|
console.log(waitingMsg)
|
|
125
|
-
setTimeout(
|
|
110
|
+
setTimeout(checker, 50)
|
|
126
111
|
}
|
|
127
112
|
}
|
|
128
113
|
checker()
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { reactive, effect } from '@vue/reactivity'
|
|
2
|
-
|
|
3
|
-
function getFromLocal<T extends object>(key: string): T {
|
|
4
|
-
let val = localStorage.getItem(key)
|
|
5
|
-
return val === null ? {} : JSON.parse(val)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function localSettings<T extends object>(
|
|
9
|
-
preset: T,
|
|
10
|
-
localStorageKey = 'settings'
|
|
11
|
-
): T {
|
|
12
|
-
let ss = reactive({ ...preset, ...getFromLocal<T>(localStorageKey) })
|
|
13
|
-
effect(() => {
|
|
14
|
-
localStorage.setItem('settings', JSON.stringify(ss))
|
|
15
|
-
for (let k in ss) {
|
|
16
|
-
let val = ss[k]
|
|
17
|
-
}
|
|
18
|
-
})
|
|
19
|
-
return ss as T
|
|
20
|
-
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
// import {
|
|
2
|
-
// createClient,
|
|
3
|
-
// PostgrestError,
|
|
4
|
-
// SupabaseClient,
|
|
5
|
-
// Session,
|
|
6
|
-
// SupabaseClientOptions,
|
|
7
|
-
// } from '@supabase/supabase-js'
|
|
8
|
-
// import { qDialog } from './dialog'
|
|
9
|
-
|
|
10
|
-
// export type {
|
|
11
|
-
// PostgrestFilterBuilder,
|
|
12
|
-
// PostgrestSingleResponse,
|
|
13
|
-
// } from '@supabase/postgrest-js'
|
|
14
|
-
|
|
15
|
-
// let SUPABASE_URL = process.env.SUPABASE_URL ?? ''
|
|
16
|
-
// let SUPABASE_KEY = process.env.SUPABASE_KEY ?? ''
|
|
17
|
-
|
|
18
|
-
// export class MySupabaseClient<Database> extends SupabaseClient<Database> {
|
|
19
|
-
// email: string = 'unauthenticated'
|
|
20
|
-
// session: Session | null = null
|
|
21
|
-
|
|
22
|
-
// constructor() {
|
|
23
|
-
// super(SUPABASE_URL, SUPABASE_KEY, {
|
|
24
|
-
// auth: {
|
|
25
|
-
// autoRefreshToken: true,
|
|
26
|
-
// persistSession: true,
|
|
27
|
-
// detectSessionInUrl: true,
|
|
28
|
-
// },
|
|
29
|
-
// })
|
|
30
|
-
// this.auth.onAuthStateChange((event, session) => {
|
|
31
|
-
// console.log('[SUPABASE AUTH]', event, session?.user?.email)
|
|
32
|
-
// this.session = session
|
|
33
|
-
// this.email = session?.user?.email ?? 'unauthenticated'
|
|
34
|
-
// })
|
|
35
|
-
// }
|
|
36
|
-
|
|
37
|
-
// async signIn() {
|
|
38
|
-
// await this.auth.signOut()
|
|
39
|
-
// await this.auth.signInWithOAuth({
|
|
40
|
-
// provider: 'google',
|
|
41
|
-
// options: {
|
|
42
|
-
// redirectTo: window.location.href,
|
|
43
|
-
// },
|
|
44
|
-
// })
|
|
45
|
-
// }
|
|
46
|
-
|
|
47
|
-
// async call<T>(fn: string, params?: object | undefined): Promise<T[]> {
|
|
48
|
-
// let { data, error } = await this.rpc<string, any>(fn, params)
|
|
49
|
-
// HANDLE_ERROR(data, error)
|
|
50
|
-
// return data
|
|
51
|
-
// }
|
|
52
|
-
|
|
53
|
-
// async callSingle<T>(fn: string, params?: object | undefined): Promise<T> {
|
|
54
|
-
// let { data, error } = await this.rpc<string, any>(fn, params).single()
|
|
55
|
-
// HANDLE_ERROR(data, error)
|
|
56
|
-
// return data as T
|
|
57
|
-
// }
|
|
58
|
-
|
|
59
|
-
// async waitForSignin(): Promise<void> {
|
|
60
|
-
// setInterval(() => {
|
|
61
|
-
// if (this.session === null) this.signIn()
|
|
62
|
-
// }, 1000)
|
|
63
|
-
// waitFor(
|
|
64
|
-
// () => this.session !== null,
|
|
65
|
-
// '[Wait for SignIn] waiting...',
|
|
66
|
-
// '[Wait for SignIn] DONE!'
|
|
67
|
-
// )
|
|
68
|
-
// }
|
|
69
|
-
// }
|
|
70
|
-
|
|
71
|
-
// // export let supabase: MySupabaseClient
|
|
72
|
-
// // let SUPABASE_URL = process.env.SUPABASE_URL
|
|
73
|
-
// // let SUPABASE_KEY = process.env.SUPABASE_KEY
|
|
74
|
-
|
|
75
|
-
// // if (SUPABASE_URL && SUPABASE_KEY) {
|
|
76
|
-
// // supabase = new MySupabaseClient(SUPABASE_URL, SUPABASE_KEY, {
|
|
77
|
-
// // auth: {
|
|
78
|
-
// // autoRefreshToken: true,
|
|
79
|
-
// // persistSession: true,
|
|
80
|
-
// // detectSessionInUrl: true,
|
|
81
|
-
// // },
|
|
82
|
-
// // })
|
|
83
|
-
// // }
|
|
84
|
-
|
|
85
|
-
// export function HANDLE_ERROR<T>(
|
|
86
|
-
// data: T[] | T | null,
|
|
87
|
-
// error: PostgrestError | null
|
|
88
|
-
// ): asserts data {
|
|
89
|
-
// if (error) {
|
|
90
|
-
// if (error.message === 'JWSError JWSInvalidSignature') {
|
|
91
|
-
// localStorage.removeItem('supabase.auth.token')
|
|
92
|
-
// qDialog.error(
|
|
93
|
-
// 'Database Error!',
|
|
94
|
-
// 'Your login session has expired. Please try refreshing the website.'
|
|
95
|
-
// )
|
|
96
|
-
// throw error
|
|
97
|
-
// }
|
|
98
|
-
// let msg = ''
|
|
99
|
-
// msg += error.details ?? '' + '<br/>'
|
|
100
|
-
// msg += error.message ?? '' + '<br/>'
|
|
101
|
-
// msg += error.hint ?? ''
|
|
102
|
-
// qDialog.error('Database Error!', msg)
|
|
103
|
-
// throw error
|
|
104
|
-
// }
|
|
105
|
-
// if (data === null) {
|
|
106
|
-
// qDialog.error('Supabase Error!', 'Returned data is null')
|
|
107
|
-
// throw 'supabase return data is null!'
|
|
108
|
-
// }
|
|
109
|
-
// }
|
|
110
|
-
|
|
111
|
-
// async function waitFor(
|
|
112
|
-
// predicate: () => boolean,
|
|
113
|
-
// waitingMsg: string,
|
|
114
|
-
// doneMsg: string
|
|
115
|
-
// ) {
|
|
116
|
-
// return new Promise(resolve => {
|
|
117
|
-
// async function checker() {
|
|
118
|
-
// if (predicate()) {
|
|
119
|
-
// console.log(doneMsg)
|
|
120
|
-
// resolve(true)
|
|
121
|
-
// } else {
|
|
122
|
-
// console.log(waitingMsg)
|
|
123
|
-
// setTimeout(checker, 50)
|
|
124
|
-
// }
|
|
125
|
-
// }
|
|
126
|
-
// checker()
|
|
127
|
-
// })
|
|
128
|
-
// }
|