@voidbase-cloud/voidbase 0.1.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/.env.example +9 -0
- package/CHANGELOG.md +19 -0
- package/COMPAT.md +43 -0
- package/LICENSE +21 -0
- package/NOTICE +8 -0
- package/README.md +124 -0
- package/bin/voidbase.ts +158 -0
- package/crons/every-minute.ts +13 -0
- package/db/migrations/20260905175935_large_swarm.sql +87 -0
- package/db/migrations/20260905185720_wild_sunspot.sql +16 -0
- package/db/migrations/20260905190723_solid_toro.sql +1 -0
- package/db/migrations/20260905213340_remarkable_union_jack.sql +11 -0
- package/db/migrations/meta/20260905175935_snapshot.json +599 -0
- package/db/migrations/meta/20260905185720_snapshot.json +703 -0
- package/db/migrations/meta/20260905190723_snapshot.json +710 -0
- package/db/migrations/meta/20260905213340_snapshot.json +781 -0
- package/db/migrations/meta/_journal.json +34 -0
- package/db/schema.ts +130 -0
- package/docs/deploy.md +153 -0
- package/docs/differences.md +88 -0
- package/docs/hooks.md +84 -0
- package/docs/migrating.md +29 -0
- package/docs/perf.md +53 -0
- package/docs/platform.md +208 -0
- package/docs/releasing.md +38 -0
- package/env.ts +23 -0
- package/hooks-plugin.ts +237 -0
- package/package.json +134 -0
- package/queues/jobs.ts +13 -0
- package/routes/api/[...path].ts +19 -0
- package/scripts/bench-realtime.ts +46 -0
- package/scripts/bench.ts +39 -0
- package/scripts/ci-suites.sh +27 -0
- package/scripts/dev.sh +29 -0
- package/scripts/export.ts +70 -0
- package/scripts/seed-app-user.sh +14 -0
- package/scripts/seed-d1.ts +17 -0
- package/scripts/seed-reference.sh +29 -0
- package/scripts/starter.sh +22 -0
- package/scripts/sync-app.ts +22 -0
- package/scripts/sync-panel.ts +66 -0
- package/src/cloud/rest.ts +297 -0
- package/src/node/assets.ts +22 -0
- package/src/node/bundle.ts +88 -0
- package/src/node/cloud-init.ts +51 -0
- package/src/node/d1.ts +44 -0
- package/src/node/deploy-cf.ts +179 -0
- package/src/node/index.ts +5 -0
- package/src/node/panel.ts +21 -0
- package/src/node/serve.ts +125 -0
- package/src/node/storage.ts +51 -0
- package/src/platform/node/env.ts +4 -0
- package/src/platform/node/hooks.ts +19 -0
- package/src/platform/node/log.ts +7 -0
- package/src/platform/node/migrations.ts +5 -0
- package/src/platform/node/photon.ts +1 -0
- package/src/platform/node/sockets.ts +22 -0
- package/src/platform/node/sse.ts +23 -0
- package/src/platform/workers/env.ts +3 -0
- package/src/platform/workers/hooks.ts +2 -0
- package/src/platform/workers/log.ts +1 -0
- package/src/platform/workers/migrations.ts +1 -0
- package/src/platform/workers/photon.ts +1 -0
- package/src/platform/workers/sockets.ts +3 -0
- package/src/platform/workers/sse.ts +1 -0
- package/src/server/api.ts +27 -0
- package/src/server/app.ts +582 -0
- package/src/server/auth-extra.ts +113 -0
- package/src/server/auth-flows.ts +186 -0
- package/src/server/auth-response.ts +111 -0
- package/src/server/auth.ts +187 -0
- package/src/server/backups.ts +234 -0
- package/src/server/batch.ts +123 -0
- package/src/server/bootstrap.ts +71 -0
- package/src/server/collections/auth-option-shape.json +71 -0
- package/src/server/collections/ddl.ts +127 -0
- package/src/server/collections/fields.ts +120 -0
- package/src/server/collections/model.ts +185 -0
- package/src/server/collections/oauth2-providers.json +1 -0
- package/src/server/collections/scaffolds.json +210 -0
- package/src/server/collections/service.ts +392 -0
- package/src/server/collections/system.json +605 -0
- package/src/server/collections/system.ts +19 -0
- package/src/server/collections/validate.ts +239 -0
- package/src/server/crc32.ts +13 -0
- package/src/server/crons.ts +100 -0
- package/src/server/crypto.ts +26 -0
- package/src/server/db.ts +37 -0
- package/src/server/errors.ts +53 -0
- package/src/server/files-api.ts +52 -0
- package/src/server/filter/compile.ts +420 -0
- package/src/server/filter/lexer.ts +107 -0
- package/src/server/filter/parser.ts +49 -0
- package/src/server/hardening.ts +136 -0
- package/src/server/hooks/index.ts +147 -0
- package/src/server/hooks/migrations.ts +58 -0
- package/src/server/hooks/node-async-hooks.d.ts +7 -0
- package/src/server/hooks/record.ts +152 -0
- package/src/server/hooks/runtime.ts +344 -0
- package/src/server/hooks/virtual-migrations.d.ts +4 -0
- package/src/server/hooks/virtual.d.ts +7 -0
- package/src/server/hub.ts +91 -0
- package/src/server/ids.ts +22 -0
- package/src/server/jobs.ts +84 -0
- package/src/server/jwt.ts +61 -0
- package/src/server/logs.ts +144 -0
- package/src/server/mail/index.ts +99 -0
- package/src/server/mail/message.ts +43 -0
- package/src/server/mail/smtp.ts +82 -0
- package/src/server/mail/templates.ts +168 -0
- package/src/server/oauth2/index.ts +198 -0
- package/src/server/oauth2/providers.ts +153 -0
- package/src/server/password.ts +17 -0
- package/src/server/realtime/hub-client.ts +50 -0
- package/src/server/realtime/index.ts +239 -0
- package/src/server/records/expand.ts +129 -0
- package/src/server/records/files.ts +69 -0
- package/src/server/records/json.ts +23 -0
- package/src/server/records/picker.ts +80 -0
- package/src/server/records/service.ts +598 -0
- package/src/server/records/thumbs.ts +148 -0
- package/src/server/records/values.ts +295 -0
- package/src/server/settings-api.ts +104 -0
- package/src/server/settings.ts +215 -0
- package/src/server/sql.ts +61 -0
- package/src/server/static.ts +17 -0
- package/src/server/storage/s3.ts +118 -0
- package/src/server/types.ts +25 -0
- package/src/server/webauthn.ts +168 -0
- package/tsconfig.json +36 -0
- package/tsconfig.node.json +27 -0
- package/types/pb_data.d.ts +24438 -0
- package/vite.config.ts +10 -0
- package/void.json +12 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Field type registry mirroring PocketBase core/field_*.go: defaults, normalization, column types.
|
|
2
|
+
import { crc32 } from "../crc32";
|
|
3
|
+
|
|
4
|
+
export const FIELD_TYPES = [
|
|
5
|
+
"text", "editor", "number", "bool", "email", "url", "date", "autodate",
|
|
6
|
+
"select", "file", "relation", "json", "password", "geoPoint",
|
|
7
|
+
] as const;
|
|
8
|
+
export type FieldType = (typeof FIELD_TYPES)[number];
|
|
9
|
+
|
|
10
|
+
export interface Field {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
type: FieldType;
|
|
14
|
+
system: boolean;
|
|
15
|
+
hidden: boolean;
|
|
16
|
+
presentable: boolean;
|
|
17
|
+
required: boolean;
|
|
18
|
+
help: string;
|
|
19
|
+
[option: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Type-specific option defaults, as PocketBase marshals them when unset (Go zero values / nil slices).
|
|
23
|
+
const TYPE_DEFAULTS: Record<FieldType, Record<string, unknown>> = {
|
|
24
|
+
text: { autogeneratePattern: "", max: 0, min: 0, pattern: "", primaryKey: false },
|
|
25
|
+
editor: { convertURLs: false, maxSize: 0 },
|
|
26
|
+
number: { max: null, min: null, onlyInt: false },
|
|
27
|
+
bool: {},
|
|
28
|
+
email: { exceptDomains: null, onlyDomains: null },
|
|
29
|
+
url: { exceptDomains: null, onlyDomains: null },
|
|
30
|
+
date: { max: "", min: "" },
|
|
31
|
+
autodate: { onCreate: false, onUpdate: false },
|
|
32
|
+
select: { maxSelect: 0, values: null },
|
|
33
|
+
file: { maxSelect: 0, maxSize: 0, mimeTypes: null, protected: false, thumbs: null },
|
|
34
|
+
relation: { cascadeDelete: false, collectionId: "", maxSelect: 0, minSelect: 0 },
|
|
35
|
+
json: { maxSize: 0 },
|
|
36
|
+
password: { cost: 0, max: 0, min: 0, pattern: "" },
|
|
37
|
+
geoPoint: {},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const COMMON_DEFAULTS = { help: "", hidden: false, presentable: false, required: false, system: false };
|
|
41
|
+
|
|
42
|
+
export const isFieldType = (t: unknown): t is FieldType => typeof t === "string" && (FIELD_TYPES as readonly string[]).includes(t);
|
|
43
|
+
|
|
44
|
+
const num = (v: unknown, fallback: number | null) => {
|
|
45
|
+
if (v === null || v === undefined || v === "") return fallback;
|
|
46
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
47
|
+
return Number.isFinite(n) ? n : fallback;
|
|
48
|
+
};
|
|
49
|
+
const bool = (v: unknown, fallback = false) => (v === undefined || v === null ? fallback : v === true || v === "true" || v === 1);
|
|
50
|
+
const str = (v: unknown, fallback = "") => (v === undefined || v === null ? fallback : String(v));
|
|
51
|
+
const strList = (v: unknown, fallback: string[] | null) => (Array.isArray(v) ? v.map(String) : fallback);
|
|
52
|
+
|
|
53
|
+
// Coerce raw JSON (from the panel, imports, migrations) into the canonical field object with alphabetical keys.
|
|
54
|
+
export function normalizeField(raw: Record<string, unknown>): Field {
|
|
55
|
+
const type = raw.type as FieldType;
|
|
56
|
+
const out: Record<string, unknown> = {
|
|
57
|
+
id: str(raw.id),
|
|
58
|
+
name: str(raw.name),
|
|
59
|
+
type,
|
|
60
|
+
system: bool(raw.system),
|
|
61
|
+
hidden: bool(raw.hidden),
|
|
62
|
+
presentable: bool(raw.presentable),
|
|
63
|
+
required: bool(raw.required),
|
|
64
|
+
help: str(raw.help),
|
|
65
|
+
};
|
|
66
|
+
if (type === "autodate") {
|
|
67
|
+
// AutodateField has no help/required in PocketBase's JSON
|
|
68
|
+
delete out.help;
|
|
69
|
+
delete out.required;
|
|
70
|
+
}
|
|
71
|
+
const d = TYPE_DEFAULTS[type] ?? {};
|
|
72
|
+
for (const [k, def] of Object.entries(d)) {
|
|
73
|
+
const v = raw[k];
|
|
74
|
+
if (typeof def === "boolean") out[k] = bool(v, def);
|
|
75
|
+
else if (typeof def === "number" || def === null && (k === "max" || k === "min")) out[k] = num(v, def as number | null);
|
|
76
|
+
else if (Array.isArray(def) || def === null) out[k] = k === "collectionId" ? str(v) : strList(v, def as string[] | null);
|
|
77
|
+
else out[k] = str(v, def as string);
|
|
78
|
+
}
|
|
79
|
+
if (type === "relation") out.collectionId = str(raw.collectionId);
|
|
80
|
+
return sortKeys(out) as Field;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function sortKeys<T extends Record<string, unknown>>(o: T): T {
|
|
84
|
+
return Object.fromEntries(Object.entries(o).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))) as T;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// PocketBase: id = type + crc32(name), suffixed 2..999 until unique within the list.
|
|
88
|
+
export function defaultFieldId(type: string, name: string, taken: Set<string>): string {
|
|
89
|
+
const base = type + crc32(name);
|
|
90
|
+
let id = base;
|
|
91
|
+
for (let i = 2; taken.has(id) && i < 1000; i++) id = base + i;
|
|
92
|
+
return id;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function isMultiple(f: Field): boolean {
|
|
96
|
+
if (f.type === "select" || f.type === "file" || f.type === "relation") return Number(f.maxSelect ?? 0) > 1;
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// SQLite column definition for a field (core/field_*.go ColumnType).
|
|
101
|
+
export function columnType(f: Field): string {
|
|
102
|
+
switch (f.type) {
|
|
103
|
+
case "text":
|
|
104
|
+
return f.primaryKey ? "TEXT PRIMARY KEY DEFAULT ('r'||lower(hex(randomblob(7)))) NOT NULL" : "TEXT DEFAULT '' NOT NULL";
|
|
105
|
+
case "editor": case "email": case "url": case "date": case "autodate": case "password":
|
|
106
|
+
return "TEXT DEFAULT '' NOT NULL";
|
|
107
|
+
case "number":
|
|
108
|
+
return "NUMERIC DEFAULT 0 NOT NULL";
|
|
109
|
+
case "bool":
|
|
110
|
+
return "BOOLEAN DEFAULT FALSE NOT NULL";
|
|
111
|
+
case "select": case "file": case "relation":
|
|
112
|
+
return isMultiple(f) ? "JSON DEFAULT '[]' NOT NULL" : "TEXT DEFAULT '' NOT NULL";
|
|
113
|
+
case "json":
|
|
114
|
+
return "JSON DEFAULT NULL";
|
|
115
|
+
case "geoPoint":
|
|
116
|
+
return `JSON DEFAULT '{"lon":0,"lat":0}' NOT NULL`;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const SYSTEM_AUTH_FIELDS = ["password", "tokenKey", "email", "emailVisibility", "verified"] as const;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { all, one } from "../db";
|
|
2
|
+
import type { Row } from "../types";
|
|
3
|
+
import type { Field } from "./fields";
|
|
4
|
+
import authOptionShape from "./auth-option-shape.json";
|
|
5
|
+
|
|
6
|
+
export type CollectionType = "base" | "auth" | "view";
|
|
7
|
+
|
|
8
|
+
export type CollectionField = Field;
|
|
9
|
+
|
|
10
|
+
// Mirrors PocketBase's collection JSON. Type-specific options (auth token configs, viewQuery, ...)
|
|
11
|
+
// live in `options` in the table and are flattened into the JSON the API returns.
|
|
12
|
+
export interface Collection {
|
|
13
|
+
id: string;
|
|
14
|
+
system: boolean;
|
|
15
|
+
type: CollectionType;
|
|
16
|
+
name: string;
|
|
17
|
+
fields: CollectionField[];
|
|
18
|
+
indexes: string[];
|
|
19
|
+
listRule: string | null;
|
|
20
|
+
viewRule: string | null;
|
|
21
|
+
createRule: string | null;
|
|
22
|
+
updateRule: string | null;
|
|
23
|
+
deleteRule: string | null;
|
|
24
|
+
options: Record<string, unknown>;
|
|
25
|
+
created: string;
|
|
26
|
+
updated: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const COMMON_KEYS = new Set([
|
|
30
|
+
"id", "system", "type", "name", "fields", "indexes",
|
|
31
|
+
"listRule", "viewRule", "createRule", "updateRule", "deleteRule", "created", "updated",
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
export function rowToCollection(row: Row): Collection {
|
|
35
|
+
return {
|
|
36
|
+
id: String(row.id),
|
|
37
|
+
system: !!row.system,
|
|
38
|
+
type: String(row.type) as CollectionType,
|
|
39
|
+
name: String(row.name),
|
|
40
|
+
fields: JSON.parse(String(row.fields ?? "[]")),
|
|
41
|
+
indexes: JSON.parse(String(row.indexes ?? "[]")),
|
|
42
|
+
listRule: (row.listRule as string | null) ?? null,
|
|
43
|
+
viewRule: (row.viewRule as string | null) ?? null,
|
|
44
|
+
createRule: (row.createRule as string | null) ?? null,
|
|
45
|
+
updateRule: (row.updateRule as string | null) ?? null,
|
|
46
|
+
deleteRule: (row.deleteRule as string | null) ?? null,
|
|
47
|
+
options: JSON.parse(String(row.options ?? "{}")),
|
|
48
|
+
created: String(row.created ?? ""),
|
|
49
|
+
updated: String(row.updated ?? ""),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Split a PocketBase-shaped collection JSON (as in exports/imports) into row columns + options.
|
|
54
|
+
export function jsonToCollection(json: Record<string, unknown>): Collection {
|
|
55
|
+
const options: Record<string, unknown> = {};
|
|
56
|
+
for (const [k, v] of Object.entries(json)) if (!COMMON_KEYS.has(k)) options[k] = v;
|
|
57
|
+
return {
|
|
58
|
+
id: String(json.id ?? ""),
|
|
59
|
+
system: !!json.system,
|
|
60
|
+
type: (json.type as CollectionType) ?? "base",
|
|
61
|
+
name: json.name == null ? "" : String(json.name),
|
|
62
|
+
fields: (json.fields as CollectionField[]) ?? [],
|
|
63
|
+
indexes: (json.indexes as string[]) ?? [],
|
|
64
|
+
listRule: (json.listRule as string | null) ?? null,
|
|
65
|
+
viewRule: (json.viewRule as string | null) ?? null,
|
|
66
|
+
createRule: (json.createRule as string | null) ?? null,
|
|
67
|
+
updateRule: (json.updateRule as string | null) ?? null,
|
|
68
|
+
deleteRule: (json.deleteRule as string | null) ?? null,
|
|
69
|
+
options,
|
|
70
|
+
created: String(json.created ?? ""),
|
|
71
|
+
updated: String(json.updated ?? ""),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The JSON the API returns for a collection, in PocketBase's marshaling order.
|
|
76
|
+
const AUTH_OPTION_ORDER = [
|
|
77
|
+
"authRule", "manageRule", "authAlert", "oauth2", "passwordAuth", "mfa", "otp", "authToken",
|
|
78
|
+
"passwordResetToken", "emailChangeToken", "verificationToken", "fileToken",
|
|
79
|
+
"verificationTemplate", "resetPasswordTemplate", "confirmEmailChangeTemplate",
|
|
80
|
+
];
|
|
81
|
+
const VIEW_OPTION_ORDER = ["viewQuery"];
|
|
82
|
+
|
|
83
|
+
export function collectionToJSON(c: Collection): Record<string, unknown> {
|
|
84
|
+
const out: Record<string, unknown> = {
|
|
85
|
+
id: c.id,
|
|
86
|
+
listRule: c.listRule,
|
|
87
|
+
viewRule: c.viewRule,
|
|
88
|
+
createRule: c.createRule,
|
|
89
|
+
updateRule: c.updateRule,
|
|
90
|
+
deleteRule: c.deleteRule,
|
|
91
|
+
name: c.name,
|
|
92
|
+
type: c.type,
|
|
93
|
+
fields: c.fields,
|
|
94
|
+
indexes: c.indexes,
|
|
95
|
+
created: c.created,
|
|
96
|
+
updated: c.updated,
|
|
97
|
+
system: c.system,
|
|
98
|
+
};
|
|
99
|
+
const order = c.type === "auth" ? AUTH_OPTION_ORDER : c.type === "view" ? VIEW_OPTION_ORDER : [];
|
|
100
|
+
const shape = c.type === "auth" ? (authOptionShape as Record<string, unknown>) : {};
|
|
101
|
+
for (const k of order) if (k in c.options) out[k] = withoutSecret(reorderLike(c.options[k], shape[k]));
|
|
102
|
+
for (const [k, v] of Object.entries(c.options)) if (!(k in out)) out[k] = withoutSecret(v);
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Emit nested option objects in PocketBase's struct key order (inputs arrive in arbitrary order, e.g. sorted snapshots).
|
|
107
|
+
function reorderLike(value: unknown, spec: unknown): unknown {
|
|
108
|
+
if (!spec || !value || typeof value !== "object") return value;
|
|
109
|
+
if (Array.isArray(value)) {
|
|
110
|
+
const elem = Array.isArray(spec) ? spec[0] : null;
|
|
111
|
+
return elem ? value.map((v) => reorderLike(v, elem)) : value;
|
|
112
|
+
}
|
|
113
|
+
if (Array.isArray(spec)) return value;
|
|
114
|
+
const src = value as Record<string, unknown>;
|
|
115
|
+
const out: Record<string, unknown> = {};
|
|
116
|
+
for (const k of Object.keys(spec as object)) if (k in src) out[k] = reorderLike(src[k], (spec as Record<string, unknown>)[k]);
|
|
117
|
+
for (const [k, v] of Object.entries(src)) if (!(k in out)) out[k] = v;
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// PocketBase never returns token secrets in collection JSON.
|
|
122
|
+
function withoutSecret(v: unknown): unknown {
|
|
123
|
+
if (v && typeof v === "object" && !Array.isArray(v) && "secret" in (v as object)) {
|
|
124
|
+
const { secret: _s, ...rest } = v as Record<string, unknown>;
|
|
125
|
+
return rest;
|
|
126
|
+
}
|
|
127
|
+
return v;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export const isAuth = (c: Collection) => c.type === "auth";
|
|
131
|
+
export const isView = (c: Collection) => c.type === "view";
|
|
132
|
+
export const SUPERUSERS = "_superusers";
|
|
133
|
+
|
|
134
|
+
type OptionsObj = Record<string, unknown>;
|
|
135
|
+
export function option<T = unknown>(c: Collection, path: string, fallback: T): T {
|
|
136
|
+
let cur: unknown = c.options;
|
|
137
|
+
for (const key of path.split(".")) {
|
|
138
|
+
if (cur == null || typeof cur !== "object") return fallback;
|
|
139
|
+
cur = (cur as OptionsObj)[key];
|
|
140
|
+
}
|
|
141
|
+
return (cur === undefined ? fallback : cur) as T;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Per-isolate cache. Writes to _collections must call invalidateCollections().
|
|
145
|
+
let cache: Map<string, Collection> | null = null;
|
|
146
|
+
let cacheAt = 0;
|
|
147
|
+
const CACHE_TTL_MS = 5_000;
|
|
148
|
+
|
|
149
|
+
export function invalidateCollections() {
|
|
150
|
+
cache = null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export async function loadCollections(db: D1Database): Promise<Map<string, Collection>> {
|
|
154
|
+
if (cache && Date.now() - cacheAt < CACHE_TTL_MS) return cache;
|
|
155
|
+
const rows = await all(db, "SELECT * FROM `_collections` ORDER BY rowid ASC");
|
|
156
|
+
const map = new Map<string, Collection>();
|
|
157
|
+
for (const row of rows) {
|
|
158
|
+
const c = rowToCollection(row);
|
|
159
|
+
map.set(c.id, c);
|
|
160
|
+
map.set(c.name, c);
|
|
161
|
+
}
|
|
162
|
+
cache = map;
|
|
163
|
+
cacheAt = Date.now();
|
|
164
|
+
return map;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export async function findCollection(db: D1Database, idOrName: string): Promise<Collection | null> {
|
|
168
|
+
const map = await loadCollections(db);
|
|
169
|
+
const hit = map.get(idOrName);
|
|
170
|
+
if (hit) return hit;
|
|
171
|
+
const row = await one(db, "SELECT * FROM `_collections` WHERE id = ? OR name = ? LIMIT 1", [idOrName, idOrName]);
|
|
172
|
+
return row ? rowToCollection(row) : null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export async function listCollections(db: D1Database): Promise<Collection[]> {
|
|
176
|
+
const map = await loadCollections(db);
|
|
177
|
+
const seen = new Set<string>();
|
|
178
|
+
const out: Collection[] = [];
|
|
179
|
+
for (const c of map.values()) {
|
|
180
|
+
if (seen.has(c.id)) continue;
|
|
181
|
+
seen.add(c.id);
|
|
182
|
+
out.push(c);
|
|
183
|
+
}
|
|
184
|
+
return out;
|
|
185
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"name":"apple","displayName":"Apple","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"315\" preserveAspectRatio=\"xMidYMid\"><path d=\"M213.8 167c.4 47.6 41.7 63.4 42.2 63.6-.3 1.2-6.6 22.6-21.8 44.8-13 19.1-26.7 38.2-48 38.6-21.1.4-28-12.5-52-12.5s-31.6 12.1-51.5 12.9c-20.7.8-36.4-20.7-49.6-39.8-27-39-47.7-110.3-20-158.4a77 77 0 0 1 65.1-39.4c20.3-.4 39.5 13.6 51.9 13.6s35.7-16.9 60.2-14.4c10.2.4 39 4.2 57.5 31.2-1.5 1-34.4 20-34 59.8M174.2 50.2A69 69 0 0 0 190.6 0c-15.8.6-35 10.5-46.3 23.8-10.2 11.8-19.1 30.6-16.7 48.7 17.6 1.3 35.7-9 46.6-22.3\"/></svg>"},{"name":"google","displayName":"Google","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"262\" preserveAspectRatio=\"xMidYMid\"><path fill=\"#4285f4\" d=\"M255.9 133.5c0-10.8-.9-18.6-2.8-26.7H130.6v48.4h71.9a64 64 0 0 1-26.7 42.4l-.2 1.6 38.7 30 2.7.3c24.7-22.8 38.9-56.3 38.9-96\"/><path fill=\"#34a853\" d=\"M130.6 261.1c35.2 0 64.8-11.6 86.4-31.6l-41.2-32a76 76 0 0 1-45.2 13.1 79 79 0 0 1-74.3-54.2l-1.5.1-40.3 31.2-.6 1.5A131 131 0 0 0 130.6 261\"/><path fill=\"#fbbc05\" d=\"M56.3 156.4a80 80 0 0 1-.2-51.7V103L15.3 71.3l-1.4.6a131 131 0 0 0 0 117.3z\"/><path fill=\"#eb4335\" d=\"M130.6 50.5c24.5 0 41 10.6 50.4 19.4L218 34c-22.8-21-52.2-34-87.4-34C79.5 0 35.4 29.3 13.9 72l42.2 32.7a79 79 0 0 1 74.5-54.2\"/></svg>"},{"name":"microsoft","displayName":"Microsoft","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"256\" preserveAspectRatio=\"xMidYMid\"><path fill=\"#f1511b\" d=\"M122 122H0V0h122z\"/><path fill=\"#80cc28\" d=\"M256 122H134V0h122z\"/><path fill=\"#00adef\" d=\"M122 256H0V134h122z\"/><path fill=\"#fbbc09\" d=\"M256 256H134V134h122z\"/></svg>"},{"name":"yandex","displayName":"Yandex","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"44\" height=\"44\" fill=\"none\"><rect width=\"44\" height=\"44\" fill=\"#fc3f1d\" rx=\"22\"/><path fill=\"#fff\" d=\"M25.2 12.3H23c-3.8 0-5.7 2-5.7 4.8 0 3.2 1.3 4.8 4.1 6.7l2.3 1.6-6.4 9.8h-5.1l6-8.9c-3.5-2.5-5.4-4.8-5.4-8.9 0-5 3.5-8.6 10.2-8.6h6.7v26.4h-4.5z\"/></svg>"},{"name":"facebook","displayName":"Facebook","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"256\" preserveAspectRatio=\"xMidYMid\"><path fill=\"#1877f2\" d=\"M256 128a128 128 0 1 0-148 126.4V165H75.5v-37H108V99.8c0-32 19.1-49.8 48.3-49.8 14 0 28.7 2.5 28.7 2.5V84h-16.1c-16 0-20.9 9.9-20.9 20v24h35.5l-5.7 37H148v89.4A128 128 0 0 0 256 128\"/><path fill=\"#fff\" d=\"m177.8 165 5.7-37H148v-24c0-10.1 5-20 20.9-20H185V52.5S170.4 50 156.3 50C127.1 50 108 67.7 108 99.8V128H75.5v37H108v89.4a129 129 0 0 0 40 0V165z\"/></svg>"},{"name":"instagram2","displayName":"Instagram","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 132 132\"><defs><radialGradient xlink:href=\"#a\" id=\"c\" cx=\"158.4\" cy=\"578.1\" r=\"65\" fx=\"158.4\" fy=\"578.1\" gradientTransform=\"matrix(0 -1.98198 1.8439 0 -1031.4 454)\" gradientUnits=\"userSpaceOnUse\"/><radialGradient xlink:href=\"#b\" id=\"d\" cx=\"147.7\" cy=\"473.5\" r=\"65\" fx=\"147.7\" fy=\"473.5\" gradientTransform=\"rotate(78.7 1103.9 776.3)scale(.88596 3.6529)\" gradientUnits=\"userSpaceOnUse\"/><linearGradient id=\"b\"><stop offset=\"0\" stop-color=\"#3771c8\"/><stop offset=\".1\" stop-color=\"#3771c8\"/><stop offset=\"1\" stop-color=\"#60f\" stop-opacity=\"0\"/></linearGradient><linearGradient id=\"a\"><stop offset=\"0\" stop-color=\"#fd5\"/><stop offset=\".1\" stop-color=\"#fd5\"/><stop offset=\".5\" stop-color=\"#ff543e\"/><stop offset=\"1\" stop-color=\"#c837ab\"/></linearGradient></defs><path fill=\"url(#c)\" d=\"M65 0C38 0 30 0 28.4.2c-5.6.4-9 1.3-12.8 3.2a28 28 0 0 0-15 21.3c-.4 3-.6 3.6-.6 19.1V65c0 27 0 35 .2 36.6.4 5.4 1.3 8.8 3 12.5 3.5 7.2 10 12.5 17.8 14.5q4 1 9.5 1.3a2913 2913 0 0 0 68.8 0c4.4-.2 7-.6 9.8-1.3 7.8-2 14.2-7.3 17.7-14.5 1.8-3.7 2.7-7.2 3.1-12.3a2759 2759 0 0 0 0-73.6c-.4-5.2-1.3-8.8-3.1-12.5q-2.1-4.3-5.6-7.6A28 28 0 0 0 105.4.6c-3-.4-3.7-.6-19.2-.6z\" transform=\"translate(1 1)\"/><path fill=\"url(#d)\" d=\"M65 0C38 0 30 0 28.4.2c-5.6.4-9 1.3-12.8 3.2a28 28 0 0 0-15 21.3c-.4 3-.6 3.6-.6 19.1V65c0 27 0 35 .2 36.6.4 5.4 1.3 8.8 3 12.5 3.5 7.2 10 12.5 17.8 14.5q4 1 9.5 1.3a2913 2913 0 0 0 68.8 0c4.4-.2 7-.6 9.8-1.3 7.8-2 14.2-7.3 17.7-14.5 1.8-3.7 2.7-7.2 3.1-12.3a2759 2759 0 0 0 0-73.6c-.4-5.2-1.3-8.8-3.1-12.5q-2.1-4.3-5.6-7.6A28 28 0 0 0 105.4.6c-3-.4-3.7-.6-19.2-.6z\" transform=\"translate(1 1)\"/><path fill=\"#fff\" d=\"M66 18c-13 0-14.7 0-19.8.3s-8.6 1-11.6 2.2a24 24 0 0 0-8.5 5.6 24 24 0 0 0-5.6 8.5 35 35 0 0 0-2.2 11.6C18 51.3 18 53 18 66s0 14.7.3 19.8 1 8.6 2.2 11.6q1.7 4.7 5.6 8.5 3.8 4 8.5 5.6c3 1.2 6.5 2 11.6 2.2s6.8.3 19.8.3 14.7 0 19.8-.3 8.6-1 11.6-2.2q4.7-1.7 8.5-5.6t5.6-8.5c1.2-3 2-6.5 2.2-11.6s.3-6.8.3-19.8 0-14.7-.3-19.8-1-8.6-2.2-11.6a24 24 0 0 0-5.6-8.5 24 24 0 0 0-8.5-5.6c-3-1.2-6.5-2-11.6-2.2S79 18 66 18m-4.3 8.7H66c12.8 0 14.3 0 19.4.2 4.7.2 7.2 1 9 1.7 2.2.8 3.7 1.9 5.4 3.6q2.4 2.2 3.6 5.5c.7 1.7 1.5 4.2 1.7 8.9.2 5 .3 6.6.3 19.4s-.1 14.3-.3 19.4c-.2 4.7-1 7.2-1.7 8.9q-1.1 3.1-3.6 5.5a15 15 0 0 1-5.5 3.6c-1.7.7-4.2 1.4-8.9 1.6-5 .3-6.6.3-19.4.3a334 334 0 0 1-19.4-.3 28 28 0 0 1-8.9-1.6q-3.1-1.3-5.5-3.6a15 15 0 0 1-3.6-5.5 25 25 0 0 1-1.7-9c-.2-5-.2-6.5-.2-19.3s0-14.4.2-19.4a26 26 0 0 1 1.7-9q1.2-3.1 3.6-5.4 2.4-2.5 5.5-3.6a25 25 0 0 1 9-1.7c4.3-.2 6-.3 15-.3zm30 8a5.8 5.8 0 1 0 0 11.4 5.8 5.8 0 0 0 0-11.5M66 41.2a24.7 24.7 0 1 0 0 49.4 24.7 24.7 0 0 0 0-49.3m0 8.7a16 16 0 1 1 0 32 16 16 0 0 1 0-32\"/></svg>"},{"name":"github","displayName":"GitHub","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"250\" preserveAspectRatio=\"xMidYMid\"><path fill=\"#161614\" d=\"M128 0a128 128 0 0 0-40.5 249.5c6.4 1.1 8.8-2.8 8.8-6.2l-.2-23.8C60.5 227.2 53 204.4 53 204.4c-5.8-14.8-14.2-18.8-14.2-18.8-11.6-7.9.8-7.7.8-7.7 12.9.9 19.7 13.1 19.7 13.1 11.4 19.6 30 14 37.2 10.7 1.2-8.3 4.5-14 8.1-17.1-28.4-3.3-58.3-14.2-58.3-63.3 0-14 5-25.4 13.2-34.3a46 46 0 0 1 1.3-34S71.5 49.7 96 66.3a123 123 0 0 1 64 0c24.5-16.6 35.2-13.1 35.2-13.1a46 46 0 0 1 1.3 33.9c8.2 9 13.2 20.3 13.2 34.3 0 49.2-30 60-58.5 63.2 4.6 4 8.7 11.7 8.7 23.7l-.2 35.1c0 3.4 2.4 7.4 8.8 6.1A128 128 0 0 0 128 0M48 182.3q-.6 1.1-2.3.4c-.9-.4-1.4-1.3-1.1-1.9q.6-1 2.2-.4 1.6.8 1.1 2m6.2 5.7c-.6.5-1.8.3-2.6-.6q-1.2-1.7-.4-2.7 1.2-.8 2.7.6 1.3 1.5.3 2.7m4.4 7.1c-.8.6-2.1 0-2.9-1-.8-1.2-.8-2.6 0-3.1q1.4-.7 2.9 1c.8 1.2.8 2.6 0 3.1m7.3 8.4c-.7.7-2.2.5-3.3-.5s-1.5-2.5-.8-3.3c.8-.8 2.3-.5 3.4.5 1 1 1.4 2.5.7 3.3m9.4 2.8c-.3 1-1.7 1.4-3.2 1-1.4-.4-2.4-1.6-2.1-2.6s1.7-1.5 3.2-1 2.4 1.6 2.1 2.6m10.7 1.2q-.1 1.7-2.7 2-2.5-.2-2.8-2c0-1 1.2-1.9 2.8-1.9s2.7.8 2.7 1.9m10.6-.4c.2 1-.9 2-2.4 2.3s-2.8-.3-3-1.3c-.2-1.1.9-2.2 2.3-2.4 1.6-.3 3 .3 3.1 1.4\"/></svg>"},{"name":"gitlab","displayName":"GitLab","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"247\" fill=\"none\"><path fill=\"#e24329\" d=\"m251.7 97.7-.3-.9-34.7-90.6a9 9 0 0 0-9-5.7q-3 .2-5.2 2a9 9 0 0 0-3.1 4.7L176 78.9H81L57.7 7.2a9.1 9.1 0 0 0-17.2-1L5.6 96.8l-.4.9a64.4 64.4 0 0 0 21.4 74.5h.1l.3.3L80 212l26 19.8 16 12a11 11 0 0 0 13 0l15.9-12 26.2-19.8 53.1-39.9h.2a64.5 64.5 0 0 0 21.3-74.5\"/><path fill=\"#fc6d26\" d=\"m251.7 97.7-.3-.9c-17 3.5-32.9 10.6-46.7 21l-76.2 57.6 48.5 36.7 53.2-39.8.2-.1a64.5 64.5 0 0 0 21.3-74.5\"/><path fill=\"#fca326\" d=\"m80 212.1 26 19.8 16 12a11 11 0 0 0 13 0l15.9-12 26.2-19.8s-22.7-17-48.6-36.7z\"/><path fill=\"#fc6d26\" d=\"M52.2 117.8a117 117 0 0 0-46.6-21l-.4.9a64.4 64.4 0 0 0 21.4 74.5h.1l.3.3L80 212l48.5-36.7z\"/></svg>"},{"name":"bitbucket","displayName":"Bitbucket","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"2500\" height=\"2256\" preserveAspectRatio=\"xMidYMid\" viewBox=\"-1 -0.6 257.9 230.8\"><linearGradient id=\"a\" x1=\"108.6%\" x2=\"46.9%\" y1=\"13.8%\" y2=\"78.8%\"><stop offset=\".2\" stop-color=\"#0052cc\"/><stop offset=\"1\" stop-color=\"#2684ff\"/></linearGradient><g fill=\"none\"><path d=\"M101 153h54l13-76H87z\"/><path fill=\"#2684ff\" d=\"M8 0a8 8 0 0 0-8 10l35 211a11 11 0 0 0 11 9h167a8 8 0 0 0 8-7l35-213a8 8 0 0 0-8-10zm147 153h-53L87 77h81z\"/><path fill=\"url(#a)\" d=\"M245 77h-77l-13 76h-53l-63 74 7 3h167a8 8 0 0 0 8-7z\"/></g></svg>"},{"name":"gitee","displayName":"Gitee","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"120 13 72 72\"><g fill=\"none\" fill-rule=\"evenodd\"><path d=\"M0 0h312v100H0z\"/><path fill=\"#c71d23\" d=\"M156 85a36 36 0 1 1 0-72 36 36 0 0 1 0 72m18.2-40h-20.4q-1.7.1-1.8 1.8v4.4q.2 1.6 1.8 1.8h12.4q1.7.1 1.8 1.8v.9c0 3-2.4 5.3-5.3 5.3h-17q-1.6-.1-1.7-1.8V42.3c0-3 2.4-5.3 5.3-5.3h25q1.5-.1 1.7-1.8v-4.4a2 2 0 0 0-1.8-1.8h-24.9C142 29 136 35 136 42.3v25q.2 1.5 1.8 1.7H164a12 12 0 0 0 12-12V46.8q-.2-1.6-1.8-1.8\"/></g></svg>"},{"name":"gitea","displayName":"Gitea/Forgejo","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" xml:space=\"preserve\" viewBox=\"0 0 640 640\"><path d=\"m396 484-127-61c-12-6-18-21-12-34l61-127c6-12 21-17 34-11l27 13V154h17v118s57 24 83 40q7 3 13 14 3 10-1 19l-61 127c-6 13-22 18-34 12\" style=\"fill:#fff\"/><path d=\"M623 150c-4-4-10-4-10-4l-178 8-39 1v117l-17-8V155l-89-3-157-8q-15-2-39 1c-9 2-34 8-54 27C-5 212 7 276 8 286c2 12 7 44 32 72 46 56 144 55 144 55s12 29 31 56c25 33 50 59 75 62h189s12 0 29-11c14-8 26-23 26-23s13-14 31-45l14-28s55-118 55-232c-1-34-9-40-11-42M126 354c-26-9-37-19-37-19s-19-13-29-40c-16-44-1-71-1-71s8-22 38-30c14-4 31-3 31-3s7 59 16 94c7 30 25 78 25 78s-26-3-43-9m300 108s-6 14-20 15l-10-1-5-2-113-55s-11-6-13-16c-2-8 3-18 3-18l54-112s5-10 12-13l5-1c8-3 18 2 18 2l110 54s13 6 16 16q1 12-2 17c-6 16-55 114-55 114\" style=\"fill:#609926\"/><path d=\"M327 380q-14 1-17 14-2 13 9 20c7 4 17 2 22-5q8-13-1-24l24-49h6l7-4 29 16 5 5c2 6-2 15-2 15-2 7-18 40-18 40q-13 1-18 13-4 14 9 21a18 18 0 0 0 21-28l6-11 13-30c1-2 6-11 3-22-2-11-13-16-13-16-12-8-29-16-29-16l-1-7-4-6 14-29-12-6-14 29q-11 0-16 10t1 20z\" style=\"fill:#609926\"/></svg>"},{"name":"discord","displayName":"Discord","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"199\" preserveAspectRatio=\"xMidYMid\"><path fill=\"#5865f2\" d=\"M216.9 16.6A209 209 0 0 0 164 0c-2.2 4.1-4.9 9.6-6.7 14a194 194 0 0 0-58.6 0C97 9.6 94.2 4.1 92 0a208 208 0 0 0-53 16.6A222 222 0 0 0 1 165a211 211 0 0 0 65 33 161 161 0 0 0 13.8-22.8q-11.5-4.4-21.8-10.6l5.3-4.3a149 149 0 0 0 129.6 0q2.6 2.3 5.3 4.3a136 136 0 0 1-21.9 10.6q6 12 13.9 22.9a211 211 0 0 0 64.8-33.2c5.3-56.3-9-105.1-38-148.4M85.5 135.1c-12.7 0-23-11.8-23-26.2s10.1-26.2 23-26.2 23.2 11.8 23 26.2c0 14.4-10.2 26.2-23 26.2m85 0c-12.6 0-23-11.8-23-26.2s10.2-26.2 23-26.2 23.3 11.8 23 26.2c0 14.4-10.1 26.2-23 26.2\"/></svg>"},{"name":"twitter","displayName":"X/Twitter","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"300\" height=\"300.3\"><path d=\"M179 127 290 0h-26l-97 110L89 0H0l117 167L0 300h26l103-116 82 116h89M36 20h41l187 262h-41\"/></svg>"},{"name":"kakao","displayName":"Kakao","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"2500\" height=\"2500\" viewBox=\"0 0 256 256\"><path fill=\"#ffe812\" d=\"M256 236q-2 18-20 20H20q-18-2-20-20V20Q2 2 20 0h216q18 2 20 20z\"/><path d=\"M128 36C71 36 24 73 24 118c0 29 19 55 49 69l-11 38 1 3h3l44-29 18 1c57 0 104-37 104-82s-47-82-104-82\"/><path fill=\"#ffe812\" d=\"M71 147q-6-1-6-6v-36H55a6 6 0 0 1 0-11h31a6 6 0 0 1 0 11h-9v36q-1 5-6 6m52 0q-3 0-5-3l-3-8H97l-3 8q-2 3-5 3l-4-1q-3-1-1-9l14-38q2-4 8-5 6 1 8 5l14 38q2 8-1 9zm-11-22-6-17-6 17zm26 21q-5-1-6-6v-40q1-6 6-6 7 0 7 6v35h12q5 0 6 5 0 7-6 6zm33 1q-5-1-6-6v-41a6 6 0 0 1 12 0v12l17-16 3-2 5 2 1 4-1 4-14 13 15 20 1 4-2 4-4 1-5-2-14-19-2 2v14a6 6 0 0 1-6 6\"/></svg>"},{"name":"vk","displayName":"\u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"48\" height=\"48\" fill=\"none\"><path fill=\"#07f\" d=\"M0 23C0 12.2 0 6.7 3.4 3.4 6.7 0 12.2 0 23 0h2c10.8 0 16.3 0 19.6 3.4C48 6.7 48 12.2 48 23v2c0 10.8 0 16.3-3.4 19.6C41.3 48 35.8 48 25 48h-2c-10.8 0-16.3 0-19.6-3.4C0 41.3 0 35.8 0 25z\"/><path fill=\"#fff\" d=\"M25.5 34.6c-10.9 0-17.1-7.5-17.4-20h5.5c.2 9.2 4.2 13 7.4 13.8V14.6h5.2v7.9c3.1-.3 6.4-4 7.6-7.9h5.1a15 15 0 0 1-7 10c2.6 1.2 6.7 4.3 8.2 10h-5.7a10 10 0 0 0-8.2-7.2v7.2z\"/></svg>"},{"name":"linear","displayName":"Linear","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"200\" height=\"200\" fill=\"#222326\" viewBox=\"0 0 100 100\"><path d=\"M1.2 61.5c-.2-1 1-1.5 1.6-.8l36.5 36.5c.7.7.1 1.8-.8 1.6A50 50 0 0 1 1.2 61.5M0 47q0 .4.3.7l52 52.1q.4.3.8.3a50 50 0 0 0 7-1 1 1 0 0 0 .5-1.6l-58-58a1 1 0 0 0-1.7.5 50 50 0 0 0-.9 7m4.2-17.2q-.2.6.2 1.1l64.8 64.8q.5.5 1 .2l5.3-2.7q.8-.6.2-1.5L8.4 24.3a1 1 0 0 0-1.5.2Q5.4 27 4.2 29.7m8.5-11.6a1 1 0 0 1 0-1.4A50 50 0 0 1 100 50a50 50 0 0 1-16.7 37.4 1 1 0 0 1-1.4 0z\"/></svg>"},{"name":"notion","displayName":"Notion","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" height=\"100\" fill=\"none\"><path fill=\"#000\" d=\"M61 0 6 4q-6 2-6 7v61l3 8 13 17q2 4 8 3l65-4q7-1 7-7V21q0-3-4-5L74 3q-4-4-13-3M26 20q-7 1-9-2l-8-6q-1-2 1-2l54-4q5 0 8 2l9 7 1 1zm-6 68V30q0-3 3-4l63-3q3 0 3 3v58q1 5-4 5l-60 3q-5 1-5-4m59-55q1 4-1 4l-3 1v43l-7 2q-4 0-6-4L43 49v29l6 1s0 4-5 4H30l2-3 3-1V41h-5q0-4 4-5l14-1 20 31V39l-5-1q0-3 3-4z\"/></svg>"},{"name":"monday","displayName":"monday.com","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" xml:space=\"preserve\" viewBox=\"0 0 127 127\"><path fill=\"#fb275d\" d=\"M24.8 87.2c-3.7 0-7.1-1.9-8.9-5.1a9 9 0 0 1 .3-9.9L34.5 44c1.9-3.1 5.4-4.9 9.1-4.8s7.1 2.1 8.8 5.3 1.5 7-.5 9.9L33.4 82.6a10 10 0 0 1-8.6 4.6\"/><path fill=\"#fc0\" d=\"M56.1 87.2c-3.7 0-7.1-1.9-8.9-5a9 9 0 0 1 .3-9.9l18.4-28.1c1.9-3.1 5.3-5 9.1-4.9s7.1 2.1 8.8 5.3 1.5 7-.7 10l-18.4 28a11 11 0 0 1-8.6 4.6\"/><path fill=\"#00ca72\" d=\"M86.7 87.2c5.6 0 10.2-4.6 10.2-10.2s-4.6-10.2-10.2-10.2S76.5 71.4 76.5 77c0 5.7 4.5 10.2 10.2 10.2\"/></svg>"},{"name":"lark","displayName":"Lark","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"256\" fill=\"none\"><path fill=\"#00d6b9\" d=\"M137 126v-1l2-1v-1l3-2 3-3 3-3 2-3 3-2 2-3 4-3 2-2 4-3 9-7 5-3 9-3 2-1a135 135 0 0 0-26-51 12 12 0 0 0-9-4H56l-2 1 1 2a288 288 0 0 1 82 93\"/><path fill=\"#3370ff\" d=\"M98 212c51 0 95-28 118-69l3-5-6 9-4 4-6 5-2 2-4 3-11 4-6 2h-15l-4-1h-3l-2-1-5-1-3-1-4-1-3-1-3-1-1-1-3-1h-2l-3-2h-2l-2-1-3-1-2-1-2-1-2-1h-2l-1-1-2-1h-1l-1-1-2-1-2-1-2-1-2-1a285 285 0 0 1-81-60l-3 1v94a12 12 0 0 0 5 11 135 135 0 0 0 76 22\"/><path fill=\"#133c9a\" d=\"M248 90a78 78 0 0 0-58-5l-2 1-14 6-6 4-7 6-2 2-4 3-2 3-3 2-2 3-3 3-3 3-3 2v1l-2 1-1 1-1 1a137 137 0 0 1-28 20l2 1 1 1h2l1 1 1 1h2l2 1 2 1 2 1 3 1 2 1h2l3 2h2l3 1 2 1 2 1 3 1 4 1 8 2 2 1 7 1h15l6-2 7-2 6-4 2-1 2-2 3-1 7-8 6-9 1-2 12-24a77 77 0 0 1 16-22\"/></svg>"},{"name":"box","displayName":"Box","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 40 21.6\"><path fill=\"#0061d5\" d=\"M39.7 19.2q.7 1.2-.2 2.1-1.2.7-2.2-.2l-3.5-4.5-3.4 4.4c-.5.7-1.5.7-2.2.2q-1-.9-.3-2.1l4-5.2-4-5.2c-.5-.7-.3-1.7.3-2.2s1.7-.3 2.2.3l3.4 4.5L37.3 7q.9-1 2.2-.3 1 1 .2 2.2L35.8 14zm-18.2-.6c-2.6 0-4.7-2-4.7-4.6s2.1-4.6 4.7-4.6 4.7 2.1 4.7 4.6a4.7 4.7 0 0 1-4.7 4.6m-13.8 0c-2.6 0-4.7-2-4.7-4.6s2.1-4.6 4.7-4.6 4.7 2.1 4.7 4.6c0 2.6-2.1 4.6-4.7 4.6M21.5 6.4a8 8 0 0 0-6.8 4 8 8 0 0 0-6.9-4q-2.7 0-4.7 1.5V1.5Q3 .2 1.6 0 .1.1 0 1.5v12.6a7.7 7.7 0 0 0 7.7 7.5c3 0 5.6-1.7 6.9-4.1a8 8 0 0 0 6.8 4.1c4.3 0 7.8-3.4 7.8-7.7a7.5 7.5 0 0 0-7.7-7.5\"/></svg>"},{"name":"spotify","displayName":"Spotify","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"256\" preserveAspectRatio=\"xMidYMid\"><path fill=\"#1ed760\" d=\"M128 0C57.3 0 0 57.3 0 128s57.3 128 128 128 128-57.3 128-128C256 57.31 198.7 0 128 0m58.7 184.61a7.97 7.97 0 0 1-10.98 2.65c-30.05-18.36-67.88-22.52-112.44-12.34a7.98 7.98 0 0 1-3.55-15.56c48.76-11.14 90.58-6.34 124.32 14.28a8 8 0 0 1 2.65 10.97m15.67-34.85a10 10 0 0 1-13.73 3.29c-34.4-21.15-86.85-27.27-127.55-14.92a10 10 0 0 1-12.45-6.65 10 10 0 0 1 6.65-12.45c46.49-14.1 104.28-7.27 143.79 17.01a10 10 0 0 1 3.29 13.72m1.34-36.3c-41.25-24.5-109.32-26.75-148.7-14.8a11.97 11.97 0 1 1-6.95-22.9c45.21-13.73 120.37-11.08 167.87 17.12a11.96 11.96 0 1 1-12.21 20.6z\"/></svg>"},{"name":"trakt","displayName":"Trakt","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\"><defs><radialGradient id=\"a\" cx=\"48.5\" cy=\"-.9\" r=\"64.8\" fx=\"48.5\" fy=\"-.9\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0\" stop-color=\"#9f42c6\"/><stop offset=\".3\" stop-color=\"#a041c3\"/><stop offset=\".4\" stop-color=\"#a43ebb\"/><stop offset=\".5\" stop-color=\"#aa39ad\"/><stop offset=\".6\" stop-color=\"#b4339a\"/><stop offset=\".7\" stop-color=\"#c02b81\"/><stop offset=\".8\" stop-color=\"#cf2061\"/><stop offset=\".9\" stop-color=\"#e1143c\"/><stop offset=\"1\" stop-color=\"#f50613\"/><stop offset=\"1\" stop-color=\"red\"/></radialGradient></defs><path d=\"M48 11.3v25.4C48 43 43 48 36.7 48H11.3C5 48 0 43 0 36.7V11.3C0 5 5 0 11.3 0h25.4A11 11 0 0 1 48 11.3\" style=\"fill:url(#a)\"/><path d=\"m13.6 18 8 7.9 1.4-1.5-8-7.9zM28 32.4l1.5-1.5-2.2-2.2L47.6 8.4q-.2-1-.8-2.1L24.5 28.7zM13 18.7 11.4 20l14.4 14.4 1.4-1.4-4.3-4.3L46.4 5.4 45 3.7 21.5 27.3zm34.9-9.1L28.7 28.8l1.5 1.4L48 12.4v-1.1zM25.2 22.3l-8-8-1.4 1.5 7.9 8zM41.3 35c0 3.4-2.8 6.2-6.2 6.2H13A6 6 0 0 1 6.8 35V13c0-3.4 2.8-6.2 6.2-6.2h20.8V4.6H12.9a8.3 8.3 0 0 0-8.3 8.3V35c0 4.6 3.7 8.3 8.3 8.3H35c4.6 0 8.3-3.7 8.3-8.3v-3.5h-2z\" style=\"fill:#fff\"/></svg>"},{"name":"twitch","displayName":"Twitch","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"268\" preserveAspectRatio=\"xMidYMid\"><path fill=\"#5a3e85\" d=\"M17 0 0 47v186h64v35h35l35-35h52l70-70V0zm24 23h192v128l-41 41h-64l-35 35v-35H41zm64 117h23V70h-23zm64 0h23V70h-23z\"/></svg>"},{"name":"patreon","displayName":"Patreon","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" xml:space=\"preserve\" viewBox=\"0 0 1080 1080\"><path d=\"M1033 324c0-137-108-250-234-291a746 746 0 0 0-512 27C106 145 49 333 47 519c-2 154 14 558 242 561 169 2 194-216 273-321 56-75 127-96 216-118a320 320 0 0 0 255-317\"/></svg>"},{"name":"strava","displayName":"Strava","logo":"<svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" width=\"2500\" height=\"2500\"><path d=\"M0 0h16v16H0z\" fill=\"#fc4c02\"/><g fill=\"#fff\" fill-rule=\"evenodd\"><path d=\"M6.9 8.8l2.5 4.5 2.4-4.5h-1.5l-.9 1.7-1-1.7z\" opacity=\".6\"/><path d=\"M7.2 2.5l3.1 6.3H4zm0 3.8l1.2 2.5H5.9z\"/></g></svg>"},{"name":"wakatime","displayName":"WakaTime","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"340\" height=\"340\" fill=\"none\"><path stroke=\"#000\" stroke-width=\"40\" d=\"M170 20a150 150 0 1 0 0 300 150 150 0 0 0 0-300Z\" clip-rule=\"evenodd\"/><path fill=\"#000\" stroke=\"#000\" stroke-width=\"10\" d=\"M190.2 213.5a8 8 0 0 1-7.6 3l-2-.8a9 9 0 0 1-2.3-2l-.9-1.3-8.8-14.2-8.8 14.2a8 8 0 0 1-6.8 4.3 8 8 0 0 1-6.8-4.4l-38.6-56.2a9 9 0 0 1-2-5.8c0-4.8 3.4-8.6 7.7-8.6 2.8 0 5.3 1.6 6.6 4l32.7 48.2 9.1-15a8 8 0 0 1 6.9-4.4q4.2.2 6.4 3.8l9.5 15.5 51.2-73.2q2.3-3.8 6.5-4c4.3 0 7.8 4 7.8 8.7q0 3.2-1.8 5.4z\"/></svg>"},{"name":"livechat","displayName":"LiveChat","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" xml:space=\"preserve\" viewBox=\"0 0 80 80\"><path d=\"M79.5 49.7a19 19 0 0 1-19 17.3H50L30 80V67l20-13h10.5a6 6 0 0 0 6.1-5.3q1-15-.2-30a5.6 5.6 0 0 0-5.2-5.1Q50.9 13.1 40 13c-10.9-.1-14.4.2-21.2.7-2.8.2-5 2.3-5.2 5.1q-1 15-.2 30c.3 3.1 3 5.3 6.1 5.2H30v13H19.5c-9.9.1-18.2-7.4-19-17.3q-1-16 .2-32C1.5 8.5 8.8 1.3 18 .7a313 313 0 0 1 44.1.1c9.2.6 16.5 7.8 17.3 17q1.1 16 .1 31.9\" style=\"fill:#ff5100\"/></svg>"},{"name":"mailcow","displayName":"mailcow","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" xml:space=\"preserve\" width=\"394.8\" height=\"376.9\"><path d=\"M56 213.3c0-20.3-.8-17.3-3.7-39.3 2.2-22.5-7.6-38.9-7.7-58.4 0-4.7-5.8-6.7-4.7-11A99 99 0 0 0 56 214.7z\" style=\"fill:#3d5263\" transform=\"translate(10 10)\"/><path d=\"m254.8 180.4-.6.5a121 121 0 0 1-80 84l11 9.2 53.2 44.8 31.6 26.5q1.3-3 1.3-6.4V167.1zM23 185.5l-6.5-5.2-16.5-13v171.6q0 3.5 1.2 6.5l58.4-48.7 27-22.4L99 263.9a121 121 0 0 1-76-78.4\" style=\"fill:#f9e82d\" transform=\"translate(10 10)\"/><path d=\"M238.4 318.9 185.1 274l-11-9.2a120 120 0 0 1-75.1-1l-12.4 10.4-27 22.5-58.4 48.6A18 18 0 0 0 18 357h235.4a18 18 0 0 0 16.7-11.5z\" style=\"fill:#edd514;fill-opacity:.89499996\" transform=\"translate(10 10)\"/><path d=\"M238.4 318.9c-41.4 4-115 5.5-178.8-22.1-21.5-9.4-42-22.1-59.6-39.2V339q0 3.5 1.2 6.5A18 18 0 0 0 18 357h235.4a18 18 0 0 0 18-18v-24.5s-12.6 2.5-32.9 4.5\" style=\"opacity:.1;fill:#3d5263\" transform=\"translate(10 10)\"/><path d=\"M86.6 274.3a120 120 0 0 0 98.5-.2 120 120 0 0 0 69.7-93.7l-.6.5a120.5 120.5 0 0 1-155.2 83 121 121 0 0 1-76-78.4l-6.5-5.2c5.5 42 32.7 77.3 70 94\" style=\"opacity:.1;fill:#3d5263\" transform=\"translate(10 10)\"/><path d=\"M54.3 63.9q-2.7 2.6-5.2 5.4l-.2.1-.7.8.2-.2a120.2 120.2 0 0 1 174.8 165 120 120 0 0 0 35-84.8A120 120 0 0 0 187 40.4a119 119 0 0 0-100.7 1.2 120 120 0 0 0-32 22.3\" style=\"fill:#fff\" transform=\"translate(10 10)\"/><path d=\"M95.8 118.5a4.6 4.6 0 1 0 0-9.2 4.6 4.6 0 0 0 0 9.2m91.1 0a4.6 4.6 0 1 0 0-9.2 4.6 4.6 0 0 0 0 9.2\" style=\"fill:#fff\" transform=\"translate(10 10)\"/><path d=\"M223.7 234.4A120.2 120.2 0 0 0 48.4 70 121 121 0 0 0 23 185.5 120.5 120.5 0 0 0 174.2 265a120 120 0 0 0 47.7-28.6zm-5.8-58.4q-3.2 11-8.7 20.5A94.8 94.8 0 0 1 56 214.8a99 99 0 0 1-16-110.3 96 96 0 0 1 97.8-54 97.3 97.3 0 0 1 84.3 97.2q0 14.9-4 28.3M49 69.3\" style=\"fill:#f1f2f2\" transform=\"translate(10 10)\"/><path d=\"M257.6 161.9a120 120 0 0 1-3.4 19l.6-.5 16.5-13.2zM0 167.2l16.5 13.1 6.5 5.2q-3.5-11.6-4.7-23.9l-2.9.9zm87.5 25.1a11.3 11.3 0 1 0 0 22.5 11.3 11.3 0 0 0 0-22.5m93.8 0a11.3 11.3 0 1 0 0 22.5 11.3 11.3 0 0 0 0-22.5m1.7-90c-7 0-15.4 7.7-15.4 14.7s8 17.2 15 17.2 15.8-9.5 15.8-16.5-8.4-15.4-15.4-15.4m3.9 16.2a4.6 4.6 0 1 1 0-9.2 4.6 4.6 0 0 1 0 9.2m-97.2-15.9c-7 0-14.4 8.1-14.4 15s8.9 16.2 15.8 16.2 15.8-9.1 15.8-16.1-10.2-15.1-17.2-15.1m6.1 16a4.6 4.6 0 1 1 0-9.3 4.6 4.6 0 0 1 0 9.2\" style=\"fill:#5a3620\" transform=\"translate(10 10)\"/><path d=\"M336.3 256.4c3.6-9.1 7.7-11 9.3-11.3-40.7 3.7-36.6 27.7-34 36l1 2.7s2 4.8 7.6 8.7c4.1 3 10.3 5.5 19 5.2 27 .4 35.6-50.2 35.6-50.2-6.6 11.7-26.4 9.9-38.5 9M49 69.4l5.3-5.4c-9-7-24.4-15.9-41.8-11.7A54 54 0 0 0 36 86.5q5.5-8.8 12.4-16.5l-.2.2zm209.8-17.2a49 49 0 0 0-39.2 9.8q10.8 9.9 19 22.3a54 54 0 0 0 20.2-32M134.3 160.2c-43.3 0-78.4 23-78.4 51.3v1.7l.2 1.6a94.8 94.8 0 0 0 153.1-18.3c-9.8-21-39.6-36.3-75-36.3M87.5 215a11.3 11.3 0 1 1 0-22.6 11.3 11.3 0 0 1 0 22.5m93.8 0a11.3 11.3 0 1 1 0-22.6 11.3 11.3 0 0 1 0 22.5M86.3 0c-18.2 16.4-.2 41.4 0 41.6Q102.6 34 121 31.1C97.6 27.7 86.3 0 86.3 0m99.9 0S175.3 26.5 153 30.9q18 2.3 34 9.5c3.4-5.3 15-26.1-.8-40.4\" style=\"fill:#fef3df\" transform=\"translate(10 10)\"/><path d=\"M218 176a163 163 0 0 0 6.5-35.7c0-50-39.3-83.9-86.8-89.8-2.1 28 3.7 87 80.2 125.5m-47.6-58.3a12.6 12.6 0 1 1 25.2 0 12.6 12.6 0 0 1-25.2 0\" style=\"fill:#87654a\" transform=\"translate(10 10)\"/><path d=\"m312.7 283.8-1-2.8a54 54 0 0 1-27.1 12.5q-6 1-13.3.5v28a206 206 0 0 0 26.2-12.5h.1c8.2-4.7 16.4-10.5 22.6-17-5.5-4-7.5-8.8-7.5-8.8M12.5 52.2C30 48 45.4 57 54.3 64q8.4-8.2 18.3-14.6C48.3 18.5 2.2 37.2 2.2 37.2A55 55 0 0 0 31.7 94q2-3.7 4.3-7.5C15.4 72.7 12.5 52.2 12.5 52.2m187.9-4.8q10.3 6.3 19.2 14.6a49 49 0 0 1 39.2-9.8s-2.5 18.4-20.3 32q2.5 3.8 4.6 7.7a54 54 0 0 0 26-54.7s-44-18-68.7 10.2m-61.5 3.1a96 96 0 0 0-99 54q-1.5 6.6-1.6 13.6v4.2q.3 6 1 11.1c4.2 25 7.9 42.5 13.4 66.8l.2 1.2q1 6 3 11.8v-1.7c0-28.3 35-51.3 78.4-51.3 35.3 0 65.1 15.3 75 36.3a99 99 0 0 0 8.6-20.5c-38-23.5-53.9-41.1-64.6-64.2-10.8-23-15.5-47.3-14.4-61.3M91 130.3a12.6 12.6 0 1 1 0-25.2 12.6 12.6 0 0 1 0 25.2\" style=\"fill:#b58765\" transform=\"translate(10 10)\"/></svg>"},{"name":"planningcenter","displayName":"Planning Center","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0.1 26.2 26.4\"><path fill=\"#2565f4\" d=\"M23.2 2.7c1.8.5 3 2.2 3 4v13c0 1.8-1.3 3.5-3 4l-8 2.5a8 8 0 0 1-4.3 0L3 23.8c-1.7-.6-3-2.3-3-4.1v-13c0-1.8 1.3-3.4 3-4l8-2.3a8 8 0 0 1 4.2 0z\"/><path fill=\"#fff\" d=\"m18 7.6-4.7 1.3h-.5L8 7.6q-1.7-.3-1.8 1.3v10.5q0 .3.3.4l1.7.4q.5.1.5-.3v-2.5H9l3.5 1h1.4l5.2-1.6q.9-.2.9-1V9c0-1-1-1.7-2-1.4m-.6 7-.2.1-3.7 1.2h-.6l-3.7-1a.2.2 0 0 1-.2-.3v-3.8q0-.2.3-.2l3 .8a3 3 0 0 0 1.8 0l3-.8q.2 0 .3.2z\"/></svg>"},{"name":"oidc","displayName":"OIDC","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"93\" height=\"84\" fill=\"none\"><path fill=\"#ccc\" d=\"M83.4 32.9c-8.7-5.5-21-8.8-34.3-8.8C22 24 .4 37.5.4 54 .4 69.3 18.5 81.8 42 84v-8.7c-15.9-2-27.8-10.7-27.8-21 0-11.9 15.5-21.6 34.8-21.6 9.5 0 18.2 2.4 24.5 6.3l-9 5.6h27.9V27.3z\"/><path fill=\"#ff6200\" d=\"M42 9.2V84l14-8.7V.2z\"/></svg>"},{"name":"oidc2","displayName":"OIDC","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"93\" height=\"84\" fill=\"none\"><path fill=\"#ccc\" d=\"M83.4 32.9c-8.7-5.5-21-8.8-34.3-8.8C22 24 .4 37.5.4 54 .4 69.3 18.5 81.8 42 84v-8.7c-15.9-2-27.8-10.7-27.8-21 0-11.9 15.5-21.6 34.8-21.6 9.5 0 18.2 2.4 24.5 6.3l-9 5.6h27.9V27.3z\"/><path fill=\"#ff6200\" d=\"M42 9.2V84l14-8.7V.2z\"/></svg>"},{"name":"oidc3","displayName":"OIDC","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"93\" height=\"84\" fill=\"none\"><path fill=\"#ccc\" d=\"M83.4 32.9c-8.7-5.5-21-8.8-34.3-8.8C22 24 .4 37.5.4 54 .4 69.3 18.5 81.8 42 84v-8.7c-15.9-2-27.8-10.7-27.8-21 0-11.9 15.5-21.6 34.8-21.6 9.5 0 18.2 2.4 24.5 6.3l-9 5.6h27.9V27.3z\"/><path fill=\"#ff6200\" d=\"M42 9.2V84l14-8.7V.2z\"/></svg>"},{"name":"cloudflare","displayName":"Cloudflare","logo":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 116\" preserveAspectRatio=\"xMidYMid\"><path d=\"M202.4 110.7c1.3-4.5.8-8.7-1.4-11.8-2-2.8-5.4-4.5-9.5-4.7l-77.4-1c-.5 0-1-.3-1.2-.7-.3-.4-.3-1-.2-1.5.3-.8 1-1.3 1.8-1.4l78.1-1c9.3-.4 19.3-7.9 22.8-17.1l4.5-11.6c.2-.5.3-1 .1-1.5C214.9 25.4 194.1 8 169.4 8c-22.8 0-42.2 14.7-49.2 35.2a23.4 23.4 0 0 0-16.3-4.5c-10.9 1.1-19.6 9.8-20.7 20.7-.3 2.8-.1 5.5.6 8.1C66 68 51.8 82.5 51.8 100.3c0 1.6.1 3.2.4 4.8.1.7.7 1.3 1.5 1.3h142.9c.8 0 1.6-.6 1.8-1.4l4-14.3Z\" fill=\"#F38020\"/><path d=\"M227.2 61.2c-.7 0-1.4 0-2.1.1-.5 0-1 .4-1.1.9l-3 10.5c-1.3 4.5-.8 8.7 1.4 11.8 2 2.8 5.4 4.5 9.5 4.7l16.5 1c.5 0 1 .3 1.2.7.3.4.3 1 .2 1.5-.3.8-1 1.3-1.8 1.4l-17.2 1c-9.3.4-19.3 7.9-22.8 17.1l-1.2 3.2c-.3.6.2 1.2.8 1.2h59.2c.7 0 1.3-.5 1.5-1.1 1-3.7 1.6-7.5 1.6-11.5 0-23.5-19.1-42.5-42.7-42.5Z\" fill=\"#FAAE40\"/></svg>"}]
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
{
|
|
2
|
+
"auth": {
|
|
3
|
+
"id": "",
|
|
4
|
+
"listRule": null,
|
|
5
|
+
"viewRule": null,
|
|
6
|
+
"createRule": null,
|
|
7
|
+
"updateRule": null,
|
|
8
|
+
"deleteRule": null,
|
|
9
|
+
"name": "",
|
|
10
|
+
"type": "auth",
|
|
11
|
+
"fields": [
|
|
12
|
+
{
|
|
13
|
+
"autogeneratePattern": "[a-z0-9]{15}",
|
|
14
|
+
"help": "",
|
|
15
|
+
"hidden": false,
|
|
16
|
+
"id": "text3208210256",
|
|
17
|
+
"max": 15,
|
|
18
|
+
"min": 15,
|
|
19
|
+
"name": "id",
|
|
20
|
+
"pattern": "^[a-z0-9]+$",
|
|
21
|
+
"presentable": false,
|
|
22
|
+
"primaryKey": true,
|
|
23
|
+
"required": true,
|
|
24
|
+
"system": true,
|
|
25
|
+
"type": "text"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"cost": 0,
|
|
29
|
+
"help": "",
|
|
30
|
+
"hidden": true,
|
|
31
|
+
"id": "password901924565",
|
|
32
|
+
"max": 0,
|
|
33
|
+
"min": 8,
|
|
34
|
+
"name": "password",
|
|
35
|
+
"pattern": "",
|
|
36
|
+
"presentable": false,
|
|
37
|
+
"required": true,
|
|
38
|
+
"system": true,
|
|
39
|
+
"type": "password"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"autogeneratePattern": "[a-zA-Z0-9]{50}",
|
|
43
|
+
"help": "",
|
|
44
|
+
"hidden": true,
|
|
45
|
+
"id": "text2504183744",
|
|
46
|
+
"max": 60,
|
|
47
|
+
"min": 30,
|
|
48
|
+
"name": "tokenKey",
|
|
49
|
+
"pattern": "",
|
|
50
|
+
"presentable": false,
|
|
51
|
+
"primaryKey": false,
|
|
52
|
+
"required": true,
|
|
53
|
+
"system": true,
|
|
54
|
+
"type": "text"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"exceptDomains": null,
|
|
58
|
+
"help": "",
|
|
59
|
+
"hidden": false,
|
|
60
|
+
"id": "email3885137012",
|
|
61
|
+
"name": "email",
|
|
62
|
+
"onlyDomains": null,
|
|
63
|
+
"presentable": false,
|
|
64
|
+
"required": true,
|
|
65
|
+
"system": true,
|
|
66
|
+
"type": "email"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"help": "",
|
|
70
|
+
"hidden": false,
|
|
71
|
+
"id": "bool1547992806",
|
|
72
|
+
"name": "emailVisibility",
|
|
73
|
+
"presentable": false,
|
|
74
|
+
"required": false,
|
|
75
|
+
"system": true,
|
|
76
|
+
"type": "bool"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"help": "",
|
|
80
|
+
"hidden": false,
|
|
81
|
+
"id": "bool256245529",
|
|
82
|
+
"name": "verified",
|
|
83
|
+
"presentable": false,
|
|
84
|
+
"required": false,
|
|
85
|
+
"system": true,
|
|
86
|
+
"type": "bool"
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
"indexes": [
|
|
90
|
+
"CREATE UNIQUE INDEX `idx_tokenKey_lo1tke8csl` ON `` (`tokenKey`)",
|
|
91
|
+
"CREATE UNIQUE INDEX `idx_email_lo1tke8csl` ON `` (`email`) WHERE `email` != ''"
|
|
92
|
+
],
|
|
93
|
+
"created": "",
|
|
94
|
+
"updated": "",
|
|
95
|
+
"system": false,
|
|
96
|
+
"authRule": "",
|
|
97
|
+
"manageRule": null,
|
|
98
|
+
"authAlert": {
|
|
99
|
+
"enabled": true,
|
|
100
|
+
"emailTemplate": {
|
|
101
|
+
"subject": "Login from a new location",
|
|
102
|
+
"body": "<p>Hello,</p>\n<p>We noticed a login to your {APP_NAME} account from a new location:</p>\n<p><em>{ALERT_INFO}</em></p>\n<p><strong>If this wasn't you, you should immediately change your {APP_NAME} account password to revoke access from all other locations.</strong></p>\n<p>If this was you, you may disregard this email.</p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"oauth2": {
|
|
106
|
+
"providers": [],
|
|
107
|
+
"mappedFields": {
|
|
108
|
+
"id": "",
|
|
109
|
+
"name": "",
|
|
110
|
+
"username": "",
|
|
111
|
+
"avatarURL": ""
|
|
112
|
+
},
|
|
113
|
+
"enabled": false
|
|
114
|
+
},
|
|
115
|
+
"passwordAuth": {
|
|
116
|
+
"enabled": true,
|
|
117
|
+
"identityFields": [
|
|
118
|
+
"email"
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
"mfa": {
|
|
122
|
+
"enabled": false,
|
|
123
|
+
"duration": 600,
|
|
124
|
+
"rule": ""
|
|
125
|
+
},
|
|
126
|
+
"otp": {
|
|
127
|
+
"enabled": false,
|
|
128
|
+
"duration": 180,
|
|
129
|
+
"length": 8,
|
|
130
|
+
"emailTemplate": {
|
|
131
|
+
"subject": "OTP for {APP_NAME}",
|
|
132
|
+
"body": "<p>Hello,</p>\n<p>Your one-time password is: <strong>{OTP}</strong></p>\n<p><i>If you didn't ask for the one-time password, you can ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"authToken": {
|
|
136
|
+
"duration": 432000
|
|
137
|
+
},
|
|
138
|
+
"passwordResetToken": {
|
|
139
|
+
"duration": 1800
|
|
140
|
+
},
|
|
141
|
+
"emailChangeToken": {
|
|
142
|
+
"duration": 1800
|
|
143
|
+
},
|
|
144
|
+
"verificationToken": {
|
|
145
|
+
"duration": 86400
|
|
146
|
+
},
|
|
147
|
+
"fileToken": {
|
|
148
|
+
"duration": 180
|
|
149
|
+
},
|
|
150
|
+
"verificationTemplate": {
|
|
151
|
+
"subject": "Verify your {APP_NAME} email",
|
|
152
|
+
"body": "<p>Hello,</p>\n<p>Thank you for joining us at {APP_NAME}.</p>\n<p>Click on the button below to verify your email address.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-verification/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Verify</a>\n</p>\n<p><i>If you didn't recently register, please ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
|
153
|
+
},
|
|
154
|
+
"resetPasswordTemplate": {
|
|
155
|
+
"subject": "Reset your {APP_NAME} password",
|
|
156
|
+
"body": "<p>Hello,</p>\n<p>Click on the button below to reset your password.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-password-reset/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Reset password</a>\n</p>\n<p><i>If you didn't ask to reset your password, please ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
|
157
|
+
},
|
|
158
|
+
"confirmEmailChangeTemplate": {
|
|
159
|
+
"subject": "Confirm your {APP_NAME} new email address",
|
|
160
|
+
"body": "<p>Hello,</p>\n<p>Click on the button below to confirm your new email address.</p>\n<p>\n <a class=\"btn\" href=\"{APP_URL}/_/#/auth/confirm-email-change/{TOKEN}\" target=\"_blank\" rel=\"noopener\">Confirm new email</a>\n</p>\n<p><i>If you didn't ask to change your email address, please ignore this email.</i></p>\n<p>\n Thanks,<br/>\n {APP_NAME} team\n</p>"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"base": {
|
|
164
|
+
"id": "",
|
|
165
|
+
"listRule": null,
|
|
166
|
+
"viewRule": null,
|
|
167
|
+
"createRule": null,
|
|
168
|
+
"updateRule": null,
|
|
169
|
+
"deleteRule": null,
|
|
170
|
+
"name": "",
|
|
171
|
+
"type": "base",
|
|
172
|
+
"fields": [
|
|
173
|
+
{
|
|
174
|
+
"autogeneratePattern": "[a-z0-9]{15}",
|
|
175
|
+
"help": "",
|
|
176
|
+
"hidden": false,
|
|
177
|
+
"id": "text3208210256",
|
|
178
|
+
"max": 15,
|
|
179
|
+
"min": 15,
|
|
180
|
+
"name": "id",
|
|
181
|
+
"pattern": "^[a-z0-9]+$",
|
|
182
|
+
"presentable": false,
|
|
183
|
+
"primaryKey": true,
|
|
184
|
+
"required": true,
|
|
185
|
+
"system": true,
|
|
186
|
+
"type": "text"
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"indexes": [],
|
|
190
|
+
"created": "",
|
|
191
|
+
"updated": "",
|
|
192
|
+
"system": false
|
|
193
|
+
},
|
|
194
|
+
"view": {
|
|
195
|
+
"id": "",
|
|
196
|
+
"listRule": null,
|
|
197
|
+
"viewRule": null,
|
|
198
|
+
"createRule": null,
|
|
199
|
+
"updateRule": null,
|
|
200
|
+
"deleteRule": null,
|
|
201
|
+
"name": "",
|
|
202
|
+
"type": "view",
|
|
203
|
+
"fields": [],
|
|
204
|
+
"indexes": [],
|
|
205
|
+
"created": "",
|
|
206
|
+
"updated": "",
|
|
207
|
+
"system": false,
|
|
208
|
+
"viewQuery": ""
|
|
209
|
+
}
|
|
210
|
+
}
|