pockethost 1.0.0-rc.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/LICENSE.md +16 -0
- package/dist/index.mjs +3156 -0
- package/dist/instance-app/migrations/1699198734_pockethost_defaults.js +39 -0
- package/dist/instance-app/pb_hooks/_ph_admin_sync.pb.js +71 -0
- package/dist/instance-app/pb_hooks/_ph_lib.js +19 -0
- package/dist/instance-app/tsconfig.json +8 -0
- package/dist/instance-app/types/goja.d.ts +58 -0
- package/dist/instance-app/types/lib.d.ts +5 -0
- package/dist/instance-app/types/types.d.ts +19573 -0
- package/dist/mothership-app/migrations/1705062576_collections_snapshot.js +1863 -0
- package/dist/mothership-app/migrations/1705083826_updated_stats.js +721 -0
- package/dist/mothership-app/migrations/1706060446_updated_instances.js +44 -0
- package/dist/mothership-app/pb_hooks/src/instances-create.pb.js +65 -0
- package/dist/mothership-app/pb_hooks/src/instances-delete.pb.js +69 -0
- package/dist/mothership-app/pb_hooks/src/instances-migrate-versions.pb.js +33 -0
- package/dist/mothership-app/pb_hooks/src/instances-notify-discord-after-create.pb.js +31 -0
- package/dist/mothership-app/pb_hooks/src/instances-notify-on-maintenance-mode.pb.js +52 -0
- package/dist/mothership-app/pb_hooks/src/instances-reset-idle.pb.js +7 -0
- package/dist/mothership-app/pb_hooks/src/instances-update.pb.js +121 -0
- package/dist/mothership-app/pb_hooks/src/instances-validate-before-create.pb.js +16 -0
- package/dist/mothership-app/pb_hooks/src/instances-validate-before-update.pb.js +43 -0
- package/dist/mothership-app/pb_hooks/src/lib.js +171 -0
- package/dist/mothership-app/pb_hooks/src/ls.pb.js +159 -0
- package/dist/mothership-app/pb_hooks/src/mail.pb.js +49 -0
- package/dist/mothership-app/pb_hooks/src/notifications.pb.js +62 -0
- package/dist/mothership-app/pb_hooks/src/random-words.js +2085 -0
- package/dist/mothership-app/pb_hooks/src/signup.pb.js +214 -0
- package/dist/mothership-app/pb_hooks/src/sns.pb.js +133 -0
- package/dist/mothership-app/pb_hooks/src/unsubscribe.pb.js +33 -0
- package/dist/mothership-app/pb_hooks/src/user-token.pb.js +33 -0
- package/dist/mothership-app/pb_hooks/src/user-welcome-msg.pb.js +32 -0
- package/dist/mothership-app/pb_hooks/src/versions-route.pb.js +12 -0
- package/dist/mothership-app/pb_hooks/src/versions.js +0 -0
- package/dist/mothership-app/pb_hooks/tsconfig.json +8 -0
- package/dist/mothership-app/pb_hooks/types/global.d.ts +1 -0
- package/dist/mothership-app/pb_hooks/types/goja.d.ts +58 -0
- package/dist/mothership-app/pb_hooks/types/lemon.d.ts +12 -0
- package/dist/mothership-app/pb_hooks/types/lib.d.ts +55 -0
- package/dist/mothership-app/pb_hooks/types/types.d.ts +19573 -0
- package/dist/mothership-app/ph_app/index.js +11 -0
- package/dist/mothership-app/ph_app/package-lock.json +657 -0
- package/dist/mothership-app/ph_app/package.json +14 -0
- package/package.json +144 -0
- package/readme.md +168 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/// <reference path="../types/types.d.ts" />
|
|
2
|
+
|
|
3
|
+
routerAdd(
|
|
4
|
+
'GET',
|
|
5
|
+
'/api/signup',
|
|
6
|
+
(c) => {
|
|
7
|
+
/**
|
|
8
|
+
* @param {string} slug
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
const isAvailable = (slug) => {
|
|
12
|
+
try {
|
|
13
|
+
const record = $app
|
|
14
|
+
.dao()
|
|
15
|
+
.findFirstRecordByData('instances', 'subdomain', slug)
|
|
16
|
+
return false
|
|
17
|
+
} catch {
|
|
18
|
+
return true
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} fieldName
|
|
24
|
+
* @param {string} slug
|
|
25
|
+
* @param {string} description
|
|
26
|
+
* @param {StringKvLookup} [extra]
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
29
|
+
const error = (fieldName, slug, description, extra) =>
|
|
30
|
+
new ApiError(500, description, {
|
|
31
|
+
[fieldName]: new ValidationError(slug, description),
|
|
32
|
+
...extra,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const instanceName = (() => {
|
|
36
|
+
const name = c.queryParam('name').trim()
|
|
37
|
+
if (name) {
|
|
38
|
+
if (name.match(/^[a-z][a-z0-9-]{2,39}$/) === null) {
|
|
39
|
+
throw error(
|
|
40
|
+
`instanceName`,
|
|
41
|
+
`invalid`,
|
|
42
|
+
`Instance name must begin with a letter, be between 3-40 characters, and can only contain a-z, 0-9, and hyphen (-).`,
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
if (isAvailable(name)) {
|
|
46
|
+
return name
|
|
47
|
+
}
|
|
48
|
+
throw error(
|
|
49
|
+
`instanceName`,
|
|
50
|
+
`exists`,
|
|
51
|
+
`Instance name ${name} is not available.`,
|
|
52
|
+
)
|
|
53
|
+
} else {
|
|
54
|
+
const random = require(`${__hooks}/random-words.js`)
|
|
55
|
+
let i = 0
|
|
56
|
+
while (true) {
|
|
57
|
+
i++
|
|
58
|
+
if (i > 100) {
|
|
59
|
+
return +new Date()
|
|
60
|
+
}
|
|
61
|
+
const slug = random.generate(2).join(`-`)
|
|
62
|
+
if (isAvailable(slug)) return slug
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
})()
|
|
66
|
+
return c.json(200, { instanceName })
|
|
67
|
+
} /* optional middlewares */,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
// HTTP 200
|
|
72
|
+
{
|
|
73
|
+
status: 'ok'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// HTTP 500
|
|
77
|
+
{
|
|
78
|
+
"code": 500,
|
|
79
|
+
"message": "That user account already exists. Try a password reset.",
|
|
80
|
+
"data": {
|
|
81
|
+
"email": {
|
|
82
|
+
"code": "exists",
|
|
83
|
+
"message": "That user account already exists. Try a password reset."
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
{
|
|
89
|
+
"code": 500,
|
|
90
|
+
"message": "Instance name was taken, sorry about that. Try another.",
|
|
91
|
+
"data": {
|
|
92
|
+
"instanceName": {
|
|
93
|
+
"code": "exists",
|
|
94
|
+
"message": "Instance name was taken, sorry about that. Try another."
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
// https://pocketbase.io/docs/js-routing/#sending-request-to-custom-routes-using-the-sdks
|
|
101
|
+
routerAdd(
|
|
102
|
+
'POST',
|
|
103
|
+
'/api/signup',
|
|
104
|
+
(c) => {
|
|
105
|
+
const dao = $app.dao()
|
|
106
|
+
const parsed = (() => {
|
|
107
|
+
const rawBody = readerToString(c.request().body)
|
|
108
|
+
try {
|
|
109
|
+
const parsed = JSON.parse(rawBody)
|
|
110
|
+
return parsed
|
|
111
|
+
} catch (e) {
|
|
112
|
+
throw new BadRequestError(
|
|
113
|
+
`Error parsing payload. You call this JSON? ${rawBody}`,
|
|
114
|
+
e,
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
})()
|
|
118
|
+
const email = parsed.email?.trim()
|
|
119
|
+
const password = parsed.password?.trim()
|
|
120
|
+
const desiredInstanceName = parsed.instanceName?.trim()
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {string} fieldName
|
|
124
|
+
* @param {string} slug
|
|
125
|
+
* @param {string} description
|
|
126
|
+
* @param {StringKvLookup} [extra]
|
|
127
|
+
* @returns
|
|
128
|
+
*/
|
|
129
|
+
const error = (fieldName, slug, description, extra) =>
|
|
130
|
+
new ApiError(500, description, {
|
|
131
|
+
[fieldName]: new ValidationError(slug, description),
|
|
132
|
+
...extra,
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
if (!email) {
|
|
136
|
+
throw error(`email`, 'required', 'Email is required')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!password) {
|
|
140
|
+
throw error(`password`, `required`, 'Password is required')
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!desiredInstanceName) {
|
|
144
|
+
throw error(`instanceName`, `required`, `Instance name is required`)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const userExists = (() => {
|
|
148
|
+
try {
|
|
149
|
+
const record = dao.findFirstRecordByData('users', 'email', email)
|
|
150
|
+
return true
|
|
151
|
+
} catch {
|
|
152
|
+
return false
|
|
153
|
+
}
|
|
154
|
+
})()
|
|
155
|
+
|
|
156
|
+
if (userExists) {
|
|
157
|
+
throw error(
|
|
158
|
+
`email`,
|
|
159
|
+
`exists`,
|
|
160
|
+
`That user account already exists. Try a password reset.`,
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
dao.runInTransaction((txDao) => {
|
|
165
|
+
const usersCollection = dao.findCollectionByNameOrId('users')
|
|
166
|
+
const instanceCollection = $app
|
|
167
|
+
.dao()
|
|
168
|
+
.findCollectionByNameOrId('instances')
|
|
169
|
+
|
|
170
|
+
const user = new Record(usersCollection)
|
|
171
|
+
try {
|
|
172
|
+
const username = $app
|
|
173
|
+
.dao()
|
|
174
|
+
.suggestUniqueAuthRecordUsername(
|
|
175
|
+
'users',
|
|
176
|
+
'user' + $security.randomStringWithAlphabet(5, '123456789'),
|
|
177
|
+
)
|
|
178
|
+
user.set('username', username)
|
|
179
|
+
user.set('email', email)
|
|
180
|
+
user.set('subscription', 'free')
|
|
181
|
+
user.set('notifyMaintenanceMode', true)
|
|
182
|
+
user.setPassword(password)
|
|
183
|
+
txDao.saveRecord(user)
|
|
184
|
+
} catch (e) {
|
|
185
|
+
throw error(`email`, `fail`, `Could not create user: ${e}`)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
const instance = new Record(instanceCollection)
|
|
190
|
+
instance.set('subdomain', desiredInstanceName)
|
|
191
|
+
instance.set('uid', user.get('id'))
|
|
192
|
+
instance.set('status', 'idle')
|
|
193
|
+
instance.set('notifyMaintenanceMode', true)
|
|
194
|
+
instance.set('syncAdmin', true)
|
|
195
|
+
const { versions } = require(`${__hooks}/versions.js`)
|
|
196
|
+
instance.set('version', versions[0])
|
|
197
|
+
txDao.saveRecord(instance)
|
|
198
|
+
} catch (e) {
|
|
199
|
+
if (`${e}`.match(/ UNIQUE /)) {
|
|
200
|
+
throw error(
|
|
201
|
+
`instanceName`,
|
|
202
|
+
`exists`,
|
|
203
|
+
`Instance name was taken, sorry about that. Try another.`,
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
throw error(`instanceName`, `fail`, `Could not create instance: ${e}`)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
$mails.sendRecordVerification($app, user)
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
return c.json(200, { status: 'ok' })
|
|
213
|
+
} /* optional middlewares */,
|
|
214
|
+
)
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/// <reference path="../types/types.d.ts" />
|
|
2
|
+
|
|
3
|
+
routerAdd('POST', '/api/sns', (c) => {
|
|
4
|
+
const dao = $app.dao()
|
|
5
|
+
const { mkLog, audit } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
|
6
|
+
const log = mkLog(`sns`)
|
|
7
|
+
|
|
8
|
+
const processBounce = (emailAddress) => {
|
|
9
|
+
log(`Processing ${emailAddress}`)
|
|
10
|
+
const extra = /** @type {{ email: string; user: string }} */ ({
|
|
11
|
+
email: emailAddress,
|
|
12
|
+
})
|
|
13
|
+
try {
|
|
14
|
+
const user = dao.findFirstRecordByData('users', 'email', emailAddress)
|
|
15
|
+
log(`user is`, user)
|
|
16
|
+
extra.user = user.getId()
|
|
17
|
+
user.setVerified(false)
|
|
18
|
+
dao.saveRecord(user)
|
|
19
|
+
audit('PBOUNCE', `User ${emailAddress} has been disabled`, {
|
|
20
|
+
dao,
|
|
21
|
+
extra,
|
|
22
|
+
log,
|
|
23
|
+
})
|
|
24
|
+
} catch (e) {
|
|
25
|
+
audit('PBOUNCE_ERR', `${e}`, { dao, log, extra })
|
|
26
|
+
log(`After audit`)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
;[].forEach(processBounce)
|
|
31
|
+
|
|
32
|
+
const raw = readerToString(c.request().body)
|
|
33
|
+
const data = JSON.parse(raw)
|
|
34
|
+
log(JSON.stringify(data, null, 2))
|
|
35
|
+
|
|
36
|
+
const { Type } = data
|
|
37
|
+
|
|
38
|
+
switch (Type) {
|
|
39
|
+
case `SubscriptionConfirmation`:
|
|
40
|
+
const url = data.SubscribeURL
|
|
41
|
+
log(url)
|
|
42
|
+
$http.send({ url })
|
|
43
|
+
return c.json(200, { status: 'ok' })
|
|
44
|
+
|
|
45
|
+
case `Notification`:
|
|
46
|
+
const msg = JSON.parse(data.Message)
|
|
47
|
+
log(msg)
|
|
48
|
+
const { notificationType } = msg
|
|
49
|
+
switch (notificationType) {
|
|
50
|
+
case `Bounce`: {
|
|
51
|
+
log(`Message is a bounce`)
|
|
52
|
+
const { bounce } = msg
|
|
53
|
+
const { bounceType } = bounce
|
|
54
|
+
switch (bounceType) {
|
|
55
|
+
case `Permanent`:
|
|
56
|
+
log(`Message is a permanent bounce`)
|
|
57
|
+
const { bouncedRecipients } = bounce
|
|
58
|
+
bouncedRecipients.forEach((recipient) => {
|
|
59
|
+
const { emailAddress } = recipient
|
|
60
|
+
processBounce(emailAddress)
|
|
61
|
+
})
|
|
62
|
+
break
|
|
63
|
+
default:
|
|
64
|
+
audit('SNS_ERR', `Unrecognized bounce type ${bounceType}`, {
|
|
65
|
+
dao,
|
|
66
|
+
log,
|
|
67
|
+
extra: { raw_payload: raw },
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
break
|
|
71
|
+
}
|
|
72
|
+
case `Complaint`:
|
|
73
|
+
{
|
|
74
|
+
log(`Message is a Complaint`, msg)
|
|
75
|
+
const { complaint } = msg
|
|
76
|
+
const { complainedRecipients } = complaint
|
|
77
|
+
complainedRecipients.forEach((recipient) => {
|
|
78
|
+
const { emailAddress } = recipient
|
|
79
|
+
log(`Processing ${emailAddress}`)
|
|
80
|
+
try {
|
|
81
|
+
const user = $app
|
|
82
|
+
.dao()
|
|
83
|
+
.findFirstRecordByData('users', 'email', emailAddress)
|
|
84
|
+
log(`user is`, user)
|
|
85
|
+
user.set(`unsubscribe`, true)
|
|
86
|
+
dao.saveRecord(user)
|
|
87
|
+
audit(
|
|
88
|
+
'COMPLAINT',
|
|
89
|
+
`User ${emailAddress} has been unsubscribed`,
|
|
90
|
+
{
|
|
91
|
+
log,
|
|
92
|
+
dao,
|
|
93
|
+
extra: { email: emailAddress, user: user.getId() },
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
} catch (e) {
|
|
97
|
+
audit(
|
|
98
|
+
'COMPLAINT_ERR',
|
|
99
|
+
`${emailAddress} is not in the system.`,
|
|
100
|
+
{
|
|
101
|
+
log,
|
|
102
|
+
dao,
|
|
103
|
+
extra: {
|
|
104
|
+
email: emailAddress,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
break
|
|
112
|
+
default:
|
|
113
|
+
audit(
|
|
114
|
+
'SNS_ERR',
|
|
115
|
+
`Unrecognized notification type ${notificationType}`,
|
|
116
|
+
{
|
|
117
|
+
log,
|
|
118
|
+
dao,
|
|
119
|
+
extra: { raw_payload: raw },
|
|
120
|
+
},
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
break
|
|
124
|
+
default:
|
|
125
|
+
audit(`SNS_ERR`, `Message ${Type} not handled`, {
|
|
126
|
+
log,
|
|
127
|
+
dao,
|
|
128
|
+
extra: { raw_payload: raw },
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return c.json(200, { status: 'ok' })
|
|
133
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/// <reference path="../types/types.d.ts" />
|
|
2
|
+
|
|
3
|
+
routerAdd('GET', '/api/unsubscribe', (c) => {
|
|
4
|
+
const dao = $app.dao()
|
|
5
|
+
const { mkLog, audit } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
|
6
|
+
const log = mkLog(`unsubscribe`)
|
|
7
|
+
|
|
8
|
+
const id = c.queryParam('e')
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const record = dao.findRecordById('users', id)
|
|
12
|
+
record.set(`unsubscribe`, true)
|
|
13
|
+
dao.saveRecord(record)
|
|
14
|
+
|
|
15
|
+
const email = record.getString('email')
|
|
16
|
+
audit('UNSUBSCRIBE', '', { dao, log, extra: { email, user: id } })
|
|
17
|
+
|
|
18
|
+
$app.newMailClient().send(
|
|
19
|
+
new MailerMessage({
|
|
20
|
+
from: {
|
|
21
|
+
address: $app.settings().meta.senderAddress,
|
|
22
|
+
name: $app.settings().meta.senderName,
|
|
23
|
+
},
|
|
24
|
+
to: [{ address: `ben@benallfree.com` }],
|
|
25
|
+
subject: `UNSUBSCRIBE ${email}`,
|
|
26
|
+
}),
|
|
27
|
+
)
|
|
28
|
+
return c.html(200, `<p>${email} has been unsubscribed.`)
|
|
29
|
+
} catch (e) {
|
|
30
|
+
audit('UNSUBSCRIBE_ERR', `User ${id} not found`, { dao, log })
|
|
31
|
+
return c.html(200, `<p>Looks like you're already unsubscribed.`)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/// <reference path="../types/types.d.ts" />
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
{
|
|
5
|
+
"id": "user-id"
|
|
6
|
+
}
|
|
7
|
+
*/
|
|
8
|
+
routerAdd(
|
|
9
|
+
'GET',
|
|
10
|
+
'/api/userToken/:id',
|
|
11
|
+
(c) => {
|
|
12
|
+
const dao = $app.dao()
|
|
13
|
+
const { mkLog } = /** @type {Lib} */ (require(`${__hooks}/lib.js`))
|
|
14
|
+
const log = mkLog(`user-token`)
|
|
15
|
+
|
|
16
|
+
const id = c.pathParam('id')
|
|
17
|
+
|
|
18
|
+
log({ id })
|
|
19
|
+
|
|
20
|
+
if (!id) {
|
|
21
|
+
throw new BadRequestError(`User ID is required.`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const rec = dao.findRecordById('users', id)
|
|
25
|
+
const tokenKey = rec.getString('tokenKey')
|
|
26
|
+
const passwordHash = rec.getString('passwordHash')
|
|
27
|
+
const email = rec.getString(`email`)
|
|
28
|
+
log({ email, passwordHash, tokenKey })
|
|
29
|
+
|
|
30
|
+
return c.json(200, { email, passwordHash, tokenKey })
|
|
31
|
+
},
|
|
32
|
+
$apis.requireAdminAuth(),
|
|
33
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/// <reference path="../types/types.d.ts" />
|
|
2
|
+
|
|
3
|
+
onModelBeforeUpdate((e) => {
|
|
4
|
+
const dao = e.dao || $app.dao()
|
|
5
|
+
const newModel = /** @type {models.Record} */ (e.model)
|
|
6
|
+
const oldModel = newModel.originalCopy()
|
|
7
|
+
|
|
8
|
+
const { audit, mkLog, enqueueNotification } = /** @type {Lib} */ (
|
|
9
|
+
require(`${__hooks}/lib.js`)
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
const log = mkLog(`user-welcome-msg`)
|
|
13
|
+
try {
|
|
14
|
+
log({ newModel, oldModel })
|
|
15
|
+
|
|
16
|
+
// Bail out if we aren't verified
|
|
17
|
+
const isVerified = newModel.getBool('verified')
|
|
18
|
+
if (!isVerified) return
|
|
19
|
+
|
|
20
|
+
// Bail out if the verified mode flag has not changed
|
|
21
|
+
if (isVerified === oldModel.getBool(`verified`)) return
|
|
22
|
+
|
|
23
|
+
log(`user just became verified`)
|
|
24
|
+
const uid = newModel.getId()
|
|
25
|
+
|
|
26
|
+
enqueueNotification(`email`, `welcome`, uid, { log, dao })
|
|
27
|
+
newModel.set(`welcome`, new DateTime())
|
|
28
|
+
} catch (e) {
|
|
29
|
+
audit(`ERROR`, `${e}`, { log, dao, extra: { user: newModel.getId() } })
|
|
30
|
+
throw e
|
|
31
|
+
}
|
|
32
|
+
}, 'users')
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference path="../types/types.d.ts" />
|
|
2
|
+
|
|
3
|
+
/** Return a list of available PocketBase versions */
|
|
4
|
+
routerAdd(
|
|
5
|
+
'GET',
|
|
6
|
+
'/api/versions',
|
|
7
|
+
(c) => {
|
|
8
|
+
const { versions } = require(`${__hooks}/versions.js`)
|
|
9
|
+
|
|
10
|
+
return c.json(200, { versions })
|
|
11
|
+
} /* optional middlewares */,
|
|
12
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function seedrandom(seed: number): void
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
interface Require {
|
|
2
|
+
(id: string): any
|
|
3
|
+
}
|
|
4
|
+
declare var require: Require
|
|
5
|
+
|
|
6
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console) */
|
|
7
|
+
interface Console {
|
|
8
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/assert) */
|
|
9
|
+
assert(condition?: boolean, ...data: any[]): void
|
|
10
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/clear) */
|
|
11
|
+
clear(): void
|
|
12
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/count) */
|
|
13
|
+
count(label?: string): void
|
|
14
|
+
/**
|
|
15
|
+
* [MDN
|
|
16
|
+
* Reference](https://developer.mozilla.org/docs/Web/API/console/countReset)
|
|
17
|
+
*/
|
|
18
|
+
countReset(label?: string): void
|
|
19
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/debug) */
|
|
20
|
+
debug(...data: any[]): void
|
|
21
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/dir) */
|
|
22
|
+
dir(item?: any, options?: any): void
|
|
23
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/dirxml) */
|
|
24
|
+
dirxml(...data: any[]): void
|
|
25
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/error) */
|
|
26
|
+
error(...data: any[]): void
|
|
27
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/group) */
|
|
28
|
+
group(...data: any[]): void
|
|
29
|
+
/**
|
|
30
|
+
* [MDN
|
|
31
|
+
* Reference](https://developer.mozilla.org/docs/Web/API/console/groupCollapsed)
|
|
32
|
+
*/
|
|
33
|
+
groupCollapsed(...data: any[]): void
|
|
34
|
+
/**
|
|
35
|
+
* [MDN
|
|
36
|
+
* Reference](https://developer.mozilla.org/docs/Web/API/console/groupEnd)
|
|
37
|
+
*/
|
|
38
|
+
groupEnd(): void
|
|
39
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/info) */
|
|
40
|
+
info(...data: any[]): void
|
|
41
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log) */
|
|
42
|
+
log(...data: any[]): void
|
|
43
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/table) */
|
|
44
|
+
table(tabularData?: any, properties?: string[]): void
|
|
45
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/time) */
|
|
46
|
+
time(label?: string): void
|
|
47
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeEnd) */
|
|
48
|
+
timeEnd(label?: string): void
|
|
49
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeLog) */
|
|
50
|
+
timeLog(label?: string, ...data: any[]): void
|
|
51
|
+
timeStamp(label?: string): void
|
|
52
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/trace) */
|
|
53
|
+
trace(...data: any[]): void
|
|
54
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/warn) */
|
|
55
|
+
warn(...data: any[]): void
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
declare var console: Console
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface WebHook {
|
|
2
|
+
meta: { custom_data: { user_id: string } }
|
|
3
|
+
data: {
|
|
4
|
+
type: 'orders' | string
|
|
5
|
+
attributes: {
|
|
6
|
+
order_number: number
|
|
7
|
+
first_order_item: { product_name: string; product_id: number }
|
|
8
|
+
status: 'active' | 'paid' | string
|
|
9
|
+
user_email: string
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
type Logger = (...args: any[]) => void
|
|
2
|
+
|
|
3
|
+
type StringKvLookup = { [_: string]: string }
|
|
4
|
+
|
|
5
|
+
type AuditEvents =
|
|
6
|
+
| 'ERROR'
|
|
7
|
+
| 'NOTIFICATION_ERR'
|
|
8
|
+
| 'LS'
|
|
9
|
+
| 'LS_ERR'
|
|
10
|
+
| 'PBOUNCE'
|
|
11
|
+
| 'PBOUNCE_ERR'
|
|
12
|
+
| 'SNS_ERR'
|
|
13
|
+
| 'COMPLAINT'
|
|
14
|
+
| 'COMPLAINT_ERR'
|
|
15
|
+
| 'UNSUBSCRIBE'
|
|
16
|
+
| 'UNSUBSCRIBE_ERR'
|
|
17
|
+
|
|
18
|
+
interface Lib {
|
|
19
|
+
mkLog: (namespace: string) => Logger
|
|
20
|
+
processNotification: (
|
|
21
|
+
notificationRec: models.Record,
|
|
22
|
+
context: { log: Logger; test?: boolean; dao: daos.Dao },
|
|
23
|
+
) => void
|
|
24
|
+
enqueueNotification: (
|
|
25
|
+
channel: 'email' | 'lemonbot',
|
|
26
|
+
template:
|
|
27
|
+
| 'maintenance-mode'
|
|
28
|
+
| 'lemon_order_email'
|
|
29
|
+
| 'lemon_order_discord'
|
|
30
|
+
| 'welcome',
|
|
31
|
+
user_id: string,
|
|
32
|
+
context: {
|
|
33
|
+
message_template_vars?: { [_: string]: string }
|
|
34
|
+
dao: daos.Dao
|
|
35
|
+
log: Logger
|
|
36
|
+
},
|
|
37
|
+
) => void
|
|
38
|
+
|
|
39
|
+
audit: (
|
|
40
|
+
event: AuditEvents,
|
|
41
|
+
note: string,
|
|
42
|
+
context: {
|
|
43
|
+
log: Logger
|
|
44
|
+
|
|
45
|
+
dao: daos.Dao
|
|
46
|
+
extra?: Partial<{
|
|
47
|
+
notification: string
|
|
48
|
+
email: string
|
|
49
|
+
user: string
|
|
50
|
+
raw_payload: string
|
|
51
|
+
}>
|
|
52
|
+
},
|
|
53
|
+
) => void
|
|
54
|
+
removeEmptyKeys: <T>(obj: T) => T
|
|
55
|
+
}
|