@gryt/core 0.2.0 → 0.3.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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/servers/address.d.ts +43 -0
- package/dist/servers/address.js +84 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -14,5 +14,6 @@
|
|
|
14
14
|
export { buildReport, describeAttached, MESSAGE_MAX, TITLE_MAX, type Diagnostics, type Report, type ReportType, } from "./reports/report.js";
|
|
15
15
|
export { getAccentColor, getLinkProvider, getProviderDetail, hostnameOf, LINK_PROVIDERS, type LinkProvider, } from "./links/providers.js";
|
|
16
16
|
export { describePreviewFailure, extractUrls, getCardSubtitle, getLinkCardLayout, type LinkCardLayout, type LinkPreviewData, } from "./links/preview.js";
|
|
17
|
+
export { normalizeCode, normalizeHost, parseServerInput, type ServerInput, } from "./servers/address.js";
|
|
17
18
|
export { NAME_POOL, pickRandomName } from "./profile/randomName.js";
|
|
18
19
|
export { cellState, CUSTOM_VALUE, describeRules, EVERYONE_VALUE, indexRules, nextCellState, scopeChoiceFromValue, scopeChoiceValue, scopeOptions, scopeSetPayload, withCell, type CellState, type ChannelRule, type RuleEffect, type ScopeChoice, } from "./permissions/channelRules.js";
|
package/dist/index.js
CHANGED
|
@@ -14,5 +14,6 @@
|
|
|
14
14
|
export { buildReport, describeAttached, MESSAGE_MAX, TITLE_MAX, } from "./reports/report.js";
|
|
15
15
|
export { getAccentColor, getLinkProvider, getProviderDetail, hostnameOf, LINK_PROVIDERS, } from "./links/providers.js";
|
|
16
16
|
export { describePreviewFailure, extractUrls, getCardSubtitle, getLinkCardLayout, } from "./links/preview.js";
|
|
17
|
+
export { normalizeCode, normalizeHost, parseServerInput, } from "./servers/address.js";
|
|
17
18
|
export { NAME_POOL, pickRandomName } from "./profile/randomName.js";
|
|
18
19
|
export { cellState, CUSTOM_VALUE, describeRules, EVERYONE_VALUE, indexRules, nextCellState, scopeChoiceFromValue, scopeChoiceValue, scopeOptions, scopeSetPayload, withCell, } from "./permissions/channelRules.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading whatever somebody pasted into the join field.
|
|
3
|
+
*
|
|
4
|
+
* Both apps had this, byte for byte: `normalizeHost`, `normalizeCode` and all
|
|
5
|
+
* of `parseServerInput`, down to the comments. The phone said so in its own
|
|
6
|
+
* header — a copy, because the desktop's `common` package was never published,
|
|
7
|
+
* written down in GRYT-406 rather than left to be found once the two had
|
|
8
|
+
* drifted.
|
|
9
|
+
*
|
|
10
|
+
* They had not drifted, which is the only comfortable moment to do this. The
|
|
11
|
+
* two apps talk to the same servers, so an address one reads differently is a
|
|
12
|
+
* server the other cannot join, and that failure looks like the server being
|
|
13
|
+
* down rather than like a parser disagreeing.
|
|
14
|
+
*
|
|
15
|
+
* What stayed behind is the scheme memory — `schemeFor`, `rememberScheme` and
|
|
16
|
+
* the rest. Those reach for storage and the two apps store differently, so they
|
|
17
|
+
* fail the test at the top of this package.
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizeHost(input: string): string;
|
|
20
|
+
export declare function normalizeCode(input: string): string;
|
|
21
|
+
export interface ServerInput {
|
|
22
|
+
/** Empty when nothing usable was in the input. */
|
|
23
|
+
host: string;
|
|
24
|
+
/** Empty for a plain address, which carries no code. */
|
|
25
|
+
code: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Three shapes arrive and they are not the same thing: a full invite link
|
|
29
|
+
* (`https://gryt.chat/invite?host=…&code=…`), a legacy one
|
|
30
|
+
* (`https://app.gryt.chat/invite/<code>`), and a plain address (`gryt.chat`,
|
|
31
|
+
* `192.168.1.5:5001`).
|
|
32
|
+
*
|
|
33
|
+
* `normalizeHost` on its own is wrong for the first two — it returns the
|
|
34
|
+
* *link's* host, which is gryt.chat, and joining that instead of the server
|
|
35
|
+
* named in the query is a confusing failure rather than an obvious one.
|
|
36
|
+
*
|
|
37
|
+
* Anything that does not parse as a link falls through to being an address, so
|
|
38
|
+
* a typo in a URL still gets the address treatment rather than an error about
|
|
39
|
+
* invite formats.
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseServerInput(input: string, opts?: {
|
|
42
|
+
defaultLegacyHost?: string;
|
|
43
|
+
}): ServerInput;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading whatever somebody pasted into the join field.
|
|
3
|
+
*
|
|
4
|
+
* Both apps had this, byte for byte: `normalizeHost`, `normalizeCode` and all
|
|
5
|
+
* of `parseServerInput`, down to the comments. The phone said so in its own
|
|
6
|
+
* header — a copy, because the desktop's `common` package was never published,
|
|
7
|
+
* written down in GRYT-406 rather than left to be found once the two had
|
|
8
|
+
* drifted.
|
|
9
|
+
*
|
|
10
|
+
* They had not drifted, which is the only comfortable moment to do this. The
|
|
11
|
+
* two apps talk to the same servers, so an address one reads differently is a
|
|
12
|
+
* server the other cannot join, and that failure looks like the server being
|
|
13
|
+
* down rather than like a parser disagreeing.
|
|
14
|
+
*
|
|
15
|
+
* What stayed behind is the scheme memory — `schemeFor`, `rememberScheme` and
|
|
16
|
+
* the rest. Those reach for storage and the two apps store differently, so they
|
|
17
|
+
* fail the test at the top of this package.
|
|
18
|
+
*/
|
|
19
|
+
export function normalizeHost(input) {
|
|
20
|
+
let h = String(input || "").trim();
|
|
21
|
+
h = h.replace(/^(wss?:\/\/|https?:\/\/)/i, "");
|
|
22
|
+
h = h.split("/")[0] || "";
|
|
23
|
+
h = h.replace(/\s+/g, "");
|
|
24
|
+
return h;
|
|
25
|
+
}
|
|
26
|
+
export function normalizeCode(input) {
|
|
27
|
+
return String(input || "")
|
|
28
|
+
.trim()
|
|
29
|
+
.replace(/\s+/g, "")
|
|
30
|
+
.toLowerCase();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The default host for a legacy `/invite/<code>` link.
|
|
34
|
+
*
|
|
35
|
+
* Those links carry no host, and the only client ever served from a path like
|
|
36
|
+
* that is the hosted one.
|
|
37
|
+
*/
|
|
38
|
+
const DEFAULT_LEGACY_HOST = "app.gryt.chat";
|
|
39
|
+
/**
|
|
40
|
+
* Three shapes arrive and they are not the same thing: a full invite link
|
|
41
|
+
* (`https://gryt.chat/invite?host=…&code=…`), a legacy one
|
|
42
|
+
* (`https://app.gryt.chat/invite/<code>`), and a plain address (`gryt.chat`,
|
|
43
|
+
* `192.168.1.5:5001`).
|
|
44
|
+
*
|
|
45
|
+
* `normalizeHost` on its own is wrong for the first two — it returns the
|
|
46
|
+
* *link's* host, which is gryt.chat, and joining that instead of the server
|
|
47
|
+
* named in the query is a confusing failure rather than an obvious one.
|
|
48
|
+
*
|
|
49
|
+
* Anything that does not parse as a link falls through to being an address, so
|
|
50
|
+
* a typo in a URL still gets the address treatment rather than an error about
|
|
51
|
+
* invite formats.
|
|
52
|
+
*/
|
|
53
|
+
export function parseServerInput(input, opts) {
|
|
54
|
+
const raw = String(input || "").trim();
|
|
55
|
+
if (!raw)
|
|
56
|
+
return { host: "", code: "" };
|
|
57
|
+
const legacyHost = normalizeHost(opts?.defaultLegacyHost || DEFAULT_LEGACY_HOST);
|
|
58
|
+
// Only something carrying a scheme can be a link. Without this, `gryt.chat`
|
|
59
|
+
// parses as a URL in some engines with "gryt.chat" as the protocol.
|
|
60
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) {
|
|
61
|
+
try {
|
|
62
|
+
const url = new URL(raw);
|
|
63
|
+
const path = url.pathname || "/";
|
|
64
|
+
// gryt://invite?host=…&code=… puts "invite" in the authority rather than
|
|
65
|
+
// the path, because the scheme is not one the URL parser treats as
|
|
66
|
+
// special. Both spellings mean the same thing.
|
|
67
|
+
const isInvite = path.startsWith("/invite") || url.hostname === "invite";
|
|
68
|
+
if (isInvite) {
|
|
69
|
+
const host = normalizeHost(url.searchParams.get("host") || "");
|
|
70
|
+
const code = normalizeCode(url.searchParams.get("code") || "");
|
|
71
|
+
if (host && code)
|
|
72
|
+
return { host, code };
|
|
73
|
+
const parts = path.split("/").filter(Boolean);
|
|
74
|
+
if (parts[0] === "invite" && parts[1]) {
|
|
75
|
+
return { host: legacyHost, code: normalizeCode(parts[1]) };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Not a URL after all. It is still probably an address.
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return { host: normalizeHost(raw), code: "" };
|
|
84
|
+
}
|
package/package.json
CHANGED