@paneljs/paneljs 0.1.0 → 0.2.1

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/adapter.d.ts +10 -6
  3. package/dist/adminService.d.ts +49 -0
  4. package/dist/adminService.js +307 -0
  5. package/dist/adminService.js.map +1 -0
  6. package/dist/authStore.d.ts +31 -0
  7. package/dist/authStore.js +3 -0
  8. package/dist/authStore.js.map +1 -0
  9. package/dist/builtInAuth.d.ts +49 -0
  10. package/dist/builtInAuth.js +117 -0
  11. package/dist/builtInAuth.js.map +1 -0
  12. package/dist/cli/args.d.ts +2 -0
  13. package/dist/cli/args.js +16 -0
  14. package/dist/cli/args.js.map +1 -0
  15. package/dist/cli/auth.d.ts +7 -0
  16. package/dist/cli/auth.js +95 -0
  17. package/dist/cli/auth.js.map +1 -0
  18. package/dist/cli/init.d.ts +37 -0
  19. package/dist/cli/init.js +137 -0
  20. package/dist/cli/init.js.map +1 -0
  21. package/dist/cli/project.d.ts +31 -0
  22. package/dist/cli/project.js +150 -0
  23. package/dist/cli/project.js.map +1 -0
  24. package/dist/cli/prompt.d.ts +10 -0
  25. package/dist/cli/prompt.js +129 -0
  26. package/dist/cli/prompt.js.map +1 -0
  27. package/dist/cli/stack.d.ts +18 -0
  28. package/dist/cli/stack.js +129 -0
  29. package/dist/cli/stack.js.map +1 -0
  30. package/dist/cli.d.ts +2 -0
  31. package/dist/cli.js +53 -0
  32. package/dist/cli.js.map +1 -0
  33. package/dist/deleteRelations.d.ts +17 -0
  34. package/dist/deleteRelations.js +100 -0
  35. package/dist/deleteRelations.js.map +1 -0
  36. package/dist/index.d.ts +21 -7
  37. package/dist/index.js +25 -7
  38. package/dist/index.js.map +1 -1
  39. package/dist/listQuery.d.ts +6 -12
  40. package/dist/listQuery.js +10 -17
  41. package/dist/listQuery.js.map +1 -1
  42. package/dist/query.d.ts +65 -0
  43. package/dist/query.js +12 -0
  44. package/dist/query.js.map +1 -0
  45. package/dist/recordSelection.d.ts +3 -6
  46. package/dist/recordSelection.js +26 -20
  47. package/dist/recordSelection.js.map +1 -1
  48. package/dist/scope.d.ts +1 -1
  49. package/dist/types.d.ts +6 -1
  50. package/package.json +19 -10
  51. package/ui/dist/assets/index-BFz2MB0D.js +11 -0
  52. package/ui/dist/assets/index-B_bCMkti.css +1 -0
  53. package/ui/dist/index.html +2 -2
  54. package/ui/dist/assets/index-ChtweaBk.js +0 -11
  55. package/ui/dist/assets/index-eXfQCDXx.css +0 -1
@@ -0,0 +1,129 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { stdin, stdout } from "node:process";
3
+ export async function question(label) {
4
+ const terminal = createInterface({ input: stdin, output: stdout });
5
+ try {
6
+ return (await terminal.question(label)).trim();
7
+ }
8
+ finally {
9
+ terminal.close();
10
+ }
11
+ }
12
+ export async function confirm(label, defaultYes = true) {
13
+ const suffix = defaultYes ? " [Y/n]: " : " [y/N]: ";
14
+ const answer = (await question(`${label}${suffix}`)).toLowerCase();
15
+ if (!answer)
16
+ return defaultYes;
17
+ return answer === "y" || answer === "yes";
18
+ }
19
+ export async function hiddenQuestion(label) {
20
+ if (!stdin.isTTY)
21
+ throw new Error("Password input requires a terminal. Pass --password or set EXPRESS_ADMIN_PASSWORD for non-interactive use.");
22
+ stdout.write(label);
23
+ return new Promise((resolveQuestion, rejectQuestion) => {
24
+ let value = "";
25
+ const restore = () => {
26
+ stdin.setRawMode(false);
27
+ stdin.pause();
28
+ stdin.off("data", onData);
29
+ };
30
+ const onData = (chunk) => {
31
+ for (const character of chunk.toString("utf8")) {
32
+ if (character === "\r" || character === "\n") {
33
+ restore();
34
+ stdout.write("\n");
35
+ resolveQuestion(value);
36
+ return;
37
+ }
38
+ if (character === "\u0003") {
39
+ restore();
40
+ rejectQuestion(new Error("Cancelled."));
41
+ return;
42
+ }
43
+ if (character === "\b" || character === "\u007f") {
44
+ if (value) {
45
+ value = value.slice(0, -1);
46
+ stdout.write("\b \b");
47
+ }
48
+ continue;
49
+ }
50
+ value += character;
51
+ stdout.write("•");
52
+ }
53
+ };
54
+ stdin.setRawMode(true);
55
+ stdin.resume();
56
+ stdin.on("data", onData);
57
+ });
58
+ }
59
+ const dim = (text) => `\x1b[2m${text}\x1b[0m`;
60
+ export async function select(label, items) {
61
+ const enabled = items
62
+ .map((item, index) => ({ item, index }))
63
+ .filter(({ item }) => !item.disabled);
64
+ if (enabled.length === 0)
65
+ throw new Error(`No available options for ${label}`);
66
+ if (!stdin.isTTY || typeof stdin.setRawMode !== "function") {
67
+ throw new Error(`${label} requires a terminal, or pass the matching flag (--framework / --orm).`);
68
+ }
69
+ let current = enabled[0].index;
70
+ const render = (first) => {
71
+ if (!first)
72
+ stdout.write(`\x1b[${items.length}A`);
73
+ for (const [index, item] of items.entries()) {
74
+ const cursor = index === current ? "❯ " : " ";
75
+ const hint = item.disabled
76
+ ? dim(" (coming soon)")
77
+ : item.hint
78
+ ? dim(` ${item.hint}`)
79
+ : "";
80
+ const line = `${cursor}${item.label}${hint}`;
81
+ const painted = item.disabled ? dim(line) : line;
82
+ stdout.write(`\x1b[2K${painted}\n`);
83
+ }
84
+ };
85
+ stdout.write(`${label}\n`);
86
+ stdout.write("\x1b[?25l");
87
+ render(true);
88
+ return new Promise((resolveSelect, rejectSelect) => {
89
+ const restore = () => {
90
+ stdin.setRawMode(false);
91
+ stdin.pause();
92
+ stdin.off("data", onData);
93
+ stdout.write("\x1b[?25h");
94
+ };
95
+ const move = (direction) => {
96
+ const position = enabled.findIndex(({ index }) => index === current);
97
+ const next = enabled[(position + direction + enabled.length) % enabled.length];
98
+ current = next.index;
99
+ render(false);
100
+ };
101
+ const onData = (chunk) => {
102
+ const text = chunk.toString("utf8");
103
+ if (text === "\u0003") {
104
+ restore();
105
+ stdout.write("\n");
106
+ rejectSelect(new Error("Cancelled."));
107
+ return;
108
+ }
109
+ if (text === "\r" || text === "\n") {
110
+ restore();
111
+ stdout.write(`\x1b[${items.length}A`);
112
+ for (const [index, item] of items.entries()) {
113
+ const mark = index === current ? "❯ " : " ";
114
+ stdout.write(`\x1b[2K${mark}${item.label}\n`);
115
+ }
116
+ resolveSelect(items[current].value);
117
+ return;
118
+ }
119
+ if (text === "\u001b[A" || text === "k")
120
+ move(-1);
121
+ if (text === "\u001b[B" || text === "j")
122
+ move(1);
123
+ };
124
+ stdin.setRawMode(true);
125
+ stdin.resume();
126
+ stdin.on("data", onData);
127
+ });
128
+ }
129
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/cli/prompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export type FrameworkId = "express" | "fastify" | "nestjs";
2
+ export type OrmId = "prisma" | "typeorm" | "drizzle";
3
+ export type PackageManager = "npm" | "pnpm" | "yarn" | "bun";
4
+ export interface StackChoice<Id extends string> {
5
+ id: Id;
6
+ label: string;
7
+ available: boolean;
8
+ }
9
+ export declare const FRAMEWORKS: StackChoice<FrameworkId>[];
10
+ export declare const ORMS: StackChoice<OrmId>[];
11
+ export declare function parseFramework(value: string): FrameworkId;
12
+ export declare function parseOrm(value: string): OrmId;
13
+ export declare function assertAvailable(kind: "framework" | "ORM", choice: StackChoice<string>): void;
14
+ export declare function resolveFramework(id: FrameworkId): StackChoice<FrameworkId>;
15
+ export declare function resolveOrm(id: OrmId): StackChoice<OrmId>;
16
+ export declare function paneljsPackages(framework: FrameworkId, orm: OrmId): string[];
17
+ export declare function docsUrl(framework: FrameworkId, orm: OrmId): string;
18
+ export declare function setupSnippet(framework: FrameworkId, orm: OrmId): string;
@@ -0,0 +1,129 @@
1
+ export const FRAMEWORKS = [
2
+ { id: "express", label: "Express", available: true },
3
+ { id: "fastify", label: "Fastify", available: false },
4
+ { id: "nestjs", label: "Nest.js", available: false },
5
+ ];
6
+ export const ORMS = [
7
+ { id: "prisma", label: "Prisma", available: true },
8
+ { id: "typeorm", label: "TypeORM", available: true },
9
+ { id: "drizzle", label: "Drizzle", available: false },
10
+ ];
11
+ const FRAMEWORK_ALIASES = {
12
+ express: "express",
13
+ fastify: "fastify",
14
+ nest: "nestjs",
15
+ nestjs: "nestjs",
16
+ "nest.js": "nestjs",
17
+ };
18
+ const ORM_ALIASES = {
19
+ prisma: "prisma",
20
+ typeorm: "typeorm",
21
+ drizzle: "drizzle",
22
+ };
23
+ export function parseFramework(value) {
24
+ const id = FRAMEWORK_ALIASES[value.trim().toLowerCase()];
25
+ if (!id) {
26
+ throw new Error(`Unknown framework "${value}". Use express (fastify and nest.js are coming soon).`);
27
+ }
28
+ return id;
29
+ }
30
+ export function parseOrm(value) {
31
+ const id = ORM_ALIASES[value.trim().toLowerCase()];
32
+ if (!id) {
33
+ throw new Error(`Unknown ORM "${value}". Use prisma or typeorm (drizzle is coming soon).`);
34
+ }
35
+ return id;
36
+ }
37
+ export function assertAvailable(kind, choice) {
38
+ if (choice.available)
39
+ return;
40
+ const instead = kind === "framework"
41
+ ? "Express is the HTTP adapter that ships today."
42
+ : "Prisma and TypeORM are the data adapters that ship today.";
43
+ throw new Error(`${choice.label} is coming soon. ${instead}`);
44
+ }
45
+ export function resolveFramework(id) {
46
+ const choice = FRAMEWORKS.find((item) => item.id === id);
47
+ if (!choice)
48
+ throw new Error(`Unknown framework "${id}".`);
49
+ assertAvailable("framework", choice);
50
+ return choice;
51
+ }
52
+ export function resolveOrm(id) {
53
+ const choice = ORMS.find((item) => item.id === id);
54
+ if (!choice)
55
+ throw new Error(`Unknown ORM "${id}".`);
56
+ assertAvailable("ORM", choice);
57
+ return choice;
58
+ }
59
+ export function paneljsPackages(framework, orm) {
60
+ resolveFramework(framework);
61
+ resolveOrm(orm);
62
+ const http = framework === "express" ? "@paneljs/express" : `@paneljs/${framework}`;
63
+ const data = orm === "prisma" ? "@paneljs/prisma" : `@paneljs/${orm}`;
64
+ return ["paneljs", http, data];
65
+ }
66
+ export function docsUrl(framework, orm) {
67
+ return `https://www.paneljs.com/docs/guide/installation/${framework}/${orm}`;
68
+ }
69
+ export function setupSnippet(framework, orm) {
70
+ resolveFramework(framework);
71
+ resolveOrm(orm);
72
+ if (orm === "prisma") {
73
+ return `import express from "express";
74
+ import { createAdmin } from "paneljs";
75
+ import { prismaAdapter } from "@paneljs/prisma";
76
+ import { mount } from "@paneljs/express";
77
+ import { prisma } from "./prisma.js";
78
+
79
+ const app = express();
80
+
81
+ const admin = createAdmin({
82
+ adapter: prismaAdapter({ prisma }),
83
+ auth: {
84
+ getCurrentUser: async (req) => {
85
+ const user = await getOperatorFromYourAuth(req);
86
+ if (!user) return null;
87
+ return {
88
+ id: user.id,
89
+ email: user.email,
90
+ role: user.role,
91
+ isSuperAdmin: user.role === "SUPER_ADMIN",
92
+ };
93
+ },
94
+ },
95
+ });
96
+
97
+ admin.register("User");
98
+ await mount(app, admin);`;
99
+ }
100
+ return `import express from "express";
101
+ import { createAdmin } from "paneljs";
102
+ import { typeormAdapter } from "@paneljs/typeorm";
103
+ import { mount } from "@paneljs/express";
104
+ import { dataSource } from "./data-source.js";
105
+
106
+ await dataSource.initialize();
107
+
108
+ const app = express();
109
+
110
+ const admin = createAdmin({
111
+ adapter: typeormAdapter({ dataSource }),
112
+ auth: {
113
+ getCurrentUser: async (req) => {
114
+ const user = await getOperatorFromYourAuth(req);
115
+ if (!user) return null;
116
+ return {
117
+ id: user.id,
118
+ email: user.email,
119
+ role: user.role,
120
+ isSuperAdmin: user.role === "SUPER_ADMIN",
121
+ };
122
+ },
123
+ },
124
+ });
125
+
126
+ admin.register("User");
127
+ await mount(app, admin);`;
128
+ }
129
+ //# sourceMappingURL=stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack.js","sourceRoot":"","sources":["../../src/cli/stack.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ import { stdin, stdout } from "node:process";
3
+ import { argument } from "./cli/args.js";
4
+ import { authSchema, createSuperuser } from "./cli/auth.js";
5
+ import { createDefaultInstall, runInit } from "./cli/init.js";
6
+ import { confirm, select } from "./cli/prompt.js";
7
+ const usage = () => {
8
+ console.log(`Usage:
9
+ paneljs init [--framework express] [--orm prisma|typeorm] [--pm npm|pnpm|yarn|bun] [--yes] [--dry-run]
10
+ paneljs auth:schema --identifier <email|username>
11
+ paneljs createsuperuser --config ./paneljs.config.mjs [--email value] [--username value] [--password value]
12
+
13
+ init adds PanelJS packages to the current app. It does not rewrite source files.
14
+ auth:schema and createsuperuser are Prisma setup tools. TypeORM uses builtInAuthEntities() instead.
15
+
16
+ The createsuperuser config module must default-export { prisma, auth }, where auth is a built-in auth configuration.`);
17
+ };
18
+ const command = process.argv[2];
19
+ const argv = process.argv.slice(2);
20
+ try {
21
+ if (command === "init") {
22
+ await runInit({
23
+ cwd: process.cwd(),
24
+ argv: process.argv.slice(3),
25
+ io: {
26
+ stdout,
27
+ isTTY: Boolean(stdin.isTTY),
28
+ env: process.env,
29
+ select,
30
+ confirm: (label) => confirm(label, true),
31
+ install: createDefaultInstall(),
32
+ },
33
+ });
34
+ }
35
+ else if (command === "auth:schema") {
36
+ console.log(authSchema(argument(argv, "--identifier") ?? ""));
37
+ }
38
+ else if (command === "createsuperuser") {
39
+ await createSuperuser(argv);
40
+ }
41
+ else if (command === "--help" || command === "-h") {
42
+ usage();
43
+ }
44
+ else {
45
+ usage();
46
+ process.exitCode = command ? 1 : 0;
47
+ }
48
+ }
49
+ catch (error) {
50
+ console.error(error instanceof Error ? error.message : "Command failed.");
51
+ process.exitCode = 1;
52
+ }
53
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,KAAK,GAAG,GAAS,EAAE;IACvB,OAAO,CAAC,GAAG,CAAC;;;;;;;;qHAQuG,CAAC,CAAC;AACvH,CAAC,CAAC;AAEF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,CAAC;IACH,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,OAAO,CAAC;YACZ,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3B,EAAE,EAAE;gBACF,MAAM;gBACN,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;gBAC3B,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,MAAM;gBACN,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC;gBACxC,OAAO,EAAE,oBAAoB,EAAE;aAChC;SACF,CAAC,CAAC;IACL,CAAC;SAAM,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAChE,CAAC;SAAM,IAAI,OAAO,KAAK,iBAAiB,EAAE,CAAC;QACzC,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;SAAM,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpD,KAAK,EAAE,CAAC;IACV,CAAC;SAAM,CAAC;QACN,KAAK,EAAE,CAAC;QACR,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC1E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { DataAdapter } from "./adapter.js";
2
+ import type { FullRegisteredModel } from "./registry.js";
3
+ import type { AdminUser } from "./types.js";
4
+ export type DeleteReferentialAction = "Cascade" | "SetNull" | "Restrict";
5
+ export type DeletePreviewRelation = {
6
+ fieldName: string;
7
+ modelName: string;
8
+ pluralName: string;
9
+ idField: string;
10
+ displayField: string;
11
+ onDelete: DeleteReferentialAction;
12
+ recordsByParentId: Record<string, Record<string, unknown>[]>;
13
+ };
14
+ /** Related rows shown on a transport's delete confirmation page. */
15
+ export declare function loadDeletePreviewRelations(parent: FullRegisteredModel, models: Map<string, FullRegisteredModel>, adapter: DataAdapter, adminUser: AdminUser, ids: Array<string | number>): Promise<DeletePreviewRelation[]>;
16
+ /** Reject deletes that would violate Restrict / Protect relations. */
17
+ export declare function assertNoRestrictedRelations(parent: FullRegisteredModel, models: Map<string, FullRegisteredModel>, adapter: DataAdapter, adminUser: AdminUser, ids: Array<string | number>): Promise<void>;
@@ -0,0 +1,100 @@
1
+ import { buildListRecordSelect } from "./recordSelection.js";
2
+ import { hasModelPermission } from "./permissions.js";
3
+ import { withSelectFields } from "./query.js";
4
+ import { resolveScope } from "./scope.js";
5
+ import { RequestValidationError } from "./validation.js";
6
+ function referentialAction(onDelete) {
7
+ if (onDelete === "Cascade")
8
+ return "Cascade";
9
+ if (onDelete === "SetNull")
10
+ return "SetNull";
11
+ return "Restrict";
12
+ }
13
+ function findChildBelongsTo(parent, child, parentHasManyRelationName) {
14
+ return child.meta.fields.find((field) => {
15
+ const relation = field.relation;
16
+ return (field.type === "relation" &&
17
+ relation?.kind === "belongsTo" &&
18
+ relation.model === parent.meta.name &&
19
+ relation.foreignKeyFields.length === 1 &&
20
+ (relation.relationName === parentHasManyRelationName ||
21
+ field.name === parentHasManyRelationName));
22
+ });
23
+ }
24
+ function listChildRelations(parent, models) {
25
+ const modelsByName = new Map([...models.values()].map((entry) => [entry.meta.name, entry]));
26
+ const children = [];
27
+ for (const relationField of parent.meta.fields) {
28
+ const relation = relationField.relation;
29
+ if (relationField.type !== "relation" || relation?.kind !== "hasMany") {
30
+ continue;
31
+ }
32
+ const childModel = modelsByName.get(relation.model);
33
+ if (!childModel)
34
+ continue;
35
+ const childRelationField = findChildBelongsTo(parent, childModel, relation.relationName);
36
+ const foreignKey = childRelationField?.relation?.foreignKeyFields[0];
37
+ if (!childRelationField || !foreignKey)
38
+ continue;
39
+ children.push({
40
+ parentFieldName: relationField.name,
41
+ childModel,
42
+ foreignKey,
43
+ onDelete: referentialAction(childRelationField.relation?.onDelete),
44
+ });
45
+ }
46
+ return children;
47
+ }
48
+ /** Related rows shown on a transport's delete confirmation page. */
49
+ export async function loadDeletePreviewRelations(parent, models, adapter, adminUser, ids) {
50
+ const relations = [];
51
+ for (const child of listChildRelations(parent, models)) {
52
+ if (!hasModelPermission(adminUser, child.childModel.resolved.permissions, "list")) {
53
+ continue;
54
+ }
55
+ const childScope = await resolveScope(child.childModel.raw, adminUser);
56
+ const childSelect = withSelectFields(buildListRecordSelect(child.childModel.meta, child.childModel), [child.foreignKey]);
57
+ const childRecords = await adapter
58
+ .resource(child.childModel.meta)
59
+ .findMany({
60
+ scope: childScope,
61
+ filters: { [child.foreignKey]: { in: ids } },
62
+ select: childSelect,
63
+ });
64
+ const recordsByParentId = {};
65
+ for (const record of childRecords) {
66
+ const parentId = record[child.foreignKey];
67
+ if (typeof parentId !== "string" && typeof parentId !== "number") {
68
+ continue;
69
+ }
70
+ const key = String(parentId);
71
+ recordsByParentId[key] = [...(recordsByParentId[key] ?? []), record];
72
+ }
73
+ relations.push({
74
+ fieldName: child.parentFieldName,
75
+ modelName: child.childModel.meta.name,
76
+ pluralName: child.childModel.meta.pluralName,
77
+ idField: child.childModel.meta.idField,
78
+ displayField: child.childModel.meta.displayField,
79
+ onDelete: child.onDelete,
80
+ recordsByParentId,
81
+ });
82
+ }
83
+ return relations;
84
+ }
85
+ /** Reject deletes that would violate Restrict / Protect relations. */
86
+ export async function assertNoRestrictedRelations(parent, models, adapter, adminUser, ids) {
87
+ for (const child of listChildRelations(parent, models)) {
88
+ if (child.onDelete !== "Restrict")
89
+ continue;
90
+ const childScope = await resolveScope(child.childModel.raw, adminUser);
91
+ const count = await adapter.resource(child.childModel.meta).count({
92
+ scope: childScope,
93
+ filters: { [child.foreignKey]: { in: ids } },
94
+ });
95
+ if (count === 0)
96
+ continue;
97
+ throw new RequestValidationError(`Cannot delete this ${parent.meta.name} because related ${child.childModel.meta.name} records still reference it.`);
98
+ }
99
+ }
100
+ //# sourceMappingURL=deleteRelations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deleteRelations.js","sourceRoot":"","sources":["../src/deleteRelations.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,27 +1,41 @@
1
1
  import type { AdminConfig, ModelConfig } from "./types.js";
2
2
  import { AdminRegistry } from "./registry.js";
3
+ import { AdminService } from "./adminService.js";
3
4
  export interface Admin {
4
5
  register(modelName: string, modelConfig?: ModelConfig): Admin;
5
6
  initialize(): Promise<void>;
6
7
  readonly registry: AdminRegistry;
7
8
  readonly config: AdminConfig;
9
+ /** Available after initialize(); transports delegate admin operations here. */
10
+ readonly service: AdminService;
8
11
  }
9
12
  export declare function createAdmin(config: AdminConfig): Admin;
10
13
  export type { AdminConfig, ModelConfig, AdminUser, AuthConfig, BuiltInAuthConfig, ExternalAuthConfig, AdminHttpRequest, AuditConfig, AdminAuditEvent, AdminFieldMeta, AdminModelMeta, AdminFieldType, RelationKind, ModelPermissions, AdminAction, AdminFieldOverride, PaginatedResponse, SchemaResponse, } from "./types.js";
11
14
  export type { DataAdapter, ModelResource } from "./adapter.js";
15
+ export type { ActionWhere, CountQuery, CreateQuery, DeleteManyQuery, EqualityFilter, FieldFilter, FieldFilters, FieldSelect, FindFirstQuery, FindManyQuery, RelationSelect, SearchQuery, UpdateManyQuery, } from "./query.js";
16
+ export { idSelect, withSelectFields } from "./query.js";
12
17
  export type { ResolvedModelConfig, FullRegisteredModel } from "./registry.js";
13
18
  export { AdminRegistry } from "./registry.js";
14
- export { hashAdminPassword, verifyAdminPassword, verifyLoginPassword } from "./passwords.js";
15
- export { AdminApiError, AuthenticationError, PermissionDeniedError, ModelNotFoundError, RecordNotFoundError } from "./errors.js";
16
- export { RequestValidationError, isFieldVisible, isFieldWritable, isSensitiveFieldName, validateWritePayload, validateHookPayload, assertRequiredCreateFields } from "./validation.js";
17
- export { hasModelPermission, hasActionPermission, hasRegisteredActionPermission } from "./permissions.js";
19
+ export { AdminService, validateSelectedIds } from "./adminService.js";
20
+ export type { AdminListInput, AdminServiceOptions, DeletePreview, DeleteSelectedResult, } from "./adminService.js";
21
+ export { assertNoRestrictedRelations, loadDeletePreviewRelations, } from "./deleteRelations.js";
22
+ export type { DeletePreviewRelation, DeleteReferentialAction, } from "./deleteRelations.js";
23
+ export { hashAdminPassword, verifyAdminPassword, verifyLoginPassword, } from "./passwords.js";
24
+ export { AdminApiError, AuthenticationError, PermissionDeniedError, ModelNotFoundError, RecordNotFoundError, } from "./errors.js";
25
+ export { RequestValidationError, isFieldVisible, isFieldWritable, isSensitiveFieldName, validateWritePayload, validateHookPayload, assertRequiredCreateFields, } from "./validation.js";
26
+ export { hasModelPermission, hasActionPermission, hasRegisteredActionPermission, } from "./permissions.js";
18
27
  export type { AdminOperation } from "./permissions.js";
19
28
  export { DELETE_SELECTED_ACTION } from "./defaultActions.js";
20
29
  export { writeAuditEvent } from "./audit.js";
21
30
  export { buildSchemaResponse } from "./schema.js";
22
- export { parseListQuery, buildListWhere } from "./listQuery.js";
31
+ export { parseListQuery } from "./listQuery.js";
32
+ export type { ParsedListQuery } from "./listQuery.js";
23
33
  export { parseRecordId } from "./ids.js";
24
- export { buildRecordSelect, buildListRecordSelect, assertSelectedRelationsAreVisible } from "./recordSelection.js";
25
- export { applyCreateScope, assertScopeFieldsUnchanged, buildScopedRecordWhere, collectScopeFieldNames, resolveScope } from "./scope.js";
34
+ export { buildRecordSelect, buildListRecordSelect, assertSelectedRelationsAreVisible, } from "./recordSelection.js";
35
+ export { applyCreateScope, assertScopeFieldsUnchanged, buildScopedRecordWhere, collectScopeFieldNames, resolveScope, } from "./scope.js";
26
36
  export { getAdminUiDist } from "./uiPath.js";
27
37
  export { isBuiltInAuth } from "./authMode.js";
38
+ export type { AdminAuthStore, AuthStoreOptions, BuiltInSessionRecord, BuiltInUserRecord, } from "./authStore.js";
39
+ export { DEFAULT_AUTH_SESSION_MODEL, DEFAULT_AUTH_USER_MODEL, } from "./authStore.js";
40
+ export { SESSION_COOKIE_NAME, authenticateBuiltInRequest, authenticateSession, clearedSessionCookie, loginWithPassword, logoutBuiltIn, readSessionToken, resolveAuthStore, sessionCookie, } from "./builtInAuth.js";
41
+ export type { BuiltInLoginResult, BuiltInLogoutResult, SessionCookie, } from "./builtInAuth.js";
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  import { AdminRegistry } from "./registry.js";
2
+ import { AdminService } from "./adminService.js";
2
3
  export function createAdmin(config) {
3
4
  const registry = new AdminRegistry();
4
5
  let initialized = false;
6
+ let service;
5
7
  const admin = {
6
8
  register(modelName, modelConfig = {}) {
7
9
  registry.register(modelName, modelConfig);
@@ -12,6 +14,11 @@ export function createAdmin(config) {
12
14
  return;
13
15
  const models = await config.adapter.introspect();
14
16
  await registry.initialize(models);
17
+ service = new AdminService({
18
+ models: new Map(registry.getAll().map((model) => [model.meta.name, model])),
19
+ adapter: config.adapter,
20
+ audit: config.audit,
21
+ });
15
22
  initialized = true;
16
23
  },
17
24
  get registry() {
@@ -20,21 +27,32 @@ export function createAdmin(config) {
20
27
  get config() {
21
28
  return config;
22
29
  },
30
+ get service() {
31
+ if (!service) {
32
+ throw new Error("[paneljs] AdminService is unavailable before admin.initialize().");
33
+ }
34
+ return service;
35
+ },
23
36
  };
24
37
  return admin;
25
38
  }
39
+ export { idSelect, withSelectFields } from "./query.js";
26
40
  export { AdminRegistry } from "./registry.js";
27
- export { hashAdminPassword, verifyAdminPassword, verifyLoginPassword } from "./passwords.js";
28
- export { AdminApiError, AuthenticationError, PermissionDeniedError, ModelNotFoundError, RecordNotFoundError } from "./errors.js";
29
- export { RequestValidationError, isFieldVisible, isFieldWritable, isSensitiveFieldName, validateWritePayload, validateHookPayload, assertRequiredCreateFields } from "./validation.js";
30
- export { hasModelPermission, hasActionPermission, hasRegisteredActionPermission } from "./permissions.js";
41
+ export { AdminService, validateSelectedIds } from "./adminService.js";
42
+ export { assertNoRestrictedRelations, loadDeletePreviewRelations, } from "./deleteRelations.js";
43
+ export { hashAdminPassword, verifyAdminPassword, verifyLoginPassword, } from "./passwords.js";
44
+ export { AdminApiError, AuthenticationError, PermissionDeniedError, ModelNotFoundError, RecordNotFoundError, } from "./errors.js";
45
+ export { RequestValidationError, isFieldVisible, isFieldWritable, isSensitiveFieldName, validateWritePayload, validateHookPayload, assertRequiredCreateFields, } from "./validation.js";
46
+ export { hasModelPermission, hasActionPermission, hasRegisteredActionPermission, } from "./permissions.js";
31
47
  export { DELETE_SELECTED_ACTION } from "./defaultActions.js";
32
48
  export { writeAuditEvent } from "./audit.js";
33
49
  export { buildSchemaResponse } from "./schema.js";
34
- export { parseListQuery, buildListWhere } from "./listQuery.js";
50
+ export { parseListQuery } from "./listQuery.js";
35
51
  export { parseRecordId } from "./ids.js";
36
- export { buildRecordSelect, buildListRecordSelect, assertSelectedRelationsAreVisible } from "./recordSelection.js";
37
- export { applyCreateScope, assertScopeFieldsUnchanged, buildScopedRecordWhere, collectScopeFieldNames, resolveScope } from "./scope.js";
52
+ export { buildRecordSelect, buildListRecordSelect, assertSelectedRelationsAreVisible, } from "./recordSelection.js";
53
+ export { applyCreateScope, assertScopeFieldsUnchanged, buildScopedRecordWhere, collectScopeFieldNames, resolveScope, } from "./scope.js";
38
54
  export { getAdminUiDist } from "./uiPath.js";
39
55
  export { isBuiltInAuth } from "./authMode.js";
56
+ export { DEFAULT_AUTH_SESSION_MODEL, DEFAULT_AUTH_USER_MODEL, } from "./authStore.js";
57
+ export { SESSION_COOKIE_NAME, authenticateBuiltInRequest, authenticateSession, clearedSessionCookie, loginWithPassword, logoutBuiltIn, readSessionToken, resolveAuthStore, sessionCookie, } from "./builtInAuth.js";
40
58
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAS9C,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC5C,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;IACrC,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,MAAM,KAAK,GAAU;QAClB,QAAQ,CAAC,SAAiB,EAAE,cAA2B,EAAE;YACtD,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YAC1C,OAAO,KAAK,CAAC;QAChB,CAAC;QACD,KAAK,CAAC,UAAU;YACb,IAAI,WAAW;gBAAE,OAAO;YACxB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACjD,MAAM,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAClC,WAAW,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,IAAI,QAAQ;YACT,OAAO,QAAQ,CAAC;QACnB,CAAC;QACD,IAAI,MAAM;YACP,OAAO,MAAM,CAAC;QACjB,CAAC;KACH,CAAC;IAEF,OAAO,KAAK,CAAC;AAChB,CAAC;AAwBD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACjI,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,eAAe,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AACvL,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAE1G,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,iCAAiC,EAAE,MAAM,sBAAsB,CAAC;AACnH,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACxI,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,13 @@
1
1
  import type { FullRegisteredModel } from "./registry.js";
2
+ import type { FieldFilters, SearchQuery } from "./query.js";
2
3
  import type { AdminModelMeta } from "./types.js";
3
4
  export type QueryValue = string | string[] | undefined;
4
5
  export type QueryMap = Record<string, QueryValue>;
5
- export declare function buildListWhere(scope: Record<string, unknown>, filters: Record<string, unknown>, search: Record<string, unknown> | undefined): Record<string, unknown>;
6
- export declare function parseListQuery(query: QueryMap, meta: AdminModelMeta, model: FullRegisteredModel, databaseProvider?: string): {
6
+ export type ParsedListQuery = {
7
7
  page: number;
8
8
  sort: string;
9
- dir: string;
10
- filters: Record<string, unknown>;
11
- search: {
12
- OR: {
13
- [x: string]: {
14
- mode?: string | undefined;
15
- contains: string;
16
- };
17
- }[];
18
- } | undefined;
9
+ dir: "asc" | "desc";
10
+ filters: FieldFilters;
11
+ search?: SearchQuery;
19
12
  };
13
+ export declare function parseListQuery(query: QueryMap, meta: AdminModelMeta, model: FullRegisteredModel): ParsedListQuery;