@jskit-ai/users-core 0.1.32 → 0.1.35
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.descriptor.mjs +16 -245
- package/package.json +7 -7
- package/src/server/UsersCoreServiceProvider.js +4 -28
- package/src/server/UsersWorkspacesServiceProvider.js +44 -0
- package/src/server/accountNotifications/accountNotificationsService.js +3 -3
- package/src/server/accountNotifications/registerAccountNotifications.js +1 -1
- package/src/server/accountPreferences/accountPreferencesService.js +3 -3
- package/src/server/accountPreferences/registerAccountPreferences.js +1 -1
- package/src/server/accountProfile/accountProfileActions.js +8 -2
- package/src/server/accountProfile/accountProfileService.js +10 -10
- package/src/server/accountProfile/avatarService.js +9 -9
- package/src/server/accountProfile/bootAccountProfileRoutes.js +5 -3
- package/src/server/accountProfile/registerAccountProfile.js +2 -2
- package/src/server/accountSecurity/accountSecurityService.js +3 -3
- package/src/server/accountSecurity/registerAccountSecurity.js +1 -1
- package/src/server/common/contributors/workspaceActionContextContributor.js +24 -17
- package/src/server/common/registerCommonRepositories.js +3 -22
- package/src/server/common/repositories/userSettingsRepository.js +1 -12
- package/src/server/common/repositories/{userProfilesRepository.js → usersRepository.js} +1 -1
- package/src/server/common/services/accountContextService.js +4 -4
- package/src/server/common/services/authProfileSyncService.js +10 -10
- package/src/server/registerUsersBootstrap.js +22 -0
- package/src/server/registerUsersCore.js +30 -0
- package/src/server/registerWorkspaceBootstrap.js +3 -6
- package/src/server/registerWorkspaceCore.js +5 -17
- package/src/server/registerWorkspaceRepositories.js +26 -0
- package/src/server/usersBootstrapContributor.js +248 -0
- package/src/server/workspaceBootstrapContributor.js +65 -259
- package/src/shared/roles.js +31 -6
- package/src/shared/settings.js +1 -2
- package/templates/migrations/users_core_generic_initial.cjs +69 -0
- package/test/authProfileSyncService.test.js +3 -3
- package/test/avatarService.test.js +2 -2
- package/test/registerUsersCore.test.js +42 -0
- package/test/roles.test.js +90 -5
- package/test/usersBootstrapContributor.test.js +172 -0
- package/test/usersRouteRequestInputValidator.test.js +7 -390
- package/test/workspaceActionContextContributor.test.js +98 -5
- package/test/workspaceBootstrapContributor.test.js +34 -346
- package/test/workspaceMembersService.test.js +4 -2
- package/test/workspaceService.test.js +12 -8
- package/test/workspaceSettingsResource.test.js +4 -2
- package/test-support/registerDefaultSettingsFields.js +1 -1
- package/templates/config/workspaceRoles.js +0 -30
- package/templates/migrations/users_core_initial.cjs +0 -123
- package/templates/migrations/users_core_workspace_settings_single_name_source.cjs +0 -71
- package/templates/migrations/users_core_workspaces_drop_color.cjs +0 -85
- package/templates/packages/main/src/shared/resources/workspaceSettingsFields.js +0 -197
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param {import('knex').Knex} knex
|
|
3
|
-
*/
|
|
4
|
-
exports.up = async function up(knex) {
|
|
5
|
-
await knex.schema.createTable("users", (table) => {
|
|
6
|
-
table.increments("id").primary();
|
|
7
|
-
table.string("auth_provider", 64).notNullable();
|
|
8
|
-
table.string("auth_provider_user_sid", 191).notNullable();
|
|
9
|
-
table.string("email", 255).notNullable();
|
|
10
|
-
table.string("username", 120).notNullable();
|
|
11
|
-
table.string("display_name", 160).notNullable();
|
|
12
|
-
table.string("avatar_storage_key", 512).nullable();
|
|
13
|
-
table.string("avatar_version", 64).nullable();
|
|
14
|
-
table.timestamp("avatar_updated_at", { useTz: false }).nullable();
|
|
15
|
-
table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
16
|
-
table.unique(["auth_provider", "auth_provider_user_sid"], "uq_users_identity");
|
|
17
|
-
table.unique(["email"], "uq_users_email");
|
|
18
|
-
table.unique(["username"], "uq_users_username");
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
await knex.schema.createTable("workspaces", (table) => {
|
|
22
|
-
table.increments("id").primary();
|
|
23
|
-
table.string("slug", 120).notNullable().unique();
|
|
24
|
-
table.string("name", 160).notNullable();
|
|
25
|
-
table.integer("owner_user_id").unsigned().notNullable().references("id").inTable("users").onDelete("CASCADE");
|
|
26
|
-
table.boolean("is_personal").notNullable().defaultTo(true);
|
|
27
|
-
table.string("avatar_url", 512).notNullable().defaultTo("");
|
|
28
|
-
table.string("color", 7).notNullable().defaultTo("#1867C0");
|
|
29
|
-
table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
30
|
-
table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
31
|
-
table.timestamp("deleted_at", { useTz: false }).nullable();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
await knex.schema.createTable("workspace_memberships", (table) => {
|
|
35
|
-
table.increments("id").primary();
|
|
36
|
-
table.integer("workspace_id").unsigned().notNullable().references("id").inTable("workspaces").onDelete("CASCADE");
|
|
37
|
-
table.integer("user_id").unsigned().notNullable().references("id").inTable("users").onDelete("CASCADE");
|
|
38
|
-
table.string("role_sid", 64).notNullable().defaultTo("member");
|
|
39
|
-
table.string("status", 32).notNullable().defaultTo("active");
|
|
40
|
-
table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
41
|
-
table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
42
|
-
table.unique(["workspace_id", "user_id"], "uq_workspace_memberships_workspace_user");
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
await knex.schema.createTable("workspace_settings", (table) => {
|
|
46
|
-
table.integer("workspace_id").unsigned().primary().references("id").inTable("workspaces").onDelete("CASCADE");
|
|
47
|
-
table.string("name", 160).notNullable().defaultTo("Workspace");
|
|
48
|
-
table.string("avatar_url", 512).notNullable().defaultTo("");
|
|
49
|
-
table.string("light_primary_color", 7).notNullable().defaultTo("#1867C0");
|
|
50
|
-
table.string("light_secondary_color", 7).notNullable().defaultTo("#48A9A6");
|
|
51
|
-
table.string("light_surface_color", 7).notNullable().defaultTo("#FFFFFF");
|
|
52
|
-
table.string("light_surface_variant_color", 7).notNullable().defaultTo("#424242");
|
|
53
|
-
table.string("dark_primary_color", 7).notNullable().defaultTo("#2196F3");
|
|
54
|
-
table.string("dark_secondary_color", 7).notNullable().defaultTo("#54B6B2");
|
|
55
|
-
table.string("dark_surface_color", 7).notNullable().defaultTo("#212121");
|
|
56
|
-
table.string("dark_surface_variant_color", 7).notNullable().defaultTo("#C8C8C8");
|
|
57
|
-
table.boolean("invites_enabled").notNullable().defaultTo(true);
|
|
58
|
-
table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
59
|
-
table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
await knex.schema.createTable("workspace_invites", (table) => {
|
|
63
|
-
table.increments("id").primary();
|
|
64
|
-
table.integer("workspace_id").unsigned().notNullable().references("id").inTable("workspaces").onDelete("CASCADE");
|
|
65
|
-
table.string("email", 255).notNullable();
|
|
66
|
-
table.string("role_sid", 64).notNullable().defaultTo("member");
|
|
67
|
-
table.string("status", 32).notNullable().defaultTo("pending");
|
|
68
|
-
table.string("token_hash", 191).notNullable();
|
|
69
|
-
table.integer("invited_by_user_id").unsigned().nullable().references("id").inTable("users").onDelete("SET NULL");
|
|
70
|
-
table.timestamp("expires_at", { useTz: false }).nullable();
|
|
71
|
-
table.timestamp("accepted_at", { useTz: false }).nullable();
|
|
72
|
-
table.timestamp("revoked_at", { useTz: false }).nullable();
|
|
73
|
-
table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
74
|
-
table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
75
|
-
table.unique(["token_hash"], "uq_workspace_invites_token_hash");
|
|
76
|
-
table.index(["workspace_id", "status"], "idx_workspace_invites_workspace_status");
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
await knex.schema.createTable("user_settings", (table) => {
|
|
80
|
-
table.integer("user_id").unsigned().primary().references("id").inTable("users").onDelete("CASCADE");
|
|
81
|
-
table.integer("last_active_workspace_id").unsigned().nullable().references("id").inTable("workspaces").onDelete("SET NULL");
|
|
82
|
-
table.string("theme", 32).notNullable().defaultTo("system");
|
|
83
|
-
table.string("locale", 24).notNullable().defaultTo("en");
|
|
84
|
-
table.string("time_zone", 64).notNullable().defaultTo("UTC");
|
|
85
|
-
table.string("date_format", 32).notNullable().defaultTo("yyyy-mm-dd");
|
|
86
|
-
table.string("number_format", 32).notNullable().defaultTo("1,234.56");
|
|
87
|
-
table.string("currency_code", 3).notNullable().defaultTo("USD");
|
|
88
|
-
table.integer("avatar_size").notNullable().defaultTo(64);
|
|
89
|
-
table.boolean("password_sign_in_enabled").notNullable().defaultTo(true);
|
|
90
|
-
table.boolean("password_setup_required").notNullable().defaultTo(false);
|
|
91
|
-
table.boolean("notify_product_updates").notNullable().defaultTo(true);
|
|
92
|
-
table.boolean("notify_account_activity").notNullable().defaultTo(true);
|
|
93
|
-
table.boolean("notify_security_alerts").notNullable().defaultTo(true);
|
|
94
|
-
table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
95
|
-
table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
await knex.schema.createTable("console_settings", (table) => {
|
|
99
|
-
table.integer("id").primary();
|
|
100
|
-
table.integer("owner_user_id").unsigned().nullable().references("id").inTable("users").onDelete("SET NULL");
|
|
101
|
-
table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
102
|
-
table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
await knex("console_settings").insert({
|
|
106
|
-
id: 1,
|
|
107
|
-
created_at: knex.fn.now(),
|
|
108
|
-
updated_at: knex.fn.now()
|
|
109
|
-
});
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* @param {import('knex').Knex} knex
|
|
114
|
-
*/
|
|
115
|
-
exports.down = async function down(knex) {
|
|
116
|
-
await knex.schema.dropTableIfExists("console_settings");
|
|
117
|
-
await knex.schema.dropTableIfExists("user_settings");
|
|
118
|
-
await knex.schema.dropTableIfExists("workspace_invites");
|
|
119
|
-
await knex.schema.dropTableIfExists("workspace_settings");
|
|
120
|
-
await knex.schema.dropTableIfExists("workspace_memberships");
|
|
121
|
-
await knex.schema.dropTableIfExists("workspaces");
|
|
122
|
-
await knex.schema.dropTableIfExists("users");
|
|
123
|
-
};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
const WORKSPACE_SETTINGS_TABLE = "workspace_settings";
|
|
2
|
-
const WORKSPACES_TABLE = "workspaces";
|
|
3
|
-
const LEGACY_NAME_COLUMN = "name";
|
|
4
|
-
const LEGACY_AVATAR_COLUMN = "avatar_url";
|
|
5
|
-
|
|
6
|
-
async function hasTable(knex, tableName) {
|
|
7
|
-
return knex.schema.hasTable(tableName);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async function hasColumn(knex, tableName, columnName) {
|
|
11
|
-
return knex.schema.hasColumn(tableName, columnName);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
exports.up = async function up(knex) {
|
|
15
|
-
const hasWorkspaceSettings = await hasTable(knex, WORKSPACE_SETTINGS_TABLE);
|
|
16
|
-
if (!hasWorkspaceSettings) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const hasLegacyName = await hasColumn(knex, WORKSPACE_SETTINGS_TABLE, LEGACY_NAME_COLUMN);
|
|
21
|
-
const hasLegacyAvatarUrl = await hasColumn(knex, WORKSPACE_SETTINGS_TABLE, LEGACY_AVATAR_COLUMN);
|
|
22
|
-
if (!hasLegacyName && !hasLegacyAvatarUrl) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
await knex.schema.alterTable(WORKSPACE_SETTINGS_TABLE, (table) => {
|
|
27
|
-
if (hasLegacyName) {
|
|
28
|
-
table.dropColumn(LEGACY_NAME_COLUMN);
|
|
29
|
-
}
|
|
30
|
-
if (hasLegacyAvatarUrl) {
|
|
31
|
-
table.dropColumn(LEGACY_AVATAR_COLUMN);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
exports.down = async function down(knex) {
|
|
37
|
-
const hasWorkspaceSettings = await hasTable(knex, WORKSPACE_SETTINGS_TABLE);
|
|
38
|
-
if (!hasWorkspaceSettings) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const hasLegacyName = await hasColumn(knex, WORKSPACE_SETTINGS_TABLE, LEGACY_NAME_COLUMN);
|
|
43
|
-
const hasLegacyAvatarUrl = await hasColumn(knex, WORKSPACE_SETTINGS_TABLE, LEGACY_AVATAR_COLUMN);
|
|
44
|
-
if (!hasLegacyName || !hasLegacyAvatarUrl) {
|
|
45
|
-
await knex.schema.alterTable(WORKSPACE_SETTINGS_TABLE, (table) => {
|
|
46
|
-
if (!hasLegacyName) {
|
|
47
|
-
table.string(LEGACY_NAME_COLUMN, 160).notNullable().defaultTo("Workspace");
|
|
48
|
-
}
|
|
49
|
-
if (!hasLegacyAvatarUrl) {
|
|
50
|
-
table.string(LEGACY_AVATAR_COLUMN, 512).notNullable().defaultTo("");
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const hasWorkspaces = await hasTable(knex, WORKSPACES_TABLE);
|
|
56
|
-
if (!hasWorkspaces) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const workspaceRows = await knex(WORKSPACES_TABLE).select("id", "name", "avatar_url");
|
|
61
|
-
for (const workspaceRow of workspaceRows) {
|
|
62
|
-
const normalizedName = String(workspaceRow?.name || "").trim() || "Workspace";
|
|
63
|
-
const normalizedAvatarUrl = String(workspaceRow?.avatar_url || "").trim();
|
|
64
|
-
await knex(WORKSPACE_SETTINGS_TABLE)
|
|
65
|
-
.where({ workspace_id: Number(workspaceRow.id) })
|
|
66
|
-
.update({
|
|
67
|
-
name: normalizedName,
|
|
68
|
-
avatar_url: normalizedAvatarUrl
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
};
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
const WORKSPACES_TABLE = "workspaces";
|
|
2
|
-
const WORKSPACE_SETTINGS_TABLE = "workspace_settings";
|
|
3
|
-
const LEGACY_COLOR_COLUMN = "color";
|
|
4
|
-
const SETTINGS_LIGHT_PRIMARY_COLOR_COLUMN = "light_primary_color";
|
|
5
|
-
const DEFAULT_WORKSPACE_COLOR = "#1867C0";
|
|
6
|
-
|
|
7
|
-
async function hasTable(knex, tableName) {
|
|
8
|
-
return knex.schema.hasTable(tableName);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async function hasColumn(knex, tableName, columnName) {
|
|
12
|
-
return knex.schema.hasColumn(tableName, columnName);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function normalizeHexColor(value) {
|
|
16
|
-
const normalized = String(value || "").trim().toUpperCase();
|
|
17
|
-
return /^#[0-9A-F]{6}$/.test(normalized) ? normalized : "";
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
exports.up = async function up(knex) {
|
|
21
|
-
const hasWorkspaces = await hasTable(knex, WORKSPACES_TABLE);
|
|
22
|
-
if (!hasWorkspaces) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const hasLegacyColor = await hasColumn(knex, WORKSPACES_TABLE, LEGACY_COLOR_COLUMN);
|
|
27
|
-
if (!hasLegacyColor) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
await knex.schema.alterTable(WORKSPACES_TABLE, (table) => {
|
|
32
|
-
table.dropColumn(LEGACY_COLOR_COLUMN);
|
|
33
|
-
});
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
exports.down = async function down(knex) {
|
|
37
|
-
const hasWorkspaces = await hasTable(knex, WORKSPACES_TABLE);
|
|
38
|
-
if (!hasWorkspaces) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const hasLegacyColor = await hasColumn(knex, WORKSPACES_TABLE, LEGACY_COLOR_COLUMN);
|
|
43
|
-
if (!hasLegacyColor) {
|
|
44
|
-
await knex.schema.alterTable(WORKSPACES_TABLE, (table) => {
|
|
45
|
-
table.string(LEGACY_COLOR_COLUMN, 7).notNullable().defaultTo(DEFAULT_WORKSPACE_COLOR);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const hasWorkspaceSettings = await hasTable(knex, WORKSPACE_SETTINGS_TABLE);
|
|
50
|
-
if (!hasWorkspaceSettings) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const hasLightPrimaryColor = await hasColumn(
|
|
55
|
-
knex,
|
|
56
|
-
WORKSPACE_SETTINGS_TABLE,
|
|
57
|
-
SETTINGS_LIGHT_PRIMARY_COLOR_COLUMN
|
|
58
|
-
);
|
|
59
|
-
if (!hasLightPrimaryColor) {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const workspaceSettingsRows = await knex(WORKSPACE_SETTINGS_TABLE).select(
|
|
64
|
-
"workspace_id",
|
|
65
|
-
SETTINGS_LIGHT_PRIMARY_COLOR_COLUMN
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
for (const row of workspaceSettingsRows) {
|
|
69
|
-
const workspaceId = Number(row?.workspace_id || 0);
|
|
70
|
-
if (!Number.isInteger(workspaceId) || workspaceId < 1) {
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const restoredColor = normalizeHexColor(row?.[SETTINGS_LIGHT_PRIMARY_COLOR_COLUMN]);
|
|
75
|
-
if (!restoredColor) {
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
await knex(WORKSPACES_TABLE)
|
|
80
|
-
.where({ id: workspaceId })
|
|
81
|
-
.update({
|
|
82
|
-
color: restoredColor
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
};
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
// @jskit-contract users.settings-fields.workspace.v1
|
|
2
|
-
// Append-only settings field registrations for workspace settings.
|
|
3
|
-
|
|
4
|
-
import { Type } from "typebox";
|
|
5
|
-
import { normalizeText } from "@jskit-ai/kernel/shared/actions/textNormalization";
|
|
6
|
-
import {
|
|
7
|
-
DEFAULT_WORKSPACE_DARK_PALETTE,
|
|
8
|
-
DEFAULT_WORKSPACE_LIGHT_PALETTE,
|
|
9
|
-
coerceWorkspaceThemeColor
|
|
10
|
-
} from "@jskit-ai/users-core/shared/settings";
|
|
11
|
-
import {
|
|
12
|
-
defineField,
|
|
13
|
-
resetWorkspaceSettingsFields
|
|
14
|
-
} from "@jskit-ai/users-core/shared/resources/workspaceSettingsFields";
|
|
15
|
-
|
|
16
|
-
function normalizeHexColor(value) {
|
|
17
|
-
const color = normalizeText(value);
|
|
18
|
-
return /^#[0-9A-Fa-f]{6}$/.test(color) ? color.toUpperCase() : null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
resetWorkspaceSettingsFields();
|
|
22
|
-
|
|
23
|
-
defineField({
|
|
24
|
-
key: "lightPrimaryColor",
|
|
25
|
-
dbColumn: "light_primary_color",
|
|
26
|
-
required: true,
|
|
27
|
-
inputSchema: Type.String({
|
|
28
|
-
minLength: 7,
|
|
29
|
-
maxLength: 7,
|
|
30
|
-
pattern: "^#[0-9A-Fa-f]{6}$",
|
|
31
|
-
messages: {
|
|
32
|
-
required: "Light primary color is required.",
|
|
33
|
-
pattern: "Light primary color must be a hex color like #1867C0.",
|
|
34
|
-
default: "Light primary color must be a hex color like #1867C0."
|
|
35
|
-
}
|
|
36
|
-
}),
|
|
37
|
-
outputSchema: Type.String({ minLength: 7, maxLength: 7, pattern: "^#[0-9A-Fa-f]{6}$" }),
|
|
38
|
-
normalizeInput: normalizeHexColor,
|
|
39
|
-
normalizeOutput: (value) => coerceWorkspaceThemeColor(value, DEFAULT_WORKSPACE_LIGHT_PALETTE.color),
|
|
40
|
-
resolveDefault: () => DEFAULT_WORKSPACE_LIGHT_PALETTE.color
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
defineField({
|
|
44
|
-
key: "lightSecondaryColor",
|
|
45
|
-
dbColumn: "light_secondary_color",
|
|
46
|
-
required: true,
|
|
47
|
-
inputSchema: Type.String({
|
|
48
|
-
minLength: 7,
|
|
49
|
-
maxLength: 7,
|
|
50
|
-
pattern: "^#[0-9A-Fa-f]{6}$",
|
|
51
|
-
messages: {
|
|
52
|
-
required: "Light secondary color is required.",
|
|
53
|
-
pattern: "Light secondary color must be a hex color like #48A9A6.",
|
|
54
|
-
default: "Light secondary color must be a hex color like #48A9A6."
|
|
55
|
-
}
|
|
56
|
-
}),
|
|
57
|
-
outputSchema: Type.String({ minLength: 7, maxLength: 7, pattern: "^#[0-9A-Fa-f]{6}$" }),
|
|
58
|
-
normalizeInput: normalizeHexColor,
|
|
59
|
-
normalizeOutput: (value) => coerceWorkspaceThemeColor(value, DEFAULT_WORKSPACE_LIGHT_PALETTE.secondaryColor),
|
|
60
|
-
resolveDefault: () => DEFAULT_WORKSPACE_LIGHT_PALETTE.secondaryColor
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
defineField({
|
|
64
|
-
key: "lightSurfaceColor",
|
|
65
|
-
dbColumn: "light_surface_color",
|
|
66
|
-
required: true,
|
|
67
|
-
inputSchema: Type.String({
|
|
68
|
-
minLength: 7,
|
|
69
|
-
maxLength: 7,
|
|
70
|
-
pattern: "^#[0-9A-Fa-f]{6}$",
|
|
71
|
-
messages: {
|
|
72
|
-
required: "Light surface color is required.",
|
|
73
|
-
pattern: "Light surface color must be a hex color like #FFFFFF.",
|
|
74
|
-
default: "Light surface color must be a hex color like #FFFFFF."
|
|
75
|
-
}
|
|
76
|
-
}),
|
|
77
|
-
outputSchema: Type.String({ minLength: 7, maxLength: 7, pattern: "^#[0-9A-Fa-f]{6}$" }),
|
|
78
|
-
normalizeInput: normalizeHexColor,
|
|
79
|
-
normalizeOutput: (value) => coerceWorkspaceThemeColor(value, DEFAULT_WORKSPACE_LIGHT_PALETTE.surfaceColor),
|
|
80
|
-
resolveDefault: () => DEFAULT_WORKSPACE_LIGHT_PALETTE.surfaceColor
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
defineField({
|
|
84
|
-
key: "lightSurfaceVariantColor",
|
|
85
|
-
dbColumn: "light_surface_variant_color",
|
|
86
|
-
required: true,
|
|
87
|
-
inputSchema: Type.String({
|
|
88
|
-
minLength: 7,
|
|
89
|
-
maxLength: 7,
|
|
90
|
-
pattern: "^#[0-9A-Fa-f]{6}$",
|
|
91
|
-
messages: {
|
|
92
|
-
required: "Light surface variant color is required.",
|
|
93
|
-
pattern: "Light surface variant color must be a hex color like #424242.",
|
|
94
|
-
default: "Light surface variant color must be a hex color like #424242."
|
|
95
|
-
}
|
|
96
|
-
}),
|
|
97
|
-
outputSchema: Type.String({ minLength: 7, maxLength: 7, pattern: "^#[0-9A-Fa-f]{6}$" }),
|
|
98
|
-
normalizeInput: normalizeHexColor,
|
|
99
|
-
normalizeOutput: (value) => coerceWorkspaceThemeColor(value, DEFAULT_WORKSPACE_LIGHT_PALETTE.surfaceVariantColor),
|
|
100
|
-
resolveDefault: () => DEFAULT_WORKSPACE_LIGHT_PALETTE.surfaceVariantColor
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
defineField({
|
|
104
|
-
key: "darkPrimaryColor",
|
|
105
|
-
dbColumn: "dark_primary_color",
|
|
106
|
-
required: true,
|
|
107
|
-
inputSchema: Type.String({
|
|
108
|
-
minLength: 7,
|
|
109
|
-
maxLength: 7,
|
|
110
|
-
pattern: "^#[0-9A-Fa-f]{6}$",
|
|
111
|
-
messages: {
|
|
112
|
-
required: "Dark primary color is required.",
|
|
113
|
-
pattern: "Dark primary color must be a hex color like #2196F3.",
|
|
114
|
-
default: "Dark primary color must be a hex color like #2196F3."
|
|
115
|
-
}
|
|
116
|
-
}),
|
|
117
|
-
outputSchema: Type.String({ minLength: 7, maxLength: 7, pattern: "^#[0-9A-Fa-f]{6}$" }),
|
|
118
|
-
normalizeInput: normalizeHexColor,
|
|
119
|
-
normalizeOutput: (value) => coerceWorkspaceThemeColor(value, DEFAULT_WORKSPACE_DARK_PALETTE.color),
|
|
120
|
-
resolveDefault: () => DEFAULT_WORKSPACE_DARK_PALETTE.color
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
defineField({
|
|
124
|
-
key: "darkSecondaryColor",
|
|
125
|
-
dbColumn: "dark_secondary_color",
|
|
126
|
-
required: true,
|
|
127
|
-
inputSchema: Type.String({
|
|
128
|
-
minLength: 7,
|
|
129
|
-
maxLength: 7,
|
|
130
|
-
pattern: "^#[0-9A-Fa-f]{6}$",
|
|
131
|
-
messages: {
|
|
132
|
-
required: "Dark secondary color is required.",
|
|
133
|
-
pattern: "Dark secondary color must be a hex color like #54B6B2.",
|
|
134
|
-
default: "Dark secondary color must be a hex color like #54B6B2."
|
|
135
|
-
}
|
|
136
|
-
}),
|
|
137
|
-
outputSchema: Type.String({ minLength: 7, maxLength: 7, pattern: "^#[0-9A-Fa-f]{6}$" }),
|
|
138
|
-
normalizeInput: normalizeHexColor,
|
|
139
|
-
normalizeOutput: (value) => coerceWorkspaceThemeColor(value, DEFAULT_WORKSPACE_DARK_PALETTE.secondaryColor),
|
|
140
|
-
resolveDefault: () => DEFAULT_WORKSPACE_DARK_PALETTE.secondaryColor
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
defineField({
|
|
144
|
-
key: "darkSurfaceColor",
|
|
145
|
-
dbColumn: "dark_surface_color",
|
|
146
|
-
required: true,
|
|
147
|
-
inputSchema: Type.String({
|
|
148
|
-
minLength: 7,
|
|
149
|
-
maxLength: 7,
|
|
150
|
-
pattern: "^#[0-9A-Fa-f]{6}$",
|
|
151
|
-
messages: {
|
|
152
|
-
required: "Dark surface color is required.",
|
|
153
|
-
pattern: "Dark surface color must be a hex color like #212121.",
|
|
154
|
-
default: "Dark surface color must be a hex color like #212121."
|
|
155
|
-
}
|
|
156
|
-
}),
|
|
157
|
-
outputSchema: Type.String({ minLength: 7, maxLength: 7, pattern: "^#[0-9A-Fa-f]{6}$" }),
|
|
158
|
-
normalizeInput: normalizeHexColor,
|
|
159
|
-
normalizeOutput: (value) => coerceWorkspaceThemeColor(value, DEFAULT_WORKSPACE_DARK_PALETTE.surfaceColor),
|
|
160
|
-
resolveDefault: () => DEFAULT_WORKSPACE_DARK_PALETTE.surfaceColor
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
defineField({
|
|
164
|
-
key: "darkSurfaceVariantColor",
|
|
165
|
-
dbColumn: "dark_surface_variant_color",
|
|
166
|
-
required: true,
|
|
167
|
-
inputSchema: Type.String({
|
|
168
|
-
minLength: 7,
|
|
169
|
-
maxLength: 7,
|
|
170
|
-
pattern: "^#[0-9A-Fa-f]{6}$",
|
|
171
|
-
messages: {
|
|
172
|
-
required: "Dark surface variant color is required.",
|
|
173
|
-
pattern: "Dark surface variant color must be a hex color like #C8C8C8.",
|
|
174
|
-
default: "Dark surface variant color must be a hex color like #C8C8C8."
|
|
175
|
-
}
|
|
176
|
-
}),
|
|
177
|
-
outputSchema: Type.String({ minLength: 7, maxLength: 7, pattern: "^#[0-9A-Fa-f]{6}$" }),
|
|
178
|
-
normalizeInput: normalizeHexColor,
|
|
179
|
-
normalizeOutput: (value) => coerceWorkspaceThemeColor(value, DEFAULT_WORKSPACE_DARK_PALETTE.surfaceVariantColor),
|
|
180
|
-
resolveDefault: () => DEFAULT_WORKSPACE_DARK_PALETTE.surfaceVariantColor
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
defineField({
|
|
184
|
-
key: "invitesEnabled",
|
|
185
|
-
dbColumn: "invites_enabled",
|
|
186
|
-
required: true,
|
|
187
|
-
inputSchema: Type.Boolean({
|
|
188
|
-
messages: {
|
|
189
|
-
required: "invitesEnabled is required.",
|
|
190
|
-
default: "invitesEnabled must be a boolean."
|
|
191
|
-
}
|
|
192
|
-
}),
|
|
193
|
-
outputSchema: Type.Boolean(),
|
|
194
|
-
normalizeInput: (value) => value === true,
|
|
195
|
-
normalizeOutput: (value) => value !== false,
|
|
196
|
-
resolveDefault: ({ defaultInvitesEnabled } = {}) => defaultInvitesEnabled !== false
|
|
197
|
-
});
|