@easy-cms/core 0.9.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +123 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @easy-cms/core
|
|
2
2
|
|
|
3
|
-
Core of [Easy CMS](https://github.com/maritonx/easy-
|
|
3
|
+
Core of [Easy CMS](https://github.com/maritonx/easy-cms) — an embedded, code-first headless CMS for Nuxt and Next.js.
|
|
4
4
|
|
|
5
5
|
> ⚠️ Pre-release. Not ready for production.
|
|
6
6
|
|
package/dist/index.d.ts
CHANGED
|
@@ -164,6 +164,11 @@ interface Database {
|
|
|
164
164
|
/** Applies pending migrations in order. Returns the names applied. */
|
|
165
165
|
migrate(): Promise<string[]>;
|
|
166
166
|
migrationStatus(): Promise<MigrationInfo[]>;
|
|
167
|
+
/**
|
|
168
|
+
* Copies the database to `file` (an absolute path) while it is in use, when the database can
|
|
169
|
+
* do that itself (SQLite). Others (Postgres) leave it out; use their own tools.
|
|
170
|
+
*/
|
|
171
|
+
readonly backup?: ((file: string) => Promise<void>) | undefined;
|
|
167
172
|
destroy(): Promise<void>;
|
|
168
173
|
}
|
|
169
174
|
/** What `sqlite()` / `postgres()` return and what `config.db` holds. */
|
|
@@ -429,6 +434,8 @@ interface CollectionConfig {
|
|
|
429
434
|
readonly singular?: Label;
|
|
430
435
|
readonly plural?: Label;
|
|
431
436
|
};
|
|
437
|
+
/** Icon in the admin menu. Default `file-text`. */
|
|
438
|
+
readonly icon?: AdminIcon;
|
|
432
439
|
readonly fields: readonly Field[];
|
|
433
440
|
/** Top-level field shown as the document title in the admin UI. */
|
|
434
441
|
readonly useAsTitle?: string;
|
|
@@ -450,6 +457,8 @@ interface CollectionConfig {
|
|
|
450
457
|
interface GlobalConfig {
|
|
451
458
|
readonly slug: string;
|
|
452
459
|
readonly label?: Label;
|
|
460
|
+
/** Icon in the admin menu. Default `settings`. */
|
|
461
|
+
readonly icon?: AdminIcon;
|
|
453
462
|
readonly fields: readonly Field[];
|
|
454
463
|
readonly drafts?: boolean;
|
|
455
464
|
/** Keep a snapshot of every save. See `CollectionConfig.versions`. */
|
|
@@ -462,11 +471,25 @@ interface GlobalConfig {
|
|
|
462
471
|
readonly hooks?: GlobalHooks;
|
|
463
472
|
}
|
|
464
473
|
type AdminLocale = 'en' | 'th';
|
|
474
|
+
/** Icons a collection or global can show in the admin menu ([Lucide](https://lucide.dev) names). */
|
|
475
|
+
declare const ADMIN_ICONS: readonly ["file-text", "newspaper", "book-open", "notebook", "folder", "tag", "tags", "image", "images", "video", "music", "file", "users", "user", "building", "store", "shopping-bag", "shopping-cart", "package", "box", "calendar", "calendar-days", "map-pin", "globe", "house", "layout-grid", "layers", "star", "heart", "message-square", "mail", "phone", "briefcase", "graduation-cap", "utensils", "car", "settings", "sliders-horizontal", "palette", "megaphone", "bell", "link", "quote", "circle-help", "award", "ticket", "camera"];
|
|
476
|
+
type AdminIcon = (typeof ADMIN_ICONS)[number];
|
|
477
|
+
/** Your or your client's brand in the admin UI. */
|
|
478
|
+
interface AdminBrand {
|
|
479
|
+
/** Shown in the menu, on the login page and in the browser tab. Default "Easy CMS". */
|
|
480
|
+
readonly name?: string;
|
|
481
|
+
/** Logo URL: a path on your site (`/logo.svg`) or an `https://` address. */
|
|
482
|
+
readonly logo?: string;
|
|
483
|
+
/** Main color as `#rrggbb`; lighter and darker shades are derived from it. */
|
|
484
|
+
readonly color?: string;
|
|
485
|
+
}
|
|
465
486
|
interface AdminConfig {
|
|
466
487
|
/** Where the admin UI is served. Default `/admin`. */
|
|
467
488
|
readonly path?: string;
|
|
468
489
|
/** Default admin UI language. Default `en`. */
|
|
469
490
|
readonly locale?: AdminLocale;
|
|
491
|
+
/** Name, logo and color of the admin UI. */
|
|
492
|
+
readonly brand?: AdminBrand;
|
|
470
493
|
}
|
|
471
494
|
interface ImageSize {
|
|
472
495
|
/** Key in `media.sizes`, e.g. `thumbnail`. */
|
|
@@ -1042,6 +1065,17 @@ declare class EasyCMS<C extends Config = Config> {
|
|
|
1042
1065
|
private scheduleTarget;
|
|
1043
1066
|
private globalScheduleTarget;
|
|
1044
1067
|
private addJob;
|
|
1068
|
+
/**
|
|
1069
|
+
* The next pending jobs across all collections and globals, soonest first; with access
|
|
1070
|
+
* enforced, only those the user may update.
|
|
1071
|
+
*/
|
|
1072
|
+
upcomingJobs(options?: AccessOptions & {
|
|
1073
|
+
limit?: number;
|
|
1074
|
+
}): Promise<(ScheduledJob & {
|
|
1075
|
+
collection?: string;
|
|
1076
|
+
global?: string;
|
|
1077
|
+
doc: ID;
|
|
1078
|
+
})[]>;
|
|
1045
1079
|
private pendingJobs;
|
|
1046
1080
|
private removeJob;
|
|
1047
1081
|
/** @internal */
|
|
@@ -1351,6 +1385,7 @@ interface AdminCollection {
|
|
|
1351
1385
|
singular?: Label;
|
|
1352
1386
|
plural?: Label;
|
|
1353
1387
|
};
|
|
1388
|
+
icon?: string;
|
|
1354
1389
|
useAsTitle?: string;
|
|
1355
1390
|
drafts: boolean;
|
|
1356
1391
|
versions: boolean;
|
|
@@ -1369,6 +1404,7 @@ interface AdminCollection {
|
|
|
1369
1404
|
interface AdminGlobal {
|
|
1370
1405
|
slug: string;
|
|
1371
1406
|
label?: Label;
|
|
1407
|
+
icon?: string;
|
|
1372
1408
|
drafts: boolean;
|
|
1373
1409
|
versions: boolean;
|
|
1374
1410
|
/** Has live preview (`preview` in the config). */
|
|
@@ -1420,4 +1456,4 @@ declare const BUILTIN_COLLECTIONS: readonly ["users", "media"];
|
|
|
1420
1456
|
/** Checks a config and returns every problem found. An empty array means it is valid. */
|
|
1421
1457
|
declare function validateConfig(config: Config): ConfigIssue[];
|
|
1422
1458
|
|
|
1423
|
-
export { type Access, type AccessArgs, type AccessOptions, type AdminCollection, type AdminConfig, type AdminField, type AdminGlobal, type AdminLocale, type AdminSchema, type AfterChangeHook, type AfterDeleteHook, type AfterReadHook, type ArrayField, Auth, type AuthConfig, type AuthUser, BUILTIN_COLLECTIONS, type BeforeChangeHook, type BeforeDeleteHook, type BeforeValidateHook, type Block, type BlocksField, type BooleanField, type BuiltinMediaCollection, type BuiltinUsersCollection, type BundleHints, CONFIG_FILE_NAMES, CSRF_COOKIE, CSRF_HEADER, type CollectionAccess, type CollectionConfig, type CollectionDocument, type CollectionHooks, type CollectionSlug, type Config, ConfigError, type ConfigIssue, type CreateEasyCMSOptions, type CreateInput, type CreateMigrationResult, DEFAULT_ADMIN_PATH, DEFAULT_API_PATH, DEFAULT_DEPTH, DEFAULT_MAX_FILE_SIZE, DEFAULT_MAX_VERSIONS, DEFAULT_TOKEN_EXPIRATION, type Database, type DatabaseAdapter, type DatabaseInitArgs, type DateField, type DepthOptions, EXTENSIONS, EasyCMS, EasyCMSError, type EmailField, FIELD_TYPES, type Field, type FieldAccess, type FieldAccessFn, type FieldError, type FieldType, type FieldValidate, type FieldValidateContext, type FieldValue, type FieldsInput, type FieldsValue, type FindArgs, type FindOptions, ForbiddenError, type GlobalAccess, type GlobalConfig, type GlobalDocument, type GlobalHooks, type GlobalInput, type GlobalSlug, type GroupField, type ID, INTERNAL_COLLECTIONS, type ImageSize, type InferCollection, type InferGlobal, type JsonField, type Label, type LivePreview, type LoadConfigOptions, type LocalStorageOptions, type LocalizationConfig, type Logger, type LoginArgs, MAX_DEPTH, MEDIA, MIN_PASSWORD_LENGTH, MIN_SECRET_LENGTH, type MediaDocument, type MediaSize, type MigrationInfo, NotFoundError, type NumberField, type Operation, type PaginatedDocs, PayloadTooLargeError, type Plugin, type PreviewTarget, type PreviewURL, QueryError, type RawDocument, type ReadOptions, type RelationshipField, type ResolvedConfig, type RestHandler, type RestHandlerOptions, type RichTextDocument, type RichTextField, type Role, type RoutesConfig, SESSION_COOKIE, type ScheduledJob, SchemaError, type SchemaMode, type SelectField, type SelectOption, type Session, type SlugField, type StorageAdapter, type StoredFile, type TextField, type TextareaField, TooManyRequestsError, UnauthorizedError, type UpdateInput, type UploadConfig, type UploadField, ValidationError, type Version, type VersionSummary, type VersionsConfig, WEBHOOK_EVENTS, type WebhookConfig, type WebhookEvent, type WebhookPayload, type Where, type WhereOperators, anyone, applyDefaults, consoleLogger, createEasyCMS, createRestHandler, defineConfig, fillMissing, findConfigFile, generateSlugs, generateTypes, hasRows, hashPassword, imageDimensions, importConfig, isAdmin, isLoggedIn, loadConfig, localStorage, mergeForUpdate, mimeAllowed, parseId, populate, readCookie, resolveConfig, rowFields, silentLogger, singularize, slugify, sniffMimeType, validateConfig, validateFields, verifyPassword };
|
|
1459
|
+
export { ADMIN_ICONS, type Access, type AccessArgs, type AccessOptions, type AdminBrand, type AdminCollection, type AdminConfig, type AdminField, type AdminGlobal, type AdminIcon, type AdminLocale, type AdminSchema, type AfterChangeHook, type AfterDeleteHook, type AfterReadHook, type ArrayField, Auth, type AuthConfig, type AuthUser, BUILTIN_COLLECTIONS, type BeforeChangeHook, type BeforeDeleteHook, type BeforeValidateHook, type Block, type BlocksField, type BooleanField, type BuiltinMediaCollection, type BuiltinUsersCollection, type BundleHints, CONFIG_FILE_NAMES, CSRF_COOKIE, CSRF_HEADER, type CollectionAccess, type CollectionConfig, type CollectionDocument, type CollectionHooks, type CollectionSlug, type Config, ConfigError, type ConfigIssue, type CreateEasyCMSOptions, type CreateInput, type CreateMigrationResult, DEFAULT_ADMIN_PATH, DEFAULT_API_PATH, DEFAULT_DEPTH, DEFAULT_MAX_FILE_SIZE, DEFAULT_MAX_VERSIONS, DEFAULT_TOKEN_EXPIRATION, type Database, type DatabaseAdapter, type DatabaseInitArgs, type DateField, type DepthOptions, EXTENSIONS, EasyCMS, EasyCMSError, type EmailField, FIELD_TYPES, type Field, type FieldAccess, type FieldAccessFn, type FieldError, type FieldType, type FieldValidate, type FieldValidateContext, type FieldValue, type FieldsInput, type FieldsValue, type FindArgs, type FindOptions, ForbiddenError, type GlobalAccess, type GlobalConfig, type GlobalDocument, type GlobalHooks, type GlobalInput, type GlobalSlug, type GroupField, type ID, INTERNAL_COLLECTIONS, type ImageSize, type InferCollection, type InferGlobal, type JsonField, type Label, type LivePreview, type LoadConfigOptions, type LocalStorageOptions, type LocalizationConfig, type Logger, type LoginArgs, MAX_DEPTH, MEDIA, MIN_PASSWORD_LENGTH, MIN_SECRET_LENGTH, type MediaDocument, type MediaSize, type MigrationInfo, NotFoundError, type NumberField, type Operation, type PaginatedDocs, PayloadTooLargeError, type Plugin, type PreviewTarget, type PreviewURL, QueryError, type RawDocument, type ReadOptions, type RelationshipField, type ResolvedConfig, type RestHandler, type RestHandlerOptions, type RichTextDocument, type RichTextField, type Role, type RoutesConfig, SESSION_COOKIE, type ScheduledJob, SchemaError, type SchemaMode, type SelectField, type SelectOption, type Session, type SlugField, type StorageAdapter, type StoredFile, type TextField, type TextareaField, TooManyRequestsError, UnauthorizedError, type UpdateInput, type UploadConfig, type UploadField, ValidationError, type Version, type VersionSummary, type VersionsConfig, WEBHOOK_EVENTS, type WebhookConfig, type WebhookEvent, type WebhookPayload, type Where, type WhereOperators, anyone, applyDefaults, consoleLogger, createEasyCMS, createRestHandler, defineConfig, fillMissing, findConfigFile, generateSlugs, generateTypes, hasRows, hashPassword, imageDimensions, importConfig, isAdmin, isLoggedIn, loadConfig, localStorage, mergeForUpdate, mimeAllowed, parseId, populate, readCookie, resolveConfig, rowFields, silentLogger, singularize, slugify, sniffMimeType, validateConfig, validateFields, verifyPassword };
|
package/dist/index.js
CHANGED
|
@@ -242,6 +242,7 @@ function withUsers(config) {
|
|
|
242
242
|
slug: USERS,
|
|
243
243
|
labels: { singular: { en: "User", th: "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49" }, plural: { en: "Users", th: "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49" } },
|
|
244
244
|
useAsTitle: "email",
|
|
245
|
+
icon: "users",
|
|
245
246
|
...custom,
|
|
246
247
|
fields: [...userFields(roles), ...custom?.fields ?? []],
|
|
247
248
|
access: {
|
|
@@ -302,6 +303,7 @@ function withMedia(config) {
|
|
|
302
303
|
const media = {
|
|
303
304
|
slug: MEDIA,
|
|
304
305
|
labels: { singular: { en: "Media", th: "\u0E2A\u0E37\u0E48\u0E2D" }, plural: { en: "Media", th: "\u0E04\u0E25\u0E31\u0E07\u0E2A\u0E37\u0E48\u0E2D" } },
|
|
306
|
+
icon: "image",
|
|
305
307
|
useAsTitle: "filename",
|
|
306
308
|
...custom,
|
|
307
309
|
fields: [...mediaFields(), ...custom?.fields ?? []],
|
|
@@ -695,6 +697,55 @@ var Auth = class {
|
|
|
695
697
|
};
|
|
696
698
|
|
|
697
699
|
// src/config.ts
|
|
700
|
+
var ADMIN_ICONS = [
|
|
701
|
+
"file-text",
|
|
702
|
+
"newspaper",
|
|
703
|
+
"book-open",
|
|
704
|
+
"notebook",
|
|
705
|
+
"folder",
|
|
706
|
+
"tag",
|
|
707
|
+
"tags",
|
|
708
|
+
"image",
|
|
709
|
+
"images",
|
|
710
|
+
"video",
|
|
711
|
+
"music",
|
|
712
|
+
"file",
|
|
713
|
+
"users",
|
|
714
|
+
"user",
|
|
715
|
+
"building",
|
|
716
|
+
"store",
|
|
717
|
+
"shopping-bag",
|
|
718
|
+
"shopping-cart",
|
|
719
|
+
"package",
|
|
720
|
+
"box",
|
|
721
|
+
"calendar",
|
|
722
|
+
"calendar-days",
|
|
723
|
+
"map-pin",
|
|
724
|
+
"globe",
|
|
725
|
+
"house",
|
|
726
|
+
"layout-grid",
|
|
727
|
+
"layers",
|
|
728
|
+
"star",
|
|
729
|
+
"heart",
|
|
730
|
+
"message-square",
|
|
731
|
+
"mail",
|
|
732
|
+
"phone",
|
|
733
|
+
"briefcase",
|
|
734
|
+
"graduation-cap",
|
|
735
|
+
"utensils",
|
|
736
|
+
"car",
|
|
737
|
+
"settings",
|
|
738
|
+
"sliders-horizontal",
|
|
739
|
+
"palette",
|
|
740
|
+
"megaphone",
|
|
741
|
+
"bell",
|
|
742
|
+
"link",
|
|
743
|
+
"quote",
|
|
744
|
+
"circle-help",
|
|
745
|
+
"award",
|
|
746
|
+
"ticket",
|
|
747
|
+
"camera"
|
|
748
|
+
];
|
|
698
749
|
function defineConfig(config) {
|
|
699
750
|
return config;
|
|
700
751
|
}
|
|
@@ -1236,9 +1287,12 @@ function validateConfig(config) {
|
|
|
1236
1287
|
const path = `collections.${collection2.slug ?? `[${i}]`}`;
|
|
1237
1288
|
validateContainer(collection2, path, collectionSlugs, add);
|
|
1238
1289
|
validateUseAsTitle(collection2, path, add);
|
|
1290
|
+
validateIcon(collection2, path, add);
|
|
1239
1291
|
});
|
|
1240
1292
|
globals.forEach((global2, i) => {
|
|
1241
|
-
|
|
1293
|
+
const path = `globals.${global2.slug ?? `[${i}]`}`;
|
|
1294
|
+
validateContainer(global2, path, collectionSlugs, add);
|
|
1295
|
+
validateIcon(global2, path, add);
|
|
1242
1296
|
});
|
|
1243
1297
|
const plugins = config.plugins;
|
|
1244
1298
|
if (plugins !== void 0 && (!Array.isArray(plugins) || plugins.some((p) => typeof p !== "function"))) {
|
|
@@ -1267,6 +1321,31 @@ function validateAdmin(config, add) {
|
|
|
1267
1321
|
if (admin.locale !== void 0 && admin.locale !== "en" && admin.locale !== "th") {
|
|
1268
1322
|
add("admin.locale", `must be "en" or "th" (got ${JSON.stringify(admin.locale)})`);
|
|
1269
1323
|
}
|
|
1324
|
+
const brand = admin.brand;
|
|
1325
|
+
if (brand === void 0) return;
|
|
1326
|
+
if (typeof brand !== "object" || brand === null) {
|
|
1327
|
+
add("admin.brand", "must be an object", "e.g. brand: { name: 'Acme', color: '#0f766e' }");
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
const { name, logo, color } = brand;
|
|
1331
|
+
if (name !== void 0 && (typeof name !== "string" || name.trim() === "")) {
|
|
1332
|
+
add("admin.brand.name", "must be a non-empty string");
|
|
1333
|
+
}
|
|
1334
|
+
if (logo !== void 0 && (typeof logo !== "string" || !/^(\/|https?:\/\/|data:image\/)/.test(logo))) {
|
|
1335
|
+
add(
|
|
1336
|
+
"admin.brand.logo",
|
|
1337
|
+
'must be a path starting with "/" or an http(s) URL',
|
|
1338
|
+
"e.g. logo: '/logo.svg'"
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
if (color !== void 0 && (typeof color !== "string" || !/^#[0-9a-f]{6}$/i.test(color))) {
|
|
1342
|
+
add("admin.brand.color", `must be a hex color like "#0f766e" (got ${JSON.stringify(color)})`);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
function validateIcon(container, path, add) {
|
|
1346
|
+
const icon = container.icon;
|
|
1347
|
+
if (icon === void 0 || ADMIN_ICONS.includes(icon)) return;
|
|
1348
|
+
add(`${path}.icon`, `unknown icon ${JSON.stringify(icon)}`, `one of: ${ADMIN_ICONS.join(", ")}`);
|
|
1270
1349
|
}
|
|
1271
1350
|
function validateAuth(config, add) {
|
|
1272
1351
|
const auth = config.auth;
|
|
@@ -1665,7 +1744,8 @@ async function resolveConfig(input) {
|
|
|
1665
1744
|
routes: { api: `/${(config.routes?.api ?? DEFAULT_API_PATH).replace(/^\/+|\/+$/g, "")}` },
|
|
1666
1745
|
admin: {
|
|
1667
1746
|
path: config.admin?.path ?? DEFAULT_ADMIN_PATH,
|
|
1668
|
-
locale: config.admin?.locale ?? "en"
|
|
1747
|
+
locale: config.admin?.locale ?? "en",
|
|
1748
|
+
brand: config.admin?.brand ?? {}
|
|
1669
1749
|
},
|
|
1670
1750
|
upload: {
|
|
1671
1751
|
dir: config.upload?.dir ?? "uploads",
|
|
@@ -3040,6 +3120,42 @@ var EasyCMS = class {
|
|
|
3040
3120
|
});
|
|
3041
3121
|
return toJob(row);
|
|
3042
3122
|
}
|
|
3123
|
+
/**
|
|
3124
|
+
* The next pending jobs across all collections and globals, soonest first; with access
|
|
3125
|
+
* enforced, only those the user may update.
|
|
3126
|
+
*/
|
|
3127
|
+
async upcomingJobs(options = {}) {
|
|
3128
|
+
if (!this.config.collections.some((c) => c.slug === SCHEDULED_JOBS)) return [];
|
|
3129
|
+
const guard = guardOf(options);
|
|
3130
|
+
const limit = options.limit ?? 10;
|
|
3131
|
+
const rows = await this.db.find({
|
|
3132
|
+
collection: SCHEDULED_JOBS,
|
|
3133
|
+
where: { state: { equals: "pending" } },
|
|
3134
|
+
sort: ["runAt"],
|
|
3135
|
+
limit: limit * 5,
|
|
3136
|
+
page: 1
|
|
3137
|
+
});
|
|
3138
|
+
const allowed2 = /* @__PURE__ */ new Map();
|
|
3139
|
+
const may = async (parent) => {
|
|
3140
|
+
if (!guard.enforce) return true;
|
|
3141
|
+
const cached = allowed2.get(parent);
|
|
3142
|
+
if (cached !== void 0) return cached;
|
|
3143
|
+
const config = parent.startsWith("global:") ? this.config.globals.find((g) => g.slug === parent.slice("global:".length)) : this.config.collections.find((c) => c.slug === parent);
|
|
3144
|
+
const access = config ? await evaluateAccess(config.access?.update, { user: guard.user }) : false;
|
|
3145
|
+
const result = access !== false;
|
|
3146
|
+
allowed2.set(parent, result);
|
|
3147
|
+
return result;
|
|
3148
|
+
};
|
|
3149
|
+
const jobs = [];
|
|
3150
|
+
for (const row of rows.docs) {
|
|
3151
|
+
const parent = String(row.parent);
|
|
3152
|
+
if (!await may(parent)) continue;
|
|
3153
|
+
const target = parent.startsWith("global:") ? { global: parent.slice("global:".length) } : { collection: parent };
|
|
3154
|
+
jobs.push({ ...toJob(row), ...target, doc: row.doc });
|
|
3155
|
+
if (jobs.length === limit) break;
|
|
3156
|
+
}
|
|
3157
|
+
return jobs;
|
|
3158
|
+
}
|
|
3043
3159
|
async pendingJobs(parent, doc) {
|
|
3044
3160
|
const rows = await this.db.find({
|
|
3045
3161
|
collection: SCHEDULED_JOBS,
|
|
@@ -3601,6 +3717,7 @@ async function collection(config, user, localized) {
|
|
|
3601
3717
|
};
|
|
3602
3718
|
if (config.labels) result.labels = config.labels;
|
|
3603
3719
|
if (config.useAsTitle) result.useAsTitle = config.useAsTitle;
|
|
3720
|
+
if (config.icon) result.icon = config.icon;
|
|
3604
3721
|
return result;
|
|
3605
3722
|
}
|
|
3606
3723
|
async function global(config, user, localized) {
|
|
@@ -3621,6 +3738,7 @@ async function global(config, user, localized) {
|
|
|
3621
3738
|
}
|
|
3622
3739
|
};
|
|
3623
3740
|
if (config.label !== void 0) result.label = config.label;
|
|
3741
|
+
if (config.icon) result.icon = config.icon;
|
|
3624
3742
|
return result;
|
|
3625
3743
|
}
|
|
3626
3744
|
async function adminSchema(cms, user) {
|
|
@@ -3863,6 +3981,8 @@ async function route(cms, ctx, method, segments, options) {
|
|
|
3863
3981
|
if (!ctx.user) throw new UnauthorizedError();
|
|
3864
3982
|
if (second === "schema" && third === void 0)
|
|
3865
3983
|
return { body: await adminSchema(cms, ctx.user) };
|
|
3984
|
+
if (second === "scheduled" && third === void 0)
|
|
3985
|
+
return { body: await cms.upcomingJobs({ user: ctx.user, overrideAccess: false }) };
|
|
3866
3986
|
const [, , collection3, id2, extra] = segments;
|
|
3867
3987
|
if (second === "access" && collection3 && id2 && extra === void 0) {
|
|
3868
3988
|
if (INTERNAL_COLLECTIONS.has(collection3) || !cms.config.collections.some((c) => c.slug === collection3)) {
|
|
@@ -4392,6 +4512,7 @@ ${map(n.globals)}
|
|
|
4392
4512
|
return parts.join("\n");
|
|
4393
4513
|
}
|
|
4394
4514
|
export {
|
|
4515
|
+
ADMIN_ICONS,
|
|
4395
4516
|
Auth,
|
|
4396
4517
|
BUILTIN_COLLECTIONS,
|
|
4397
4518
|
CONFIG_FILE_NAMES,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easy-cms/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Embedded, code-first headless CMS for Nuxt and Next.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"repository": {
|
|
32
32
|
"type": "git",
|
|
33
|
-
"url": "git+https://github.com/maritonx/easy-
|
|
33
|
+
"url": "git+https://github.com/maritonx/easy-cms.git",
|
|
34
34
|
"directory": "packages/core"
|
|
35
35
|
},
|
|
36
36
|
"keywords": [
|