querysub 0.154.0 → 0.155.0
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/4-deploy/deployMain.ts +5 -3
- package/src/4-dom/qreact.tsx +1 -0
- package/src/diagnostics/logs/injectFileLocationToConsole.ts +2 -1
- package/src/library-components/URLParam.ts +7 -2
- package/src/library-components/loadingIndicator.tsx +93 -0
- package/src/user-implementation/LoginPage.tsx +1 -1
- package/src/user-implementation/UserPage.tsx +1 -1
- package/src/user-implementation/addSuperUser.ts +12 -6
- package/src/user-implementation/setEmailKey.ts +10 -5
- package/src/user-implementation/userData.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "querysub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.155.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
|
|
25
25
|
"pako": "^2.1.0",
|
|
26
26
|
"preact": "^10.11.3",
|
|
27
|
-
"socket-function": "^0.
|
|
27
|
+
"socket-function": "^0.88.0",
|
|
28
28
|
"terser": "^5.31.0",
|
|
29
29
|
"typesafecss": "^0.6.3",
|
|
30
30
|
"yaml": "^2.5.0",
|
|
@@ -137,11 +137,13 @@ export async function deployMain() {
|
|
|
137
137
|
debugName: "setLiveDeployedHash",
|
|
138
138
|
inlineNestedWatchers: true,
|
|
139
139
|
watchFunction: () => {
|
|
140
|
-
if (
|
|
140
|
+
if (yargObj.deployonlycode) {
|
|
141
141
|
void setLiveDeployedHash({ hash: gitRef, refreshThresholdTime, });
|
|
142
|
-
}
|
|
143
|
-
|
|
142
|
+
} else if (yargObj.deployonlyui) {
|
|
143
|
+
void replaceFunctions({ domainName, functions: currentFunctions, });
|
|
144
|
+
} else {
|
|
144
145
|
void replaceFunctions({ domainName, functions: currentFunctions, });
|
|
146
|
+
void setLiveDeployedHash({ hash: gitRef, refreshThresholdTime, });
|
|
145
147
|
}
|
|
146
148
|
},
|
|
147
149
|
});
|
package/src/4-dom/qreact.tsx
CHANGED
|
@@ -79,6 +79,7 @@ export namespace qreact {
|
|
|
79
79
|
export type ComponentChildren = preact.ComponentChildren;
|
|
80
80
|
export type VDom = preact.ComponentChildren;
|
|
81
81
|
export type Component = InstanceType<typeof Component>;
|
|
82
|
+
export type ComponentClass = preact.ComponentClass;
|
|
82
83
|
export namespace JSX {
|
|
83
84
|
export type IntrinsicElements = {
|
|
84
85
|
[key in keyof preact.JSX.IntrinsicElements]: (
|
|
@@ -41,7 +41,8 @@ if (isNode()) {
|
|
|
41
41
|
.replaceAll(` logDisk(`, ` logDisk(console.__context, { __LINE__: ${index} },`)
|
|
42
42
|
;
|
|
43
43
|
}).join("\n");
|
|
44
|
-
|
|
44
|
+
// IMPORTANT! No newlines, so the line numbers match up with the original source.
|
|
45
|
+
return `var console = (${shimConsole.toString().replaceAll("\n", " ")})(); ${contents}`;
|
|
45
46
|
});
|
|
46
47
|
|
|
47
48
|
// We want to call shimConsoleLogs early. Before we call it, our additional context isn't
|
|
@@ -63,14 +63,19 @@ export function createURLSync<T>(urlKey: string, defaultValue: T, config?: {
|
|
|
63
63
|
if (config?.storage === "localStorage") {
|
|
64
64
|
localStorageKeys.add(urlKey);
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
function setDefaults() {
|
|
67
67
|
Querysub.localCommit(() => {
|
|
68
68
|
data().defaults[urlKey] = defaultValue;
|
|
69
69
|
if (!(urlKey in loadSearchCache)) {
|
|
70
70
|
data().params[urlKey] = deepCloneJSON(defaultValue);
|
|
71
71
|
}
|
|
72
72
|
});
|
|
73
|
-
}
|
|
73
|
+
}
|
|
74
|
+
if (!Querysub) {
|
|
75
|
+
setImmediate(setDefaults);
|
|
76
|
+
} else {
|
|
77
|
+
setDefaults();
|
|
78
|
+
}
|
|
74
79
|
function deleteKeys(obj: any) {
|
|
75
80
|
if (!canHaveChildren(obj)) return;
|
|
76
81
|
for (let key in obj) {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { qreact } from "../4-dom/qreact";
|
|
2
|
+
import { Querysub } from "../4-querysub/Querysub";
|
|
3
|
+
import { css } from "typesafecss";
|
|
4
|
+
import { formatNumber, formatTime } from "socket-function/src/formatting/format";
|
|
5
|
+
|
|
6
|
+
export class UnsyncedIndicator extends qreact.Component {
|
|
7
|
+
lastSynced = Date.now();
|
|
8
|
+
render() {
|
|
9
|
+
let unsynced = Querysub.watchUnsyncedComponents();
|
|
10
|
+
let unsyncedCount = unsynced.size;
|
|
11
|
+
if (unsyncedCount === 0) {
|
|
12
|
+
this.lastSynced = Date.now();
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
let timeSinceLastSync = Date.now() - this.lastSynced;
|
|
16
|
+
if (timeSinceLastSync < 1500) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
if (timeSinceLastSync > 30 * 1000) {
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
title={`Server has not responded for ${formatTime(timeSinceLastSync)}`}
|
|
23
|
+
className={
|
|
24
|
+
css.vbox(10).pad(20)
|
|
25
|
+
.hsla(0, 0, 0, 0.8)
|
|
26
|
+
.position("fixed")
|
|
27
|
+
.bottom(10)
|
|
28
|
+
.right(10)
|
|
29
|
+
.zIndex(1000)
|
|
30
|
+
}
|
|
31
|
+
>
|
|
32
|
+
<div className={css.vbox(10).maxWidth(250)}>
|
|
33
|
+
<h3 className={css.margin(0)}>Server Not Responding</h3>
|
|
34
|
+
<div>The server has not responded for {formatTime(timeSinceLastSync)}. It is recommended to refresh the page to try to resolve this issue.</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div className={css.hbox(10).justifyContent("flex-end")}>
|
|
37
|
+
<button
|
|
38
|
+
className={css.pad(8, 16).hsl(200, 50, 50).color("white").pointer}
|
|
39
|
+
onClick={() => {
|
|
40
|
+
window.location.reload();
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
Refresh Now
|
|
44
|
+
</button>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
let magnitude = Math.ceil(Math.log2(unsyncedCount + 1) / Math.log2(6));
|
|
50
|
+
return <div
|
|
51
|
+
class={
|
|
52
|
+
css
|
|
53
|
+
.position("fixed").bottom(0).right(0)
|
|
54
|
+
.background("hsl(0, 0%, 10%)").color("hsl(0, 0%, 80%)")
|
|
55
|
+
.fontSize(12).zIndex(1000)
|
|
56
|
+
.borderRadius(100)
|
|
57
|
+
}
|
|
58
|
+
title={`Loading data for ${formatNumber(unsyncedCount)} components`}
|
|
59
|
+
>
|
|
60
|
+
<svg
|
|
61
|
+
width="60px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"
|
|
62
|
+
|
|
63
|
+
>
|
|
64
|
+
{
|
|
65
|
+
[
|
|
66
|
+
// The smaller they are, the faster they should go
|
|
67
|
+
// Large should be more blue, smaller more red
|
|
68
|
+
["hsl(-20, 75%, 75%)", "1.5", "1s", "10"],
|
|
69
|
+
["hsl(-5, 75%, 75%)", "2", "1.5s", "15"],
|
|
70
|
+
["hsl(-35, 75%, 75%)", "1", "0.5s", "5"],
|
|
71
|
+
["hsl(10, 75%, 75%)", "2.5", "2s", "20"],
|
|
72
|
+
["hsl(25, 75%, 75%)", "3", "2.5s", "25"],
|
|
73
|
+
["hsl(70, 75%, 75%)", "3.5", "3s", "30"],
|
|
74
|
+
["hsl(115, 75%, 75%)", "4", "3.5s", "35"],
|
|
75
|
+
["hsl(160, 75%, 75%)", "4.5", "4s", "40"],
|
|
76
|
+
["hsl(205, 75%, 75%)", "5", "4.5s", "45"],
|
|
77
|
+
["hsl(230, 75%, 75%)", "5.5", "5s", "50"],
|
|
78
|
+
].slice(0, magnitude).map(([color, r, dur, o]) =>
|
|
79
|
+
<circle cx="50" cy={50 + Number(o)} r={Number(r) * 2} fill={color}>
|
|
80
|
+
<animateTransform
|
|
81
|
+
attributeName="transform"
|
|
82
|
+
type="rotate"
|
|
83
|
+
from={`0 50 50`} to={`360 50 50`}
|
|
84
|
+
dur={dur} repeatCount="indefinite"
|
|
85
|
+
/>
|
|
86
|
+
</circle>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
</svg>
|
|
90
|
+
|
|
91
|
+
</div>;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import { Querysub } from "../4-querysub/Querysub";
|
|
2
2
|
import { scriptCreateUser } from "./userData";
|
|
3
3
|
import { pathValueCommitter } from "../0-path-value-core/PathValueCommitter";
|
|
4
|
+
import yargs from "yargs";
|
|
5
|
+
import { isNodeTrue } from "socket-function/src/misc";
|
|
6
|
+
|
|
7
|
+
let yargObj = isNodeTrue() && yargs(process.argv)
|
|
8
|
+
.option("email", { type: "string", desc: `The email of the user to add as a superuser.` })
|
|
9
|
+
.argv || {}
|
|
10
|
+
;
|
|
4
11
|
|
|
5
12
|
async function main() {
|
|
6
|
-
const howToCall = ` Call with yarn addsuperuser <email>`;
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (!userId.includes("@")) throw new Error(`Invalid email ${userId}.` + howToCall);
|
|
13
|
+
const howToCall = ` Call with yarn addsuperuser --email <email>`;
|
|
14
|
+
const email = yargObj.email;
|
|
15
|
+
if (!email) throw new Error("No email provided." + howToCall);
|
|
16
|
+
if (!email.includes("@")) throw new Error(`Invalid email ${email}.` + howToCall);
|
|
17
|
+
const userId = email;
|
|
12
18
|
|
|
13
19
|
await Querysub.hostService("addSuperUser");
|
|
14
20
|
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { Querysub } from "../4-querysub/Querysub";
|
|
2
2
|
import { pathValueCommitter } from "../0-path-value-core/PathValueCommitter";
|
|
3
3
|
import { scriptSetPostmarkAPIKey } from "./userData";
|
|
4
|
+
import { isNodeTrue } from "socket-function/src/misc";
|
|
5
|
+
import yargs from "yargs";
|
|
6
|
+
|
|
7
|
+
let yargObj = isNodeTrue() && yargs(process.argv)
|
|
8
|
+
.option("key", { type: "string", desc: `The key to set for the email.` })
|
|
9
|
+
.argv || {}
|
|
10
|
+
;
|
|
4
11
|
|
|
5
12
|
async function main() {
|
|
6
|
-
const howToCall = ` Call with yarn setemailkey <key>`;
|
|
7
|
-
const
|
|
8
|
-
const key = args[0];
|
|
9
|
-
console.log(process.argv);
|
|
13
|
+
const howToCall = ` Call with yarn setemailkey --key <key>`;
|
|
14
|
+
const key = yargObj.key;
|
|
10
15
|
if (!key) throw new Error("No key provided." + howToCall);
|
|
11
16
|
|
|
12
|
-
await Querysub.hostService("
|
|
17
|
+
await Querysub.hostService("setEmailKey");
|
|
13
18
|
|
|
14
19
|
await Querysub.commitSynced(() => {
|
|
15
20
|
scriptSetPostmarkAPIKey({ apiKey: key });
|
|
@@ -651,6 +651,8 @@ function sendLoginEmail(config: {
|
|
|
651
651
|
await sendEmail_postmark({
|
|
652
652
|
apiKey,
|
|
653
653
|
to: email,
|
|
654
|
+
// TODO: Allow configuring this (defaulting to getDomain() if unconfigured). For now we hardcode it, because it takes
|
|
655
|
+
// a while to verify a new postmark email, and we don't even know what final domain we will be using.
|
|
654
656
|
from: "login@querysub.com",
|
|
655
657
|
subject,
|
|
656
658
|
contents,
|