corebasic 1.0.229 → 1.0.231
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/dist/libs/auth.js +5 -4
- package/dist/libs/compression.js +1 -7
- package/dist/libs/dip/suffix/index.js +8 -6
- package/dist/libs/dip/suffix/policy.js +6 -4
- package/dist/libs/dip/suffix/query.js +290 -279
- package/dist/libs/dip/suffix/suffix.js +17 -13
- package/dist/libs/dip/suffix/tests/date.test.js +21 -34
- package/dist/libs/dip/suffix/tests/policy.test.js +41 -80
- package/dist/libs/dip.js +28 -26
- package/dist/libs/dipper.js +0 -1
- package/dist/libs/elabase.js +1 -1
- package/dist/libs/kafka.js +7 -4
- package/dist/libs/messaging.js +7 -4
- package/dist/libs/session.js +2 -2
- package/libs/auth.ts +48 -9
- package/libs/compression.ts +6 -1
- package/libs/cpp.ts +15 -13
- package/libs/dip/suffix/date.ts +6 -6
- package/libs/dip/suffix/index.ts +41 -26
- package/libs/dip/suffix/policy.ts +16 -13
- package/libs/dip/suffix/query.ts +289 -289
- package/libs/dip/suffix/suffix.ts +26 -20
- package/libs/dip/suffix/tests/date.test.ts +32 -64
- package/libs/dip/suffix/tests/policy.applySuffixPolicy.test.ts +20 -20
- package/libs/dip/suffix/tests/policy.test.ts +41 -109
- package/libs/dip/suffix/tests/suffix.test.ts +2 -2
- package/libs/dip.ts +59 -33
- package/libs/dipper.ts +25 -10
- package/libs/elabase.ts +1 -1
- package/libs/kafka.ts +74 -11
- package/libs/messaging.ts +80 -19
- package/libs/session.ts +21 -10
- package/libs/utils.ts +1 -1
- package/package.json +1 -1
package/libs/kafka.ts
CHANGED
|
@@ -4,12 +4,73 @@ import { Kafka, logLevel as KafkaLogLevel, CompressionTypes as KafkaCompressionT
|
|
|
4
4
|
export const logLevel = KafkaLogLevel
|
|
5
5
|
export const CompressionTypes = KafkaCompressionTypes
|
|
6
6
|
|
|
7
|
-
let kafka, producer, admin
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
type KafkaCallback = (topic: string, message: unknown, partition: number) => unknown | Promise<unknown>
|
|
9
|
+
|
|
10
|
+
type KafkaConsumer = {
|
|
11
|
+
connect: () => Promise<void>
|
|
12
|
+
subscribe: (arg: {topic: string; fromBeginning: boolean}) => Promise<void>
|
|
13
|
+
run: (arg: {
|
|
14
|
+
autoCommit: boolean
|
|
15
|
+
eachMessage: (arg: {
|
|
16
|
+
topic: string
|
|
17
|
+
partition: number
|
|
18
|
+
message: {
|
|
19
|
+
value: string | Buffer | null
|
|
20
|
+
offset: string
|
|
21
|
+
}
|
|
22
|
+
}) => Promise<void>
|
|
23
|
+
}) => Promise<void>
|
|
24
|
+
commitOffsets: (offsets: {topic: string; partition: number; offset: string}[]) => Promise<void>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type KafkaProducer = {
|
|
28
|
+
connect: () => Promise<void>
|
|
29
|
+
send: (arg: unknown) => Promise<unknown>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type KafkaAdmin = {
|
|
33
|
+
createTopics: (arg: {
|
|
34
|
+
topics: {
|
|
35
|
+
topic: string
|
|
36
|
+
numPartitions: number
|
|
37
|
+
replicationFactor: number
|
|
38
|
+
}[]
|
|
39
|
+
}) => Promise<unknown>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type KafkaClient = {
|
|
43
|
+
consumer: (arg: {groupId: string}) => KafkaConsumer
|
|
44
|
+
producer: (arg: {allowAutoTopicCreation: boolean}) => KafkaProducer
|
|
45
|
+
admin: () => KafkaAdmin
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type KafkaStartArg = {
|
|
49
|
+
clientId?: string
|
|
50
|
+
brokers?: string[]
|
|
51
|
+
sasl?: false | {
|
|
52
|
+
mechanism: string
|
|
53
|
+
username?: string
|
|
54
|
+
password?: string
|
|
55
|
+
}
|
|
56
|
+
logLevel?: unknown
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
let kafka: KafkaClient
|
|
61
|
+
let producer: KafkaProducer
|
|
62
|
+
let admin: KafkaAdmin
|
|
63
|
+
|
|
64
|
+
let appName: string
|
|
10
65
|
let topicPrefix = ''
|
|
11
66
|
|
|
12
|
-
|
|
67
|
+
declare global {
|
|
68
|
+
var app: {
|
|
69
|
+
name?: string
|
|
70
|
+
} | undefined
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const start = (arg?: KafkaStartArg) => {
|
|
13
74
|
arg = !arg && !process.env.APP_DEPLOYMENT_NAME ? { clientId: (global.app?.name ?? 'app') + '-dev', brokers: ['127.0.0.1:9092'], sasl: false, logLevel: logLevel.ERROR } : arg
|
|
14
75
|
appName = arg?.clientId ?? (process.env.APP_DEPLOYMENT_NAME ?? (global.app?.name ?? 'app'))
|
|
15
76
|
topicPrefix = `${appName}.`
|
|
@@ -28,7 +89,7 @@ export const start = (arg) => {
|
|
|
28
89
|
}
|
|
29
90
|
|
|
30
91
|
|
|
31
|
-
export const createTopic = async (topic, partition, replicas) => {
|
|
92
|
+
export const createTopic = async (topic: string, partition?: number, replicas?: number) => {
|
|
32
93
|
topic = topicPrefix + topic
|
|
33
94
|
return await admin.createTopics({ topics: [{topic, numPartitions: partition ?? 1, replicationFactor: replicas ?? 1}] })
|
|
34
95
|
}
|
|
@@ -39,7 +100,7 @@ export const createTopic = async (topic, partition, replicas) => {
|
|
|
39
100
|
|
|
40
101
|
let consumers = []
|
|
41
102
|
|
|
42
|
-
const start_consumer = async function (topic, groupId, callback?:
|
|
103
|
+
const start_consumer = async function (topic: string, groupId: string | KafkaCallback, callback?: KafkaCallback) {
|
|
43
104
|
callback = typeof groupId === "string" ? callback : groupId
|
|
44
105
|
groupId = typeof groupId === "string" ? `${appName}.${groupId}` : `${appName}.${topic}`
|
|
45
106
|
|
|
@@ -49,15 +110,17 @@ const start_consumer = async function (topic, groupId, callback?: Function) {
|
|
|
49
110
|
await consumer.connect()
|
|
50
111
|
await consumer.subscribe({ topic: topic, fromBeginning: true })
|
|
51
112
|
|
|
113
|
+
const fn = callback!
|
|
114
|
+
|
|
52
115
|
await consumer.run({
|
|
53
116
|
autoCommit: false,
|
|
54
117
|
eachMessage: async ({ topic, partition, message }) => {
|
|
55
|
-
//
|
|
118
|
+
// fn(topic, message.value.toString(), partition) // toString() returns array so won't parse if json.
|
|
56
119
|
let success
|
|
57
120
|
try {
|
|
58
|
-
success = await
|
|
121
|
+
success = await fn(topic, JSON.parse(message.value as string), partition)
|
|
59
122
|
} catch (ex) {
|
|
60
|
-
success = await
|
|
123
|
+
success = await fn(topic, message.value, partition)
|
|
61
124
|
}
|
|
62
125
|
|
|
63
126
|
await consumer.commitOffsets([{ topic, partition, offset: (Number(message.offset) + 1).toString() }]);
|
|
@@ -71,7 +134,7 @@ const start_consumer = async function (topic, groupId, callback?: Function) {
|
|
|
71
134
|
// Producer
|
|
72
135
|
// ===========
|
|
73
136
|
let producerInvoked = false
|
|
74
|
-
const start_producer = async function (topic, message, key, options) {
|
|
137
|
+
const start_producer = async function (topic: string, message: object, key: string, options?: object) {
|
|
75
138
|
|
|
76
139
|
let isJson = Object.prototype.toString.call(message) === '[object Object]' || Object.prototype.toString.call(message) === '[object Array]'
|
|
77
140
|
|
|
@@ -97,13 +160,13 @@ const start_producer = async function (topic, message, key, options) {
|
|
|
97
160
|
// start_consumer('quickstart-events')
|
|
98
161
|
// start_producer('quickstart-events', 'Hello KafkaJS user! Little')
|
|
99
162
|
|
|
100
|
-
export const receive = async function(topic, groupId, callback?:
|
|
163
|
+
export const receive = async function(topic: string, groupId: string, callback?: KafkaCallback) {
|
|
101
164
|
topic = topicPrefix + topic
|
|
102
165
|
return (await start_consumer(topic, groupId, callback))
|
|
103
166
|
}
|
|
104
167
|
|
|
105
168
|
|
|
106
|
-
export const send = async function(topic, message, key, options) {
|
|
169
|
+
export const send = async function(topic: string, message: object, key: string, options?: object) {
|
|
107
170
|
topic = topicPrefix + topic
|
|
108
171
|
await start_producer(topic, message, key, options)
|
|
109
172
|
}
|
package/libs/messaging.ts
CHANGED
|
@@ -9,24 +9,85 @@ import { createClient } from 'redis';
|
|
|
9
9
|
const url = process.env.REDIS_URL || "redis://localhost:6380"
|
|
10
10
|
|
|
11
11
|
// url: 'redis://alice:foobared@localhost:6380'
|
|
12
|
-
let consumer, publisher
|
|
13
12
|
|
|
14
13
|
|
|
14
|
+
type RedisListener = (message: string, channel: string) => void
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
type RedisConsumer = {
|
|
17
|
+
connect: () => Promise<void>
|
|
18
|
+
subscribe: (channel: string, listener: RedisListener) => Promise<void>
|
|
19
|
+
unsubscribe: (channel: string, listener: RedisListener) => Promise<void>
|
|
20
|
+
on: (event: string, listener: (err: unknown) => void) => void
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type RedisPublisher = {
|
|
24
|
+
connect: () => Promise<void>
|
|
25
|
+
publish: (channel: string, message: string) => Promise<unknown>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type Request = {
|
|
29
|
+
body: {
|
|
30
|
+
client: string
|
|
31
|
+
}
|
|
32
|
+
params: {
|
|
33
|
+
user: string
|
|
34
|
+
}
|
|
35
|
+
on: (event: string, listener: () => void | Promise<void>) => void
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type Response = {
|
|
39
|
+
writeHead: (status: number, headers: Record<string, string>) => void
|
|
40
|
+
write: (data: string) => void
|
|
41
|
+
flush?: () => void
|
|
42
|
+
end: () => void
|
|
43
|
+
json: (body: unknown) => void
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type UserRequest = {
|
|
47
|
+
req: Request
|
|
48
|
+
res: Response
|
|
49
|
+
uid: string
|
|
50
|
+
}
|
|
17
51
|
|
|
52
|
+
type UserListeners = {
|
|
53
|
+
count: number
|
|
54
|
+
[uid: string]: number | RedisListener
|
|
18
55
|
}
|
|
19
56
|
|
|
20
|
-
|
|
57
|
+
type UserPool = {
|
|
58
|
+
reqres: UserRequest[]
|
|
59
|
+
listeners: UserListeners
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
type ExpressApp = {
|
|
63
|
+
get: (
|
|
64
|
+
path: string,
|
|
65
|
+
handler: (req: Request, res: Response) => Promise<void>
|
|
66
|
+
) => unknown
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
let consumer: RedisConsumer
|
|
71
|
+
let publisher: RedisPublisher
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
let users_pool: Record<string, UserPool> = {}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
async function disconnect(user: string, uid: string) {
|
|
21
78
|
if (!users_pool[user])
|
|
22
79
|
return
|
|
23
80
|
|
|
24
|
-
|
|
25
|
-
|
|
81
|
+
|
|
82
|
+
let res_items = users_pool[user].reqres.filter(item => item.uid === uid)
|
|
83
|
+
if (res_items) {
|
|
84
|
+
const res = res_items[0]!.res
|
|
85
|
+
res.end()
|
|
86
|
+
}
|
|
26
87
|
|
|
27
88
|
if (users_pool[user].listeners[uid]) {
|
|
28
89
|
if (users_pool[user].listeners.count == 1)
|
|
29
|
-
await consumer.unsubscribe(user, users_pool[user].listeners[uid]);
|
|
90
|
+
await consumer.unsubscribe(user, users_pool[user].listeners[uid] as RedisListener);
|
|
30
91
|
users_pool[user].listeners.count --
|
|
31
92
|
}
|
|
32
93
|
users_pool[user].reqres = users_pool[user].reqres.filter(item => item.uid !== uid)
|
|
@@ -36,9 +97,9 @@ async function disconnect(user, uid) {
|
|
|
36
97
|
|
|
37
98
|
// await consumer.unsubscribe(user);
|
|
38
99
|
}
|
|
39
|
-
async function connect({user,req,res, uid}) {
|
|
100
|
+
async function connect({user, req, res, uid}: {user: string, req: Request, res: Response, uid: string}) {
|
|
40
101
|
res.writeHead(200, {'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive'})
|
|
41
|
-
const listener = (message, channel) => {
|
|
102
|
+
const listener = (message: string, channel: string) => {
|
|
42
103
|
if (users_pool[user]) {
|
|
43
104
|
try {message = JSON.parse(message)} catch {}
|
|
44
105
|
for (let {req, res} of users_pool[user].reqres) {
|
|
@@ -56,7 +117,7 @@ async function connect({user,req,res, uid}) {
|
|
|
56
117
|
users_pool[user].listeners.count ++
|
|
57
118
|
}
|
|
58
119
|
|
|
59
|
-
export async function start(app) {
|
|
120
|
+
export async function start(app: ExpressApp) {
|
|
60
121
|
consumer = createClient({ url });
|
|
61
122
|
await consumer.connect();
|
|
62
123
|
publisher = createClient({ url });
|
|
@@ -79,7 +140,7 @@ export async function start(app) {
|
|
|
79
140
|
}
|
|
80
141
|
|
|
81
142
|
|
|
82
|
-
export async function publish(channel, message) {
|
|
143
|
+
export async function publish(channel: string, message: object | string) {
|
|
83
144
|
if (publisher && !Utils.isEmpty(channel)) {
|
|
84
145
|
try {
|
|
85
146
|
await publisher.publish(channel, typeof message === "object" ? JSON.stringify(message) : message)
|
|
@@ -108,44 +169,44 @@ export async function newProducer() {
|
|
|
108
169
|
let defaultConsumer = await newConsumer()
|
|
109
170
|
let defaultProducer = await newProducer()
|
|
110
171
|
|
|
111
|
-
export async function subscribe(channel, listener) {
|
|
172
|
+
export async function subscribe(channel: string, listener: RedisListener) {
|
|
112
173
|
await defaultConsumer.subscribe(channel, listener)
|
|
113
174
|
}
|
|
114
175
|
|
|
115
|
-
export async function produce(channel, message) {
|
|
176
|
+
export async function produce(channel: string, message: string) {
|
|
116
177
|
await defaultProducer.publish(channel, message)
|
|
117
178
|
}
|
|
118
179
|
|
|
119
180
|
|
|
120
181
|
let defaultSetGetConsumer = await newConsumer()
|
|
121
182
|
|
|
122
|
-
export async function set(key, value) {
|
|
183
|
+
export async function set(key: string, value: object | string | number) {
|
|
123
184
|
await defaultSetGetConsumer.set(`${process.env.REDIS_CHANNEL_PREFIX}_${key}`, typeof value === 'object' ? JSON.stringify(value) : value)
|
|
124
185
|
}
|
|
125
|
-
export async function get(key) {
|
|
186
|
+
export async function get(key: string) {
|
|
126
187
|
let value = await defaultSetGetConsumer.get(`${process.env.REDIS_CHANNEL_PREFIX}_${key}`)
|
|
127
188
|
try { value = JSON.parse(value) } catch(err) { }
|
|
128
189
|
return value
|
|
129
190
|
}
|
|
130
|
-
export async function del(key) {
|
|
191
|
+
export async function del(key: string) {
|
|
131
192
|
await defaultSetGetConsumer.del(`${process.env.REDIS_CHANNEL_PREFIX}_${key}`)
|
|
132
193
|
}
|
|
133
194
|
|
|
134
|
-
export async function hset(key, subkey, value) {
|
|
195
|
+
export async function hset(key: string, subkey: string, value: object | string | number) {
|
|
135
196
|
await defaultSetGetConsumer.HSET(`${process.env.REDIS_CHANNEL_PREFIX}_${key}`, subkey, typeof value === 'object' ? JSON.stringify(value) : value)
|
|
136
197
|
}
|
|
137
|
-
export async function hget(key, subkey) {
|
|
198
|
+
export async function hget(key: string, subkey: string) {
|
|
138
199
|
let value = await defaultSetGetConsumer.HGET(`${process.env.REDIS_CHANNEL_PREFIX}_${key}`, subkey)
|
|
139
200
|
try { value = JSON.parse(value) } catch(err) { }
|
|
140
201
|
return value
|
|
141
202
|
}
|
|
142
|
-
export async function hdel(key, subkey) {
|
|
203
|
+
export async function hdel(key: string, subkey: string) {
|
|
143
204
|
await defaultSetGetConsumer.HDEL(`${process.env.REDIS_CHANNEL_PREFIX}_${key}`, subkey)
|
|
144
205
|
}
|
|
145
206
|
|
|
146
207
|
// Hydrate
|
|
147
208
|
|
|
148
|
-
export async function hydrate(callback) {
|
|
209
|
+
export async function hydrate(callback: () => Promise<{user: string, company: string, items: any[]}>) {
|
|
149
210
|
setTimeout(async () => {
|
|
150
211
|
let {user,company,items} = await callback()
|
|
151
212
|
await publish(user, {event: "RPC_hydrate", data: { company, items }, txn: Utils.uid() })
|
package/libs/session.ts
CHANGED
|
@@ -3,7 +3,17 @@ import * as Features from './features.ts'
|
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
import jwt from 'jsonwebtoken'
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
type Req = { header: (h: string) => string; path: string; url: string; body: { staff: string; company: string; outlet: string; app: string; feature: string; } }
|
|
7
|
+
type Res = { json: (body: unknown) => unknown; status: (code: number) => { json: (body: unknown) => unknown };}
|
|
8
|
+
type Next = () => void;
|
|
9
|
+
type Use = (req: Req, res: Res, next: Next) => Promise<void>
|
|
10
|
+
|
|
11
|
+
type ReqRefreshToken = { body: { userId: string; clientId: string; refreshToken: string } }
|
|
12
|
+
type ResRefreshToken = { json: (body: unknown) => unknown; status: (code: number) => { json: (body: unknown) => unknown };}
|
|
13
|
+
|
|
14
|
+
type ExpressApp = {use: (fn: Use) => void, post: (route: string, callback: (req: ReqRefreshToken, res: ResRefreshToken) => void) => void}
|
|
15
|
+
|
|
16
|
+
let app: ExpressApp
|
|
7
17
|
|
|
8
18
|
|
|
9
19
|
|
|
@@ -15,16 +25,15 @@ const DEPLOY_TOKEN_SECRET = process.env.DEPLOY_TOKEN_SECRET || "MY_SECRET_DEPLOY
|
|
|
15
25
|
|
|
16
26
|
const NDCURVE_DEVELOPER_LICENSE_ACCESS_TOKEN_SECRET = process.env.NDCURVE_DEVELOPER_LICENSE_ACCESS_TOKEN_PUBLIC_KEY
|
|
17
27
|
|
|
18
|
-
let urlsAllowed = []
|
|
19
|
-
export
|
|
28
|
+
let urlsAllowed: string[] = []
|
|
29
|
+
export let ALLOWED_URLS: string[] = []
|
|
20
30
|
|
|
21
|
-
export const start = (expressApp, allowedUrls) => {
|
|
31
|
+
export const start = (expressApp: ExpressApp, allowedUrls: string[]) => {
|
|
22
32
|
urlsAllowed = ["/refreshToken", "/login"].concat(allowedUrls ?? [])
|
|
23
33
|
ALLOWED_URLS = urlsAllowed
|
|
24
34
|
app = expressApp
|
|
25
35
|
|
|
26
|
-
|
|
27
|
-
app.use(async (req, res, next) => {
|
|
36
|
+
app.use(async (req: Req, res: Res, next: Next) => {
|
|
28
37
|
|
|
29
38
|
// return next() // Disable session
|
|
30
39
|
|
|
@@ -33,7 +42,7 @@ export const start = (expressApp, allowedUrls) => {
|
|
|
33
42
|
if (urlsAllowed.includes(req.path))
|
|
34
43
|
return next()
|
|
35
44
|
|
|
36
|
-
const checkPrivilege = async req => {
|
|
45
|
+
const checkPrivilege = async (req: Req) => {
|
|
37
46
|
const staff = Utils.isEmpty(req.body.staff) ? 'BLANK_STAFF' : req.body.staff
|
|
38
47
|
const granted = (await Features.send({company: req.body.company, outlet: req.body.outlet, app: req.body.app}, "privileges.query.check", {feature: req.body.feature }, {id: staff})).data.granted
|
|
39
48
|
if (!granted)
|
|
@@ -71,11 +80,13 @@ export const start = (expressApp, allowedUrls) => {
|
|
|
71
80
|
return next()
|
|
72
81
|
throw null;
|
|
73
82
|
} catch (error) {
|
|
74
|
-
|
|
83
|
+
type ErrorType = { message?: string }
|
|
84
|
+
res.status(401).json({ message: (error as ErrorType)?.message === "Access Denied" ? "Access Denied" : 'Unauthorized' })
|
|
75
85
|
}
|
|
76
86
|
})
|
|
77
87
|
|
|
78
|
-
|
|
88
|
+
|
|
89
|
+
app.post("/refreshToken", (req: ReqRefreshToken, res: ResRefreshToken) => {
|
|
79
90
|
try {
|
|
80
91
|
let { userId, clientId, refreshToken } = req.body
|
|
81
92
|
type Decoded = {userId: string, clientId: string}
|
|
@@ -101,7 +112,7 @@ export const start = (expressApp, allowedUrls) => {
|
|
|
101
112
|
}
|
|
102
113
|
|
|
103
114
|
|
|
104
|
-
export const generateAccessToken = (userId, clientId) => {
|
|
115
|
+
export const generateAccessToken = (userId: string, clientId: string) => {
|
|
105
116
|
let data = { userId, clientId }
|
|
106
117
|
|
|
107
118
|
let now = Utils.now()
|
package/libs/utils.ts
CHANGED
|
@@ -124,7 +124,7 @@ export function toDate(arg: string, currentTime?: boolean): Date | undefined { /
|
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
export function getDatesBetweenTwoDates(start: number | Date, end: number | Date) {
|
|
127
|
-
let arr = [];
|
|
127
|
+
let arr: Date[] = [];
|
|
128
128
|
let dt = new Date(start);
|
|
129
129
|
|
|
130
130
|
dt.setHours(0)
|