opacacms 0.1.21 → 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.
- package/README.md +792 -50
- package/dist/admin/auth-client.d.ts +39 -39
- package/dist/admin/index.js +2360 -1392
- package/dist/admin/react.d.ts +1 -1
- package/dist/admin/react.js +8 -0
- package/dist/admin/router.d.ts +1 -0
- package/dist/admin/stores/ui.d.ts +10 -0
- package/dist/admin/ui/admin-layout.d.ts +4 -4
- package/dist/admin/ui/components/DataDetailView.d.ts +1 -1
- package/dist/admin/ui/components/DetailSheet.d.ts +19 -0
- package/dist/admin/ui/components/PluginSettingsForm.d.ts +11 -0
- package/dist/admin/ui/components/fields/BooleanField.d.ts +2 -1
- package/dist/admin/ui/components/fields/DateField.d.ts +1 -1
- package/dist/admin/ui/components/fields/FieldLabel.d.ts +11 -0
- package/dist/admin/ui/components/fields/FileField.d.ts +1 -1
- package/dist/admin/ui/components/fields/NumberField.d.ts +1 -1
- package/dist/admin/ui/components/fields/RadioField.d.ts +1 -1
- package/dist/admin/ui/components/fields/RelationshipField.d.ts +3 -1
- package/dist/admin/ui/components/fields/SelectField.d.ts +1 -1
- package/dist/admin/ui/components/fields/TextAreaField.d.ts +1 -1
- package/dist/admin/ui/components/fields/TextField.d.ts +1 -1
- package/dist/admin/ui/components/fields/VirtualField.d.ts +1 -0
- package/dist/admin/ui/components/fields/index.d.ts +16 -16
- package/dist/admin/ui/components/fields/richtext-editor/index.d.ts +1 -1
- package/dist/admin/ui/components/media/AssetManagerModal.d.ts +1 -1
- package/dist/admin/ui/components/toast.d.ts +1 -1
- package/dist/admin/ui/components/ui/accordion.d.ts +1 -1
- package/dist/admin/ui/components/ui/button.d.ts +1 -1
- package/dist/admin/ui/components/ui/collapsible.d.ts +1 -1
- package/dist/admin/ui/components/ui/dialog.d.ts +1 -1
- package/dist/admin/ui/components/ui/group.d.ts +1 -1
- package/dist/admin/ui/components/ui/index.d.ts +17 -17
- package/dist/admin/ui/components/ui/input.d.ts +1 -1
- package/dist/admin/ui/components/ui/label.d.ts +1 -1
- package/dist/admin/ui/components/ui/radio-group.d.ts +1 -1
- package/dist/admin/ui/components/ui/relationship.d.ts +4 -4
- package/dist/admin/ui/components/ui/select.d.ts +1 -1
- package/dist/admin/ui/components/ui/sheet.d.ts +1 -1
- package/dist/admin/ui/components/ui/tabs.d.ts +1 -1
- package/dist/admin/ui/components/versions-sheet.d.ts +11 -0
- package/dist/admin/ui/views/media-registry-view.d.ts +1 -1
- package/dist/admin/ui/views/settings-view.d.ts +2 -2
- package/dist/admin/vue.js +8 -0
- package/dist/admin/webcomponent.js +20 -2
- package/dist/admin.css +1 -1
- package/dist/auth/index.d.ts +101 -41
- package/dist/{chunk-fqastxq9.js → chunk-06ks4ggh.js} +133 -44
- package/dist/{chunk-xrfhhz85.js → chunk-2es275xs.js} +480 -85
- package/dist/{chunk-v521d72w.js → chunk-3rdhbedb.js} +1 -1
- package/dist/chunk-51z3x7kq.js +20 -0
- package/dist/{chunk-7fyepksb.js → chunk-526a3gqx.js} +1 -1
- package/dist/{chunk-0sdceeys.js → chunk-6d1vdfwa.js} +121 -31
- package/dist/{chunk-wmvjvn7b.js → chunk-6qq3ne6b.js} +39 -1
- package/dist/{chunk-0am1m47g.js → chunk-6v1fw7q7.js} +5 -5
- package/dist/{chunk-t9v845m2.js → chunk-7y1nbmw6.js} +34 -3
- package/dist/chunk-8scgdznr.js +44 -0
- package/dist/{chunk-mycmsjd9.js → chunk-b3kr8w41.js} +57 -6
- package/dist/chunk-bexcv7xe.js +36 -0
- package/dist/{chunk-ekxkvqjm.js → chunk-bygjkgrx.js} +124 -34
- package/dist/{chunk-16vgcf3k.js → chunk-byq8g0rd.js} +1 -1
- package/dist/{chunk-cpw2y3pn.js → chunk-dykn5hr6.js} +7 -7
- package/dist/chunk-fj19qccp.js +78 -0
- package/dist/{chunk-n1xraw7j.js → chunk-g1jb60xd.js} +1 -1
- package/dist/{chunk-xa7rjsn2.js → chunk-j53pz21t.js} +2 -2
- package/dist/{chunk-nb7ctdg8.js → chunk-jdfw4v3r.js} +1 -1
- package/dist/chunk-mkn49zmy.js +102 -0
- package/dist/{chunk-59sg3pw9.js → chunk-n133qpsm.js} +128 -34
- package/dist/{chunk-2kyhqvhc.js → chunk-qxt9vge8.js} +1 -1
- package/dist/chunk-r39em4yj.js +29 -0
- package/dist/chunk-rqyjjqgy.js +91 -0
- package/dist/chunk-rsf0tpy1.js +8 -0
- package/dist/chunk-t0zg026p.js +71 -0
- package/dist/{chunk-61kwqve4.js → chunk-tfnaf41w.js} +118 -37
- package/dist/chunk-twpvxfce.js +64 -0
- package/dist/{chunk-ybbbqj63.js → chunk-v9z61v3g.js} +15 -0
- package/dist/{chunk-jwjk85ze.js → chunk-ywm4t2gm.js} +6 -2
- package/dist/cli/commands/plugin-build.d.ts +1 -0
- package/dist/cli/commands/plugin-init.d.ts +1 -0
- package/dist/cli/commands/plugin-sync.d.ts +1 -0
- package/dist/cli/index.js +24 -6
- package/dist/config-utils.d.ts +1 -1
- package/dist/config.d.ts +21 -4
- package/dist/db/adapter.d.ts +2 -2
- package/dist/db/better-sqlite.d.ts +2 -1
- package/dist/db/better-sqlite.js +5 -5
- package/dist/db/bun-sqlite.d.ts +2 -1
- package/dist/db/bun-sqlite.js +5 -5
- package/dist/db/d1.d.ts +1 -1
- package/dist/db/d1.js +5 -5
- package/dist/db/index.js +9 -9
- package/dist/db/postgres.d.ts +3 -3
- package/dist/db/postgres.js +5 -5
- package/dist/db/sqlite.d.ts +2 -1
- package/dist/db/sqlite.js +5 -5
- package/dist/index.js +4 -3
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/ui-bridge.d.ts +12 -0
- package/dist/plugins/utils.d.ts +5 -0
- package/dist/runtimes/bun.js +13 -7
- package/dist/runtimes/cloudflare-workers.js +5 -5
- package/dist/runtimes/next.js +5 -5
- package/dist/runtimes/node.js +13 -7
- package/dist/schema/collection.d.ts +9 -26
- package/dist/schema/fields/base.d.ts +3 -2
- package/dist/schema/fields/index.d.ts +12 -0
- package/dist/schema/fields/validation.test.d.ts +1 -0
- package/dist/schema/global.d.ts +10 -7
- package/dist/schema/index.js +22 -6
- package/dist/server/admin-router.d.ts +2 -2
- package/dist/server/admin.d.ts +2 -1
- package/dist/server/collection-router.d.ts +1 -1
- package/dist/server/handlers.d.ts +10 -0
- package/dist/server/middlewares/admin.d.ts +2 -2
- package/dist/server/middlewares/auth.d.ts +1 -1
- package/dist/server/middlewares/context.d.ts +2 -0
- package/dist/server/middlewares/rate-limit.d.ts +1 -1
- package/dist/server/openapi.d.ts +2 -0
- package/dist/server/plugins-loader.d.ts +6 -0
- package/dist/server/router.d.ts +3 -3
- package/dist/server/routers/admin.d.ts +2 -2
- package/dist/server/routers/auth.d.ts +1 -1
- package/dist/server/routers/collections.d.ts +1 -1
- package/dist/server/routers/plugins.d.ts +18 -0
- package/dist/server/setup-middlewares.d.ts +2 -2
- package/dist/server/system-router.d.ts +1 -1
- package/dist/server.js +11 -7
- package/dist/storage/adapters/local.d.ts +1 -1
- package/dist/storage/adapters/s3.d.ts +1 -1
- package/dist/storage/index.js +34 -25
- package/dist/types.d.ts +224 -17
- package/dist/utils/logger.d.ts +13 -35
- package/dist/validation.d.ts +40 -0
- package/dist/validator.d.ts +1 -1
- package/package.json +41 -27
- package/dist/admin/ui/components/DataDetailSheet.d.ts +0 -13
- package/dist/admin/ui/components/ui/relationship-detail-sheet.d.ts +0 -9
- package/dist/chunk-62ev8gnc.js +0 -41
- package/dist/chunk-j4d50hrx.js +0 -20
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import type { Auth } from "../../auth";
|
|
3
3
|
import type { OpacaConfig } from "../../types";
|
|
4
|
-
import type { ApiContextVariables } from "
|
|
4
|
+
import type { ApiContextVariables } from "../../server/router";
|
|
5
5
|
export declare function createAuthRouter(config: OpacaConfig, state: {
|
|
6
6
|
auth: Auth | undefined;
|
|
7
7
|
}): Hono<{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import type { Auth } from "../../auth";
|
|
3
3
|
import type { OpacaConfig } from "../../types";
|
|
4
|
-
import type { ApiContextVariables } from "
|
|
4
|
+
import type { ApiContextVariables } from "../../server/router";
|
|
5
5
|
export declare function mountCollectionRoutes(router: Hono<{
|
|
6
6
|
Variables: ApiContextVariables;
|
|
7
7
|
}>, config: OpacaConfig, state: {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Hono } from "hono";
|
|
2
|
+
import type { OpacaConfig } from "../../types";
|
|
3
|
+
import type { ApiContextVariables } from "../setup-middlewares";
|
|
4
|
+
/**
|
|
5
|
+
* Mounts all plugin-specific routes and middlewares.
|
|
6
|
+
*
|
|
7
|
+
* @param config - The OpacaCMS configuration.
|
|
8
|
+
* @param settings - The loaded plugin settings.
|
|
9
|
+
* @param logger - The system logger.
|
|
10
|
+
* @param router - The Hono router instance.
|
|
11
|
+
*/
|
|
12
|
+
export declare function mountPluginRoutes(config: OpacaConfig, settings: Record<string, any>, logger: typeof import("../../utils/logger").logger, router: Hono<{
|
|
13
|
+
Variables: ApiContextVariables;
|
|
14
|
+
}>): void;
|
|
15
|
+
/**
|
|
16
|
+
* Fires the onInitComplete hook for all plugins.
|
|
17
|
+
*/
|
|
18
|
+
export declare function firePluginInitComplete(config: OpacaConfig, settings: Record<string, any>, logger: typeof import("../../utils/logger").logger): void;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Hono } from "hono";
|
|
2
2
|
import type { Auth } from "../auth";
|
|
3
3
|
import type { OpacaConfig } from "../types";
|
|
4
|
-
import { type AuthContextVariables } from "
|
|
5
|
-
import { type OpacaContextVariables } from "
|
|
4
|
+
import { type AuthContextVariables } from "../server/middlewares/auth";
|
|
5
|
+
import { type OpacaContextVariables } from "../server/middlewares/context";
|
|
6
6
|
export type ApiContextVariables = OpacaContextVariables & AuthContextVariables;
|
|
7
7
|
export declare function setupMiddlewares(router: Hono<{
|
|
8
8
|
Variables: ApiContextVariables;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import type { OpacaConfig } from "../types";
|
|
3
|
-
import type { ApiContextVariables } from "
|
|
3
|
+
import type { ApiContextVariables } from "../server/router";
|
|
4
4
|
export declare function createSystemRouter(config: OpacaConfig): Hono<{
|
|
5
5
|
Variables: ApiContextVariables;
|
|
6
6
|
}, import("hono/types").BlankSchema, "/">;
|
package/dist/server.js
CHANGED
|
@@ -3,20 +3,24 @@ import {
|
|
|
3
3
|
createAdminHandlers,
|
|
4
4
|
createGlobalHandlers,
|
|
5
5
|
createHandlers,
|
|
6
|
-
hydrateDoc
|
|
7
|
-
|
|
6
|
+
hydrateDoc,
|
|
7
|
+
parsePopulate,
|
|
8
|
+
populateDoc
|
|
9
|
+
} from "./chunk-2es275xs.js";
|
|
8
10
|
import {
|
|
9
11
|
defineConfig
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import"./chunk-
|
|
12
|
+
} from "./chunk-7y1nbmw6.js";
|
|
13
|
+
import"./chunk-b3kr8w41.js";
|
|
12
14
|
import {
|
|
13
15
|
BaseDatabaseAdapter
|
|
14
16
|
} from "./chunk-s8mqwnm1.js";
|
|
15
|
-
import"./chunk-
|
|
16
|
-
import"./chunk-
|
|
17
|
-
import"./chunk-
|
|
17
|
+
import"./chunk-qxt9vge8.js";
|
|
18
|
+
import"./chunk-v9z61v3g.js";
|
|
19
|
+
import"./chunk-t0zg026p.js";
|
|
18
20
|
import"./chunk-8sqjbsgt.js";
|
|
19
21
|
export {
|
|
22
|
+
populateDoc,
|
|
23
|
+
parsePopulate,
|
|
20
24
|
hydrateDoc,
|
|
21
25
|
defineConfig,
|
|
22
26
|
createHandlers,
|
package/dist/storage/index.js
CHANGED
|
@@ -219,21 +219,25 @@ function createLocalAdapter(config) {
|
|
|
219
219
|
};
|
|
220
220
|
}
|
|
221
221
|
// src/storage/adapters/s3.ts
|
|
222
|
-
import {
|
|
223
|
-
DeleteObjectCommand,
|
|
224
|
-
GetObjectCommand,
|
|
225
|
-
HeadObjectCommand,
|
|
226
|
-
PutObjectCommand,
|
|
227
|
-
S3Client
|
|
228
|
-
} from "@aws-sdk/client-s3";
|
|
229
|
-
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
230
222
|
function createS3Adapter(config) {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
223
|
+
let _s3Client = null;
|
|
224
|
+
let _sdk = null;
|
|
225
|
+
const getSdk = async () => {
|
|
226
|
+
if (_sdk)
|
|
227
|
+
return _sdk;
|
|
228
|
+
const [clientS3, presigner] = await Promise.all([
|
|
229
|
+
import("@aws-sdk/client-s3"),
|
|
230
|
+
import("@aws-sdk/s3-request-presigner")
|
|
231
|
+
]);
|
|
232
|
+
_sdk = { ...clientS3, ...presigner };
|
|
233
|
+
_s3Client = new _sdk.S3Client({
|
|
234
|
+
region: config.region,
|
|
235
|
+
endpoint: config.endpoint,
|
|
236
|
+
credentials: config.credentials,
|
|
237
|
+
forcePathStyle: config.forcePathStyle
|
|
238
|
+
});
|
|
239
|
+
return _sdk;
|
|
240
|
+
};
|
|
237
241
|
const getFullKey = (filename) => {
|
|
238
242
|
if (config.prefix) {
|
|
239
243
|
const p = config.prefix.replace(/\/$/, "");
|
|
@@ -252,6 +256,7 @@ function createS3Adapter(config) {
|
|
|
252
256
|
name: "s3",
|
|
253
257
|
async upload(file, options) {
|
|
254
258
|
try {
|
|
259
|
+
const sdk = await getSdk();
|
|
255
260
|
if (options?.allowedmime_types && !options.allowedmime_types.includes(file.mime_type)) {
|
|
256
261
|
throw new Invalidmime_typeError("s3", options.allowedmime_types, file.mime_type);
|
|
257
262
|
}
|
|
@@ -267,7 +272,7 @@ function createS3Adapter(config) {
|
|
|
267
272
|
}
|
|
268
273
|
const key = getFullKey(finalFilename);
|
|
269
274
|
const body = file.buffer || file.stream;
|
|
270
|
-
const command = new PutObjectCommand({
|
|
275
|
+
const command = new sdk.PutObjectCommand({
|
|
271
276
|
Bucket: config.bucket,
|
|
272
277
|
Key: key,
|
|
273
278
|
Body: body,
|
|
@@ -275,7 +280,7 @@ function createS3Adapter(config) {
|
|
|
275
280
|
ContentLength: file.filesize,
|
|
276
281
|
ACL: config.acl || "private"
|
|
277
282
|
});
|
|
278
|
-
await
|
|
283
|
+
await _s3Client.send(command);
|
|
279
284
|
return {
|
|
280
285
|
filename: finalFilename,
|
|
281
286
|
mime_type: file.mime_type,
|
|
@@ -290,22 +295,24 @@ function createS3Adapter(config) {
|
|
|
290
295
|
},
|
|
291
296
|
async delete(filename) {
|
|
292
297
|
try {
|
|
293
|
-
const
|
|
298
|
+
const sdk = await getSdk();
|
|
299
|
+
const command = new sdk.DeleteObjectCommand({
|
|
294
300
|
Bucket: config.bucket,
|
|
295
301
|
Key: getFullKey(filename)
|
|
296
302
|
});
|
|
297
|
-
await
|
|
303
|
+
await _s3Client.send(command);
|
|
298
304
|
} catch (error) {
|
|
299
305
|
throw new StorageError("s3", "delete", `Failed to delete ${filename} from S3 bucket ${config.bucket}`, error);
|
|
300
306
|
}
|
|
301
307
|
},
|
|
302
308
|
async exists(filename) {
|
|
303
309
|
try {
|
|
304
|
-
const
|
|
310
|
+
const sdk = await getSdk();
|
|
311
|
+
const command = new sdk.HeadObjectCommand({
|
|
305
312
|
Bucket: config.bucket,
|
|
306
313
|
Key: getFullKey(filename)
|
|
307
314
|
});
|
|
308
|
-
await
|
|
315
|
+
await _s3Client.send(command);
|
|
309
316
|
return true;
|
|
310
317
|
} catch (error) {
|
|
311
318
|
if (error.name === "NotFound" || error.$metadata?.httpStatusCode === 404)
|
|
@@ -315,24 +322,26 @@ function createS3Adapter(config) {
|
|
|
315
322
|
},
|
|
316
323
|
async generatePresignedUrl(filename, operation, expiresInSeconds = 3600) {
|
|
317
324
|
try {
|
|
325
|
+
const sdk = await getSdk();
|
|
318
326
|
let command;
|
|
319
327
|
if (operation === "write") {
|
|
320
|
-
command = new PutObjectCommand({ Bucket: config.bucket, Key: getFullKey(filename) });
|
|
328
|
+
command = new sdk.PutObjectCommand({ Bucket: config.bucket, Key: getFullKey(filename) });
|
|
321
329
|
} else {
|
|
322
|
-
command = new GetObjectCommand({ Bucket: config.bucket, Key: getFullKey(filename) });
|
|
330
|
+
command = new sdk.GetObjectCommand({ Bucket: config.bucket, Key: getFullKey(filename) });
|
|
323
331
|
}
|
|
324
|
-
return await getSignedUrl(
|
|
332
|
+
return await sdk.getSignedUrl(_s3Client, command, { expiresIn: expiresInSeconds });
|
|
325
333
|
} catch (error) {
|
|
326
334
|
throw new StorageError("s3", "presign", `Failed to generate presigned URL for ${filename}`, error);
|
|
327
335
|
}
|
|
328
336
|
},
|
|
329
337
|
async download(filename) {
|
|
330
338
|
try {
|
|
331
|
-
const
|
|
339
|
+
const sdk = await getSdk();
|
|
340
|
+
const command = new sdk.GetObjectCommand({
|
|
332
341
|
Bucket: config.bucket,
|
|
333
342
|
Key: getFullKey(filename)
|
|
334
343
|
});
|
|
335
|
-
const response = await
|
|
344
|
+
const response = await _s3Client.send(command);
|
|
336
345
|
if (!response.Body) {
|
|
337
346
|
throw new StorageError("s3", "download", `File not found: ${filename}`);
|
|
338
347
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { Session as BetterAuthSession, User as BetterAuthUser, Prettify } from "better-auth";
|
|
2
3
|
import type { Context } from "hono";
|
|
3
4
|
import type { icons } from "lucide-react";
|
|
4
|
-
import type { AdminConfig, CollectionHooks, FieldType, AccessConfig as ValidationAccessConfig
|
|
5
|
+
import type { AdminConfig, CollectionHooks, FieldType, AccessConfig as ValidationAccessConfig } from "./validation";
|
|
5
6
|
export type { FieldType };
|
|
7
|
+
export type Session = BetterAuthSession;
|
|
8
|
+
export type User = Prettify<BetterAuthUser & {
|
|
9
|
+
role?: string;
|
|
10
|
+
banned?: boolean;
|
|
11
|
+
banReason?: string | null;
|
|
12
|
+
bannedUntil?: Date | null;
|
|
13
|
+
}>;
|
|
6
14
|
export type IconName = keyof typeof icons;
|
|
7
15
|
export interface BaseField {
|
|
8
16
|
name: string;
|
|
@@ -12,7 +20,7 @@ export interface BaseField {
|
|
|
12
20
|
unique?: boolean;
|
|
13
21
|
localized?: boolean;
|
|
14
22
|
defaultValue?: unknown;
|
|
15
|
-
validate?: (value: unknown) => boolean | string;
|
|
23
|
+
validate?: ((value: unknown) => boolean | string) | z.ZodTypeAny;
|
|
16
24
|
access?: FieldAccessConfig;
|
|
17
25
|
admin?: {
|
|
18
26
|
description?: string;
|
|
@@ -26,6 +34,7 @@ export interface BaseField {
|
|
|
26
34
|
Field?: string;
|
|
27
35
|
Cell?: string;
|
|
28
36
|
};
|
|
37
|
+
customProps?: Record<string, unknown>;
|
|
29
38
|
};
|
|
30
39
|
references?: {
|
|
31
40
|
table: string;
|
|
@@ -167,7 +176,10 @@ export interface VirtualField extends BaseField {
|
|
|
167
176
|
}) => any | Promise<any>;
|
|
168
177
|
returnType?: "string" | "number" | "boolean" | "json";
|
|
169
178
|
}
|
|
170
|
-
export
|
|
179
|
+
export interface UIField extends BaseField {
|
|
180
|
+
type: "ui";
|
|
181
|
+
}
|
|
182
|
+
export type Field = TextField | SlugField | TextAreaField | NumberField | RichTextField | RelationshipField | SelectField | VirtualField | RadioField | DateField | BooleanField | JSONField | FileField | BlocksField | GroupField | RowField | CollapsibleField | TabsField | JoinField | ArrayField | UIField;
|
|
171
183
|
export interface ApiKey {
|
|
172
184
|
id: string;
|
|
173
185
|
name: string | null;
|
|
@@ -197,18 +209,20 @@ export interface AccessConfig extends Omit<ValidationAccessConfig, "read" | "cre
|
|
|
197
209
|
delete?: boolean | ((args: AccessArgs) => boolean | Promise<boolean>);
|
|
198
210
|
}
|
|
199
211
|
export type { CollectionHooks };
|
|
200
|
-
export interface Collection
|
|
201
|
-
|
|
212
|
+
export interface Collection {
|
|
213
|
+
slug: string;
|
|
214
|
+
label?: string;
|
|
215
|
+
icon?: IconName;
|
|
202
216
|
apiPath?: string;
|
|
217
|
+
fields: Field[];
|
|
203
218
|
hooks?: CollectionHooks;
|
|
204
219
|
access?: AccessConfig;
|
|
205
|
-
icon?: IconName;
|
|
206
220
|
versions?: {
|
|
207
221
|
drafts?: boolean;
|
|
208
222
|
maxRevisions?: number;
|
|
209
223
|
autosave?: boolean;
|
|
210
224
|
};
|
|
211
|
-
timestamps
|
|
225
|
+
timestamps?: boolean | {
|
|
212
226
|
createdAt?: string;
|
|
213
227
|
updatedAt?: string;
|
|
214
228
|
};
|
|
@@ -217,11 +231,23 @@ export interface Collection extends Omit<ValidationCollection, "fields" | "hooks
|
|
|
217
231
|
url: string;
|
|
218
232
|
headers?: Record<string, string>;
|
|
219
233
|
}[];
|
|
234
|
+
auth?: boolean;
|
|
220
235
|
admin?: {
|
|
221
|
-
|
|
236
|
+
/**
|
|
237
|
+
* If true, the collection's title will be used as a breadcrumb.
|
|
238
|
+
*/
|
|
222
239
|
useAsTitle?: string;
|
|
240
|
+
/**
|
|
241
|
+
* If true, the collection will be hidden from the Admin UI sidebar but still accessible via direct URL.
|
|
242
|
+
*/
|
|
223
243
|
hidden?: boolean;
|
|
244
|
+
/**
|
|
245
|
+
* If true, the collection will be completely disabled from the Admin UI (hidden from sidebar and blocked via direct URL).
|
|
246
|
+
*/
|
|
224
247
|
disableAdmin?: boolean;
|
|
248
|
+
/**
|
|
249
|
+
* Predefined filtered views for the collection list.
|
|
250
|
+
*/
|
|
225
251
|
views?: {
|
|
226
252
|
name: string;
|
|
227
253
|
filter: Record<string, any>;
|
|
@@ -235,21 +261,121 @@ export interface Collection extends Omit<ValidationCollection, "fields" | "hooks
|
|
|
235
261
|
}) => Promise<unknown>;
|
|
236
262
|
}[];
|
|
237
263
|
} | boolean;
|
|
264
|
+
hidden?: boolean;
|
|
238
265
|
}
|
|
239
|
-
export interface Global
|
|
266
|
+
export interface Global {
|
|
267
|
+
slug: string;
|
|
240
268
|
fields: Field[];
|
|
241
269
|
access?: AccessConfig;
|
|
242
270
|
label?: string;
|
|
243
271
|
icon?: IconName;
|
|
244
|
-
timestamps
|
|
272
|
+
timestamps?: boolean | {
|
|
245
273
|
createdAt?: string;
|
|
246
274
|
updatedAt?: string;
|
|
247
275
|
};
|
|
248
276
|
}
|
|
249
|
-
export interface
|
|
277
|
+
export interface OpacaPluginContext {
|
|
278
|
+
config: OpacaConfig;
|
|
279
|
+
logger: typeof import("./utils/logger").logger;
|
|
280
|
+
settings?: Record<string, any>;
|
|
281
|
+
}
|
|
282
|
+
export interface OpacaPlugin {
|
|
283
|
+
/**
|
|
284
|
+
* Unique name/slug for the plugin (e.g. 'stripe')
|
|
285
|
+
*/
|
|
286
|
+
name: string;
|
|
287
|
+
/**
|
|
288
|
+
* User-friendly label for the plugin
|
|
289
|
+
*/
|
|
290
|
+
label?: string;
|
|
291
|
+
/**
|
|
292
|
+
* Short description of what the plugin does
|
|
293
|
+
*/
|
|
294
|
+
description?: string;
|
|
295
|
+
/**
|
|
296
|
+
* Plugin version (e.g. '1.0.0')
|
|
297
|
+
*/
|
|
298
|
+
version?: string;
|
|
299
|
+
/**
|
|
300
|
+
* Plugin author
|
|
301
|
+
*/
|
|
302
|
+
author?: string;
|
|
303
|
+
/**
|
|
304
|
+
* Link to plugin documentation or homepage
|
|
305
|
+
*/
|
|
306
|
+
homepage?: string;
|
|
307
|
+
/**
|
|
308
|
+
* Lucide icon name for the plugin
|
|
309
|
+
*/
|
|
310
|
+
icon?: IconName;
|
|
311
|
+
/**
|
|
312
|
+
* Callback fired during OpacaCMS initialization.
|
|
313
|
+
* Use this to extend the schema (collections, globals).
|
|
314
|
+
*/
|
|
315
|
+
onInit?: (context: OpacaPluginContext) => OpacaConfig | void;
|
|
316
|
+
/**
|
|
317
|
+
* Callback fired when the Hono router is initialized.
|
|
318
|
+
* Use this to add custom API routes.
|
|
319
|
+
*/
|
|
320
|
+
onRouterInit?: (app: import("hono").Hono<any, any, any>, context: OpacaPluginContext) => void;
|
|
321
|
+
/**
|
|
322
|
+
* Callback fired after all plugins have been initialized.
|
|
323
|
+
*/
|
|
324
|
+
onInitComplete?: (context: OpacaPluginContext) => void | Promise<void>;
|
|
325
|
+
/**
|
|
326
|
+
* Hook called on every CMS API request.
|
|
327
|
+
* Return false to block the request.
|
|
328
|
+
*/
|
|
329
|
+
onRequest?: (c: import("hono").Context) => void | false | Promise<void | false>;
|
|
330
|
+
/**
|
|
331
|
+
* Hook for static site generation (SSG) output.
|
|
332
|
+
*/
|
|
333
|
+
onExport?: (args: {
|
|
334
|
+
pages: any[];
|
|
335
|
+
outputDir: string;
|
|
336
|
+
}) => void | Promise<void | {
|
|
337
|
+
path: string;
|
|
338
|
+
content: string;
|
|
339
|
+
}[]>;
|
|
340
|
+
/**
|
|
341
|
+
* Callback fired when the CMS is shutting down.
|
|
342
|
+
*/
|
|
343
|
+
onDestroy?: () => void | Promise<void>;
|
|
344
|
+
/**
|
|
345
|
+
* Defines UI assets (scripts, styles) to be loaded by the Admin UI.
|
|
346
|
+
*/
|
|
347
|
+
adminAssets?: () => {
|
|
348
|
+
styles?: string[];
|
|
349
|
+
scripts?: string[];
|
|
350
|
+
};
|
|
351
|
+
/**
|
|
352
|
+
* Defines a configuration schema for the plugin.
|
|
353
|
+
* This will be used to generate a settings form in the Admin UI.
|
|
354
|
+
*/
|
|
355
|
+
configSchema?: Field[];
|
|
356
|
+
/**
|
|
357
|
+
* Defines the administrative UI for the plugin.
|
|
358
|
+
* This can point to local files during development or contain inlined source for production.
|
|
359
|
+
*/
|
|
360
|
+
adminUI?: {
|
|
361
|
+
/** The name of the custom element/component to render */
|
|
362
|
+
component?: string;
|
|
363
|
+
/** Absolute path to the source file (.tsx) - Used in dev/Node/Bun */
|
|
364
|
+
filePath?: string;
|
|
365
|
+
/** The inlined transpiled source code - Used in Workers/Production */
|
|
366
|
+
source?: string;
|
|
367
|
+
};
|
|
368
|
+
/** Runtime settings for the plugin */
|
|
369
|
+
settings?: Record<string, any>;
|
|
370
|
+
}
|
|
371
|
+
export interface OpacaConfig<Resource extends string = string> {
|
|
372
|
+
appName?: string;
|
|
373
|
+
serverURL?: string;
|
|
374
|
+
secret?: string;
|
|
375
|
+
db: DatabaseAdapter;
|
|
376
|
+
logger?: OpacaLoggerConfig;
|
|
250
377
|
collections: Collection[];
|
|
251
378
|
globals?: Global[];
|
|
252
|
-
db: DatabaseAdapter;
|
|
253
379
|
admin?: AdminConfig;
|
|
254
380
|
api?: ApiConfig;
|
|
255
381
|
access?: OpacaAccessConfig<Resource>;
|
|
@@ -259,6 +385,14 @@ export interface OpacaConfig<Resource extends string = string> extends Omit<Vali
|
|
|
259
385
|
locales: string[];
|
|
260
386
|
defaultLocale: string;
|
|
261
387
|
};
|
|
388
|
+
storages?: Record<string, any>;
|
|
389
|
+
runMigrationsOnStartup?: boolean;
|
|
390
|
+
plugins?: OpacaPlugin[];
|
|
391
|
+
}
|
|
392
|
+
export interface OpacaLoggerConfig {
|
|
393
|
+
disabled?: boolean;
|
|
394
|
+
disableColors?: boolean;
|
|
395
|
+
level?: "debug" | "info" | "warn" | "error";
|
|
262
396
|
}
|
|
263
397
|
export interface OpacaAuthConfig {
|
|
264
398
|
/**
|
|
@@ -327,6 +461,15 @@ export interface ApiConfig {
|
|
|
327
461
|
provider?: (c: Context) => any;
|
|
328
462
|
keyGenerator?: (c: Context) => string | Promise<string>;
|
|
329
463
|
};
|
|
464
|
+
openAPI?: {
|
|
465
|
+
enabled?: boolean;
|
|
466
|
+
path?: string;
|
|
467
|
+
theme?: "alternate" | "default" | "moon" | "purple" | "solarized" | "bluePlanet" | "saturn" | "kepler" | "mars" | "deepSpace" | "none" | string;
|
|
468
|
+
layout?: "modern" | "classic" | string;
|
|
469
|
+
hideModels?: boolean;
|
|
470
|
+
hideDownloadButton?: boolean;
|
|
471
|
+
customCss?: string;
|
|
472
|
+
};
|
|
330
473
|
}
|
|
331
474
|
export type { AdminConfig };
|
|
332
475
|
export interface FindOptions {
|
|
@@ -354,8 +497,8 @@ export interface DatabaseAdapter {
|
|
|
354
497
|
/**
|
|
355
498
|
* Internal ORM instance (e.g. Drizzle instance)
|
|
356
499
|
*/
|
|
357
|
-
readonly db?:
|
|
358
|
-
readonly raw?:
|
|
500
|
+
readonly db?: any;
|
|
501
|
+
readonly raw?: any;
|
|
359
502
|
unsafe(sql: string, params?: unknown[]): Promise<unknown>;
|
|
360
503
|
count(collection: string, query?: Record<string, unknown>): Promise<number>;
|
|
361
504
|
create<T extends object>(collection: string, data: Partial<T>): Promise<T>;
|
|
@@ -431,16 +574,28 @@ export interface SerializableCollection {
|
|
|
431
574
|
fields: SerializableCollection["fields"];
|
|
432
575
|
}[];
|
|
433
576
|
}[];
|
|
434
|
-
timestamps
|
|
577
|
+
timestamps?: boolean | {
|
|
435
578
|
createdAt?: string;
|
|
436
579
|
updatedAt?: string;
|
|
437
580
|
};
|
|
438
581
|
auth?: boolean;
|
|
439
582
|
admin?: {
|
|
440
583
|
defaultColumns?: string[];
|
|
584
|
+
/**
|
|
585
|
+
* If true, the collection's title will be used as a breadcrumb.
|
|
586
|
+
*/
|
|
441
587
|
useAsTitle?: string;
|
|
588
|
+
/**
|
|
589
|
+
* If true, the collection will be hidden from the Admin UI sidebar but still accessible via direct URL.
|
|
590
|
+
*/
|
|
442
591
|
hidden?: boolean;
|
|
592
|
+
/**
|
|
593
|
+
* If true, the collection will be completely disabled from the Admin UI (hidden from sidebar and blocked via direct URL).
|
|
594
|
+
*/
|
|
443
595
|
disableAdmin?: boolean;
|
|
596
|
+
/**
|
|
597
|
+
* Predefined filtered views for the collection list.
|
|
598
|
+
*/
|
|
444
599
|
views?: {
|
|
445
600
|
name: string;
|
|
446
601
|
filter: Record<string, any>;
|
|
@@ -488,5 +643,57 @@ export interface SerializableConfig {
|
|
|
488
643
|
}[];
|
|
489
644
|
}[];
|
|
490
645
|
needsInit?: boolean;
|
|
491
|
-
storages
|
|
646
|
+
storages: Record<string, unknown>;
|
|
647
|
+
plugins?: {
|
|
648
|
+
/**
|
|
649
|
+
* Name of the plugin.
|
|
650
|
+
*/
|
|
651
|
+
name: string;
|
|
652
|
+
/**
|
|
653
|
+
* Label to be used in the admin UI.
|
|
654
|
+
*/
|
|
655
|
+
label?: string;
|
|
656
|
+
/**
|
|
657
|
+
* Description of the plugin.
|
|
658
|
+
*/
|
|
659
|
+
description?: string;
|
|
660
|
+
/**
|
|
661
|
+
* Version of the plugin.
|
|
662
|
+
*/
|
|
663
|
+
version?: string;
|
|
664
|
+
/**
|
|
665
|
+
* Author of the plugin.
|
|
666
|
+
*/
|
|
667
|
+
author?: string;
|
|
668
|
+
/**
|
|
669
|
+
* Homepage of the plugin.
|
|
670
|
+
*/
|
|
671
|
+
homepage?: string;
|
|
672
|
+
/**
|
|
673
|
+
* Icon to be used in the admin UI.
|
|
674
|
+
*/
|
|
675
|
+
icon?: IconName;
|
|
676
|
+
/**
|
|
677
|
+
* Assets to be loaded in the admin UI.
|
|
678
|
+
*/
|
|
679
|
+
adminAssets?: {
|
|
680
|
+
styles?: string[];
|
|
681
|
+
scripts?: string[];
|
|
682
|
+
};
|
|
683
|
+
/**
|
|
684
|
+
* Admin UI configuration.
|
|
685
|
+
*/
|
|
686
|
+
adminUI?: {
|
|
687
|
+
/**
|
|
688
|
+
* The name of the custom element to register.
|
|
689
|
+
*/
|
|
690
|
+
component?: string;
|
|
691
|
+
/**
|
|
692
|
+
* The inlined transpiled source code - Used in Workers/Production
|
|
693
|
+
*/
|
|
694
|
+
source?: string;
|
|
695
|
+
};
|
|
696
|
+
settings?: Record<string, any>;
|
|
697
|
+
configSchema?: SerializableCollection["fields"];
|
|
698
|
+
}[];
|
|
492
699
|
}
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -1,35 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
success: (message: string, ...args: any[]) => void;
|
|
16
|
-
/**
|
|
17
|
-
* Dim/Debug logging.
|
|
18
|
-
* e.g., "Starting schema push...", "Syncing database..."
|
|
19
|
-
*/
|
|
20
|
-
debug: (message: string, ...args: any[]) => void;
|
|
21
|
-
/**
|
|
22
|
-
* Warning logging.
|
|
23
|
-
* For non-fatal errors or deprecated warnings.
|
|
24
|
-
*/
|
|
25
|
-
warn: (message: string, ...args: any[]) => void;
|
|
26
|
-
/**
|
|
27
|
-
* Error logging.
|
|
28
|
-
* For fatal errors, exceptions, and validation failures.
|
|
29
|
-
*/
|
|
30
|
-
error: (message: string, ...args: any[]) => void;
|
|
31
|
-
/**
|
|
32
|
-
* Raw formatting function if manual concatenation is needed.
|
|
33
|
-
*/
|
|
34
|
-
format: (color: "green" | "red" | "yellow" | "gray", msg: string) => string;
|
|
35
|
-
};
|
|
1
|
+
import type { OpacaLoggerConfig } from "../types";
|
|
2
|
+
export declare class OpacaLogger {
|
|
3
|
+
private config;
|
|
4
|
+
constructor(config?: OpacaLoggerConfig);
|
|
5
|
+
private shouldLog;
|
|
6
|
+
info(message: string, ...args: any[]): void;
|
|
7
|
+
success(message: string, ...args: any[]): void;
|
|
8
|
+
debug(message: string, ...args: any[]): void;
|
|
9
|
+
warn(message: string, ...args: any[]): void;
|
|
10
|
+
error(message: string, ...args: any[]): void;
|
|
11
|
+
format(color: "green" | "red" | "yellow" | "gray", msg: string): string;
|
|
12
|
+
}
|
|
13
|
+
export declare const logger: OpacaLogger;
|