feat(housekeeping): complete people moderation parity
This commit is contained in:
1 parent
3d385d1869
commit
29fe22297b
41 files changed
+3465
-580
No files matched your search
@@ -5,6 +5,8 @@ vi.mock("@/lib/auth", () => ({ invalidateLoginCache: vi.fn() }));
|
||||
vi.mock("@/lib/auth/password", () => ({ hashPassword: vi.fn() }));
|
||||
|
||||
import { COMMUNITY_COMMAND_IDS } from "../../domains/people/commands/community-commands";
|
||||
import { MODERATION_COMMAND_IDS } from "../../domains/people/commands/moderation-commands";
|
||||
import { SUPPORT_COMMAND_IDS } from "../../domains/people/commands/support-commands";
|
||||
import { USER_COMMAND_IDS } from "../../domains/people/commands/user-commands";
|
||||
import { SYSTEM_COMMAND_IDS } from "../../domains/system/commands/system-commands";
|
||||
import { anyCapability, ok } from "../contracts";
|
||||
@@ -72,6 +74,12 @@ describe("housekeeping command bootstrap", () => {
|
||||
expect(
|
||||
COMMUNITY_COMMAND_IDS.map((id) => getHousekeepingCommand(id)?.id),
|
||||
).toEqual(COMMUNITY_COMMAND_IDS);
|
||||
expect(
|
||||
SUPPORT_COMMAND_IDS.map((id) => getHousekeepingCommand(id)?.id),
|
||||
).toEqual(SUPPORT_COMMAND_IDS);
|
||||
expect(
|
||||
MODERATION_COMMAND_IDS.map((id) => getHousekeepingCommand(id)?.id),
|
||||
).toEqual(MODERATION_COMMAND_IDS);
|
||||
expect(() =>
|
||||
registerHousekeepingCommand({
|
||||
id: "system.bootstrap.too-late",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import "server-only";
|
||||
|
||||
import { COMMUNITY_COMMANDS } from "../../domains/people/commands/community-commands";
|
||||
import { MODERATION_COMMANDS } from "../../domains/people/commands/moderation-commands";
|
||||
import { SUPPORT_COMMANDS } from "../../domains/people/commands/support-commands";
|
||||
import { USER_COMMANDS } from "../../domains/people/commands/user-commands";
|
||||
import { SYSTEM_COMMANDS } from "../../domains/system/commands/system-commands";
|
||||
import type { HousekeepingCommand } from "./registry";
|
||||
@@ -40,6 +42,8 @@ export function registerHousekeepingCommands<
|
||||
const currentHousekeepingCommands = defineHousekeepingCommands(
|
||||
...USER_COMMANDS,
|
||||
...COMMUNITY_COMMANDS,
|
||||
...SUPPORT_COMMANDS,
|
||||
...MODERATION_COMMANDS,
|
||||
...SYSTEM_COMMANDS,
|
||||
);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { join, posix } from "node:path";
|
||||
import { createElement, type ReactElement } from "react";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { PEOPLE_PRIMARY_ROUTE_IDS } from "../domains/people/route-handlers";
|
||||
import { PEOPLE_ROUTE_IDS } from "../domains/people/routes";
|
||||
import { SYSTEM_ROUTE_IDS } from "../domains/system/routes";
|
||||
import { HOUSEKEEPING_MANIFESTS } from "../manifests";
|
||||
import { discoverLegacyPages } from "../migration/discover-legacy-pages";
|
||||
@@ -28,6 +28,14 @@ const approvedRuntimeImports = new Map<string, ReadonlySet<string>>([
|
||||
"src/features/housekeeping/domains/people/commands/user-commands.ts",
|
||||
new Set(["src/features/housekeeping/domains/people/services/mutations"]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/commands/support-commands.ts",
|
||||
new Set(["src/features/housekeeping/domains/people/services/mutations"]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/commands/moderation-commands.ts",
|
||||
new Set(["src/features/housekeeping/domains/people/services/mutations"]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/pages/community.tsx",
|
||||
new Set([
|
||||
@@ -75,6 +83,47 @@ const approvedRuntimeImports = new Map<string, ReadonlySet<string>>([
|
||||
"src/features/housekeeping/domains/people/queries/users",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/pages/support.tsx",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/pages/people-command-form",
|
||||
"src/features/housekeeping/domains/people/pages/page-state",
|
||||
"src/features/housekeeping/domains/people/queries/support",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/pages/ticket-detail.tsx",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/pages/people-command-form",
|
||||
"src/features/housekeeping/domains/people/pages/page-state",
|
||||
"src/features/housekeeping/domains/people/queries/support",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/pages/help-ticket-detail.tsx",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/models",
|
||||
"src/features/housekeeping/domains/people/pages/people-command-form",
|
||||
"src/features/housekeeping/domains/people/pages/page-state",
|
||||
"src/features/housekeeping/domains/people/queries/support",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/pages/moderation.tsx",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/pages/people-command-form",
|
||||
"src/features/housekeeping/domains/people/pages/page-state",
|
||||
"src/features/housekeeping/domains/people/queries/moderation",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/pages/cfh-detail.tsx",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/pages/people-command-form",
|
||||
"src/features/housekeeping/domains/people/pages/page-state",
|
||||
"src/features/housekeeping/domains/people/queries/moderation",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/pages/page-state.tsx",
|
||||
new Set(["src/features/housekeeping/domains/people/models"]),
|
||||
@@ -95,17 +144,50 @@ const approvedRuntimeImports = new Map<string, ReadonlySet<string>>([
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/manifest.ts",
|
||||
new Set(["src/features/housekeeping/domains/people/routes"]),
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/inbox",
|
||||
"src/features/housekeeping/domains/people/routes",
|
||||
"src/features/housekeeping/domains/people/search",
|
||||
"src/features/housekeeping/domains/people/widgets",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/search.ts",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/queries/community",
|
||||
"src/features/housekeeping/domains/people/queries/support",
|
||||
"src/features/housekeeping/domains/people/queries/users",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/inbox.ts",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/queries/moderation",
|
||||
"src/features/housekeeping/domains/people/queries/support",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/widgets.ts",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/models",
|
||||
"src/features/housekeeping/domains/people/queries/support",
|
||||
]),
|
||||
],
|
||||
[
|
||||
"src/features/housekeeping/domains/people/route-handlers.ts",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/pages/community",
|
||||
"src/features/housekeeping/domains/people/pages/cfh-detail",
|
||||
"src/features/housekeeping/domains/people/pages/help-ticket-detail",
|
||||
"src/features/housekeeping/domains/people/pages/moderation",
|
||||
"src/features/housekeeping/domains/people/pages/multi-accounts",
|
||||
"src/features/housekeeping/domains/people/pages/staff",
|
||||
"src/features/housekeeping/domains/people/pages/support",
|
||||
"src/features/housekeeping/domains/people/pages/ticket-detail",
|
||||
"src/features/housekeeping/domains/people/pages/user-detail",
|
||||
"src/features/housekeeping/domains/people/pages/user-edit",
|
||||
"src/features/housekeeping/domains/people/pages/users",
|
||||
"src/features/housekeeping/domains/people/routes",
|
||||
]),
|
||||
],
|
||||
[
|
||||
@@ -217,6 +299,8 @@ const approvedRuntimeImports = new Map<string, ReadonlySet<string>>([
|
||||
"src/features/housekeeping/foundation/commands/bootstrap.ts",
|
||||
new Set([
|
||||
"src/features/housekeeping/domains/people/commands/community-commands",
|
||||
"src/features/housekeeping/domains/people/commands/moderation-commands",
|
||||
"src/features/housekeeping/domains/people/commands/support-commands",
|
||||
"src/features/housekeeping/domains/people/commands/user-commands",
|
||||
"src/features/housekeeping/domains/system/commands/system-commands",
|
||||
]),
|
||||
@@ -838,7 +922,7 @@ describe("housekeeping foundation completion contracts", () => {
|
||||
registry.domains
|
||||
.find((domain) => domain.id === "people")
|
||||
?.routes.map((route) => route.id),
|
||||
).toEqual(PEOPLE_PRIMARY_ROUTE_IDS);
|
||||
).toEqual(PEOPLE_ROUTE_IDS);
|
||||
expect(
|
||||
registry.domains
|
||||
.find((domain) => domain.id === "system")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { PERMS } from "@/lib/permission-slugs";
|
||||
import { PEOPLE_PRIMARY_ROUTES } from "../domains/people/routes";
|
||||
import { PEOPLE_INBOX_SOURCES } from "../domains/people/inbox";
|
||||
import { PEOPLE_ROUTES } from "../domains/people/routes";
|
||||
import { PEOPLE_SEARCH_PROVIDERS } from "../domains/people/search";
|
||||
import { PEOPLE_WIDGETS } from "../domains/people/widgets";
|
||||
import { SYSTEM_ROUTES } from "../domains/system/routes";
|
||||
import { HOUSEKEEPING_MANIFESTS } from "../manifests";
|
||||
import { HOUSEKEEPING_MIGRATION_MATRIX } from "../migration/matrix";
|
||||
@@ -357,14 +360,20 @@ describe("housekeeping registry", () => {
|
||||
});
|
||||
expect(actual.routes).toEqual(
|
||||
expected.id === "people"
|
||||
? PEOPLE_PRIMARY_ROUTES
|
||||
? PEOPLE_ROUTES
|
||||
: expected.id === "system"
|
||||
? SYSTEM_ROUTES
|
||||
: [],
|
||||
);
|
||||
expect(actual.searchProviders).toEqual([]);
|
||||
expect(actual.inboxSources).toEqual([]);
|
||||
expect(actual.widgets).toEqual([]);
|
||||
expect(actual.searchProviders).toEqual(
|
||||
expected.id === "people" ? PEOPLE_SEARCH_PROVIDERS : [],
|
||||
);
|
||||
expect(actual.inboxSources).toEqual(
|
||||
expected.id === "people" ? PEOPLE_INBOX_SOURCES : [],
|
||||
);
|
||||
expect(actual.widgets).toEqual(
|
||||
expected.id === "people" ? PEOPLE_WIDGETS : [],
|
||||
);
|
||||
expect(actual.capability).toEqual({ mode: "any", slugs: expected.slugs });
|
||||
}
|
||||
});
|
||||
@@ -389,7 +398,7 @@ describe("housekeeping registry", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects duplicate provider and widget ids across domain manifests", () => {
|
||||
it("rejects duplicates within each provider kind across domain manifests", () => {
|
||||
expect(() =>
|
||||
createHousekeepingRegistry([
|
||||
{ ...manifest("people"), searchProviders: [searchProvider("shared")] },
|
||||
@@ -425,7 +434,7 @@ describe("housekeeping registry", () => {
|
||||
widgets: [widget("shared", "content")],
|
||||
},
|
||||
]),
|
||||
).toThrow("duplicate widget id: shared");
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it("rejects provider and widget ownership outside their manifest", () => {
|
||||
|
||||
@@ -24,7 +24,9 @@ export function createHousekeepingRegistry(
|
||||
const routeIds = new Set<string>();
|
||||
const routeHrefs = new Set<string>();
|
||||
const routeShapes = new Set<string>();
|
||||
const registryEntryIds = new Set<string>();
|
||||
const searchProviderIds = new Set<string>();
|
||||
const inboxSourceIds = new Set<string>();
|
||||
const widgetIds = new Set<string>();
|
||||
|
||||
for (const manifest of manifests) {
|
||||
if (!approvedDomainIds.has(manifest.id)) {
|
||||
@@ -48,19 +50,19 @@ export function createHousekeepingRegistry(
|
||||
manifest.searchProviders,
|
||||
manifest.id,
|
||||
"search provider",
|
||||
registryEntryIds,
|
||||
searchProviderIds,
|
||||
);
|
||||
validateOwnedRegistryEntries(
|
||||
manifest.inboxSources,
|
||||
manifest.id,
|
||||
"inbox source",
|
||||
registryEntryIds,
|
||||
inboxSourceIds,
|
||||
);
|
||||
validateOwnedRegistryEntries(
|
||||
manifest.widgets,
|
||||
manifest.id,
|
||||
"widget",
|
||||
registryEntryIds,
|
||||
widgetIds,
|
||||
);
|
||||
for (const widget of manifest.widgets) {
|
||||
if (widget.kind !== "mandatory" && widget.kind !== "optional") {
|
||||
|
||||
Reference in new issue
Block a user