feat: add new JSON schemas for Tibi configuration including fields, hooks, jobs, and permissions

- Introduced `field-list.schema.json`, `field-meta.schema.json`, and `field.schema.json` for field configurations.
- Added `hooks.schema.json` for defining hooks in the Tibi project.
- Created `image-filter.schema.json` for image processing configurations.
- Implemented `job.schema.json` for job scheduling configurations.
- Added `openapi.schema.json` for OpenAPI metadata generation.
- Introduced `permissions.schema.json` for managing permissions in the project.
- Created `project.schema.json` for overall project configuration.
- Added `projections.schema.json` for defining projections in the project.
- Implemented a validation script `validate-schemas.mjs` to ensure schema compliance.
This commit is contained in:
2026-07-01 09:21:26 +00:00
parent 4b588d1269
commit 40b441df04
41 changed files with 4038 additions and 3231 deletions
+13
View File
@@ -0,0 +1,13 @@
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
.DS_Store
Thumbs.db
.env
.env.*
!.env.example
+6 -3
View File
@@ -1,9 +1,12 @@
{
"yaml.customTags": ["!include scalar"],
"yaml.schemas": {
"schemas/api-config/config.json": "demo-api/config.y*ml",
"schemas/api-config/collection.json": "demo-api/collections/*.y*ml",
"schemas/api-config/field.json": "demo-api/collections/fields/*.y*ml"
"schemas/config/project.schema.json": "demo-api/config.y*ml",
"schemas/config/collection.schema.json": "demo-api/collections/*.y*ml",
"schemas/config/field.schema.json": "demo-api/collections/fields/*.y*ml",
"schemas/config/field-list.schema.json": "demo-api/collections/fieldLists/*.y*ml",
"schemas/config/job.schema.json": "demo-api/jobs/*.y*ml",
"schemas/config/asset.schema.json": "demo-api/assets/*.y*ml"
},
"editor.formatOnSave": true,
"editor.tabCompletion": "on",
+56
View File
@@ -0,0 +1,56 @@
# yaml-language-server: $schema=../../schemas/config/action.schema.json
name: demo-action
meta:
label: { de: Demo Aktion, en: Demo Action }
methods:
get:
query:
title: { de: Demo Query, en: Demo Query }
fields:
- name: verbose
type: boolean
execution:
kind: sync
post:
data:
title: { de: Demo Input, en: Demo Input }
fields:
- name: dryRun
type: boolean
execution:
kind: sse
cancellable: true
output:
title: { de: Demo Ergebnis, en: Demo Result }
mapping:
summary:
fields:
- source: result.status
type: string
meta:
label: { de: Status, en: Status }
permissions:
public:
methods:
get: true
post: false
user:
methods:
get: true
post: false
admin:
methods:
get: true
post: true
hooks:
get:
handle:
type: javascript
file: hooks/demo-action/get_handle.js
post:
handle:
type: javascript
file: hooks/demo-action/post_handle.js
@@ -1,4 +1,4 @@
# yaml-language-server: $schema=../../../schemas/api-config/permissions.json
# yaml-language-server: $schema=../../../schemas/config/permissions.schema.json
public:
methods:
+85 -7
View File
@@ -3,11 +3,7 @@ uploadPath: ../media/mycol
meta:
label: { de: mycol, en: mycol }
rowIdentTpl: { twig: "{{ title }}" }
views:
- type: table
columns:
- title
preview: testfield
permissions: !include global/test-permissions.yml
@@ -39,8 +35,7 @@ fields:
label:
de: test2
en: test2
widget: "contentbuilder"
baseHref: /mycol
widget: "textarea"
- name: testfield3
type: string
@@ -50,3 +45,86 @@ fields:
en: test3
widget: "select"
choices: []
- name: code
type: string
validator:
pattern: "[A-Z]{3}-[0-9]{2}"
meta:
label:
de: Code
en: Code
widget: "text"
- name: status
type: string
validator:
in: [draft, published]
meta:
label:
de: Status
en: Status
widget: "text"
- name: contactEmail
type: string
validator:
format: email
meta:
label:
de: E-Mail
en: Email
widget: "text"
- name: shortCode
type: string
validator:
minLength: 3
maxLength: 5
meta:
label:
de: Kurzcode
en: Short code
widget: "text"
- name: rating
type: number
validator:
min: 1
max: 10
meta:
label:
de: Bewertung
en: Rating
widget: "text"
- name: eventDate
type: date
validator:
minDate: "2024-01-01"
maxDate: "2026-12-31"
meta:
label:
de: Eventdatum
en: Event date
widget: "date"
- name: heroImage
type: file
validator:
minFileSize: "10KB"
maxFileSize: "2MB"
accept: ["image/jpeg", "image/png", "image/webp"]
image:
minWidth: 1200
maxWidth: 3200
minHeight: 600
maxHeight: 2400
- name: attachments
type: file[]
validator:
minItems: 1
maxItems: 3
maxFileSize: "5MB"
accept: ["application/pdf"]
+3
View File
@@ -9,6 +9,9 @@ meta:
collections:
- !include collections/mycol.yml
actions:
- !include actions/demo-action.yml
assets:
- name: _dist_
path: ../frontend/_dist_
Vendored
+128 -11
View File
@@ -90,6 +90,22 @@ declare global {
k?: number
topK?: number
weights?: { [source: string]: number }
/** Fusion strategy: "rrf" (default), "score_rrf", "score_sum", "rank_score", "hybrid" */
strategy?: "rrf" | "score_rrf" | "score_sum" | "rank_score" | "hybrid"
/** Score normalization: "none" (default), "minmax", "zscore" */
normalize?: "none" | "minmax" | "zscore"
/** Blend factor for "hybrid" strategy: 0.0 = pure rank, 1.0 = pure score */
scoreWeight?: number
/** Per-source overrides for fine-grained fusion tuning */
sourceConfig?: { [source: string]: SourceFusionConfig }
}
/** Per-source overrides for rank fusion */
export interface SourceFusionConfig {
/** Override global scoreWeight for this source */
scoreWeight?: number
/** Score multiplier for this source (default 1.0) */
boost?: number
}
export interface VectorConfig {
@@ -101,6 +117,35 @@ declare global {
chunkOverlap?: number
}
export interface SearchExplainSource {
mode?: string
matched?: boolean
rank?: number
weight?: number
score?: number
/** Normalized score (only present when normalize is active) */
normalizedScore?: number
contribution?: number
details?: SearchExplanation
}
export interface SearchExplanation {
algorithm?: string
/** Fusion strategy used ("score_rrf", "hybrid", etc.). Omitted when default "rrf". */
strategy?: string
/** Normalization mode used ("minmax", "zscore"). Omitted when "none". */
normalize?: string
k?: number
sources?: { [source: string]: SearchExplainSource }
}
export interface SearchMeta {
score?: number
mode?: string
/** Present when the request uses qExplain=1 or qExplain=true. */
details?: SearchExplanation
}
/** Search configuration for a collection */
export interface SearchConfig {
/** Search config name (used in query parameter qName) */
@@ -132,6 +177,8 @@ declare global {
vector?: VectorConfig
/** Reciprocal rank fusion configuration */
rrf?: RrfConfig
/** Execute synchronously (false) or via background queue (true). Vector mode defaults to true. */
async?: boolean
/** Auto-regenerate enrichment data when the config changes */
autoRegenerate?: boolean
}
@@ -204,15 +251,24 @@ declare global {
export type ChoiceValue = string | number | boolean | null
export type ChoiceStyle = Record<string, string | number | boolean>
export interface ChoiceItem {
id?: ChoiceValue
value?: ChoiceValue
name?: LocalizedText
label?: LocalizedText
description?: LocalizedText
badgeVariant?: "success" | "error" | "warning" | "info" | "neutral"
chipVariant?: "success" | "error" | "warning" | "info" | "neutral"
badgeStyle?: Record<string, string | number | boolean>
chipStyle?: Record<string, string | number | boolean>
/**
* Flat inline CSS properties for badge/chip rendering.
* Supports camelCase, kebab-case, and CSS custom properties.
* `bg` and `text` remain aliases for `background` and `color`.
*/
badgeStyle?: ChoiceStyle
/** Alias for `badgeStyle`. */
chipStyle?: ChoiceStyle
}
export type EvalStringConfig = {
@@ -334,7 +390,9 @@ declare global {
/** Action endpoint descriptor as returned by context.api() for _actions resources */
export interface ActionInfo {
name: string
permissions?: { [role: string]: PermissionSet }
meta?: ActionMeta
audit?: AuditCollectionConfig
[key: string]: any
}
@@ -366,21 +424,76 @@ declare global {
export interface ActionExecutionMeta {
kind?: "sync" | "sse" | string
progress?: boolean
cancellable?: boolean
[key: string]: any
}
export interface ActionMappedField extends Omit<
CollectionFieldInfo,
"name"
> {
/** Dot-path in action payload/result/progress. Preferred over `name` for mapped output configs. */
source?: string
/** Legacy fallback for path-based mappings. */
name?: string
}
export interface ActionOutputProgressMapping {
indexField?: string
countField?: string
statusField?: string | string[]
messageField?: string
fields?: ActionMappedField[]
}
export interface ActionOutputMapping {
summary?: {
fields?: ActionMappedField[]
}
details?: {
fields?: ActionMappedField[]
}
progress?: ActionOutputProgressMapping
}
export interface ActionOutputMeta {
display?: "summary" | "detail" | "raw" | "download" | "none" | string
title?: LocalizedText
fields?: CollectionFieldInfo[]
mapping?: ActionOutputMapping
[key: string]: any
}
export type MethodPermission = boolean | { allow: boolean; bulk?: boolean }
export type SimpleMethodPermission = boolean | { allow: boolean }
export interface AllowedMethodPermission {
allow: boolean
bulk?: boolean
}
export interface CollectionYourPermissions {
get?: AllowedMethodPermission
post?: AllowedMethodPermission
put?: AllowedMethodPermission
delete?: AllowedMethodPermission
readonlyFields?: string[]
hiddenFields?: string[]
}
export interface ActionYourPermissions {
get?: { allow: boolean }
post?: { allow: boolean }
}
export interface ProjectYourPermissions {
_actions?: { [actionName: string]: ActionYourPermissions }
[collectionName: string]:
| CollectionYourPermissions
| { [actionName: string]: ActionYourPermissions }
| undefined
}
export interface PermissionSet {
methods?: {
get?: SimpleMethodPermission
@@ -444,7 +557,7 @@ declare global {
users?: string[]
configFile?: string
api?: ApiInfo
yourPermissions?: { [key: string]: any }
yourPermissions?: ProjectYourPermissions
[key: string]: any
}
@@ -1095,12 +1208,19 @@ declare global {
}
interface CharsetPackage {
/**
* decode byte-oriented input using the given encoding
*
* supported encodings: utf-8, iso-8859-1
*/
decode(input: string | Int8Array | number[], encoding: string): string
/**
* convert iso8859 to utf8
*
* @param iso8859 iso string
* @param iso8859 iso string or bytes
*/
iso8859ToUtf8(iso8859: string): string
iso8859ToUtf8(iso8859: string | Int8Array | number[]): string
}
interface ImagePackage {
@@ -1525,10 +1645,7 @@ declare global {
}
export interface HookContext
extends GetHookData,
GetHookGetOnlyData,
PostHookData,
JobData {
extends GetHookData, GetHookGetOnlyData, PostHookData, JobData {
request(): {
method: string
remoteAddr: string
@@ -1541,7 +1658,7 @@ declare global {
header(h: string): string
body(): string
/**
* bodyBytes return []byte go slice of post body for later use pe. in iso8859ToUtf8
* bodyBytes returns the raw request body bytes for later decoding via charset.decode
*/
bodyBytes(): Int8Array
}
+350
View File
@@ -0,0 +1,350 @@
{
"name": "tibi-types",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "tibi-types",
"version": "0.0.1",
"license": "MIT",
"devDependencies": {
"ajv": "^8.20.0",
"ajv-formats": "^3.0.1",
"glob": "^11.1.0",
"js-yaml": "^4.1.1"
}
},
"node_modules/@isaacs/cliui": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz",
"integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/ajv": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"dev": true,
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
"integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ajv": "^8.0.0"
},
"peerDependencies": {
"ajv": "^8.0.0"
},
"peerDependenciesMeta": {
"ajv": {
"optional": true
}
}
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0"
},
"node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/brace-expansion": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true,
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
"integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "BSD-3-Clause"
},
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"dev": true,
"license": "ISC",
"dependencies": {
"cross-spawn": "^7.0.6",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
"integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"foreground-child": "^3.3.1",
"jackspeak": "^4.1.1",
"minimatch": "^10.1.1",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true,
"license": "ISC"
},
"node_modules/jackspeak": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz",
"integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^9.0.0"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-yaml": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true,
"license": "MIT"
},
"node_modules/lru-cache": {
"version": "11.2.7",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz",
"integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/minimatch": {
"version": "10.2.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"brace-expansion": "^5.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minipass": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
"integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"dev": true,
"license": "BlueOak-1.0.0"
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/path-scurry": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
"integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
}
}
}
+9 -2
View File
@@ -1,10 +1,17 @@
{
"name": "tibi-types",
"version": "0.0.1",
"description": "tibi javascript types and json schemas",
"description": "tibi hook types and validated config schemas",
"types": "index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"validate:schemas": "node scripts/validate-schemas.mjs",
"test": "npm run validate:schemas"
},
"devDependencies": {
"ajv": "^8.20.0",
"ajv-formats": "^3.0.1",
"glob": "^11.1.0",
"js-yaml": "^4.1.1"
},
"repository": {
"type": "git",
-23
View File
@@ -1,23 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server assets configuration",
"description": "tibi-server assets linter",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x\\-": {
"description": "template property"
}
},
"properties": {
"name": {
"type": "string",
"description": "name, used in url ../NAMESPACE/_/assets/NAME"
},
"path": {
"type": "string",
"description": "path relative to config.yml"
}
},
"required": ["name", "path"]
}
-389
View File
@@ -1,389 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server collection configuration",
"description": "tibi-server collection configuration",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x\\-": {
"description": "template property"
}
},
"properties": {
"name": {
"type": "string",
"description": "collection name, part of api path"
},
"defaultLanguage": {
"type": "string",
"description": "default language for database text index"
},
"uploadPath": {
"type": "string",
"description": "relative to config.yml, path for file uploads"
},
"upload": {
"type": "object",
"description": "collection-specific upload defaults and restrictions",
"additionalProperties": false,
"properties": {
"maxBodySize": {
"type": "string",
"description": "request body size limit override for this collection (e.g. '10MB')"
},
"allowedMimeTypes": {
"type": "array",
"description": "allowed MIME types for file uploads in this collection; empty means all types are allowed",
"items": {
"type": "string"
}
}
}
},
"meta": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"type": "object",
"description": "meta object used for admin ui configuration",
"additionalProperties": true,
"allOf": [
{
"$ref": "collectionNavigation.json"
}
],
"properties": {
"rowIdentTpl": {
"description": "template which evaluates to short string to identify entry in pe. select boxes",
"$ref": "definitions.json#/definitions/evalExpressions"
},
"subNavigation": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"type": "array",
"description": "sub navigation of collection",
"items": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "collectionNavigation.json"
}
]
}
}
]
},
"pagebuilder": {
"type": "object",
"description": "Collection-level pagebuilder defaults. These serve as fallbacks when field-level pagebuilder config omits them.",
"additionalProperties": false,
"properties": {
"blockTypeField": {
"type": "string",
"description": "Name of the sub-field that holds the block type identifier. Default: 'blockType'. Used as fallback for all pagebuilder fields in this collection."
},
"blockRegistry": {
"type": "object",
"description": "Block registry configuration.",
"additionalProperties": false,
"properties": {
"file": {
"type": "string",
"description": "URL to an ES module that default-exports a BlockRegistry. Used as fallback for all pagebuilder fields in this collection."
}
}
}
}
}
}
}
]
},
"projections": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "projections.json"
}
]
},
"permissions": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "permissions.json"
}
]
},
"hooks": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "hooks.json"
}
]
},
"imageFilter": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "imageFilter.json"
}
]
},
"fields": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"type": "array",
"description": "fields of collection",
"items": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "field.json"
}
]
}
}
]
},
"indexes": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"type": "array",
"description": "indexes of collection",
"items": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "index.json"
}
]
}
}
]
},
"bulk": {
"type": "object",
"description": "bulk operation configuration",
"additionalProperties": false,
"properties": {
"optimize": {
"type": "object",
"description": "enable optimised single-DB-call bulk path without requiring a hook file",
"additionalProperties": false,
"properties": {
"create": {
"type": "boolean",
"description": "POST with JSON array uses optimised InsertMany path"
},
"update": {
"type": "boolean",
"description": "PUT without ID uses optimised path"
},
"delete": {
"type": "boolean",
"description": "DELETE without ID uses optimised path"
}
}
}
}
},
"cors": {
"type": "object",
"description": "cors configuration",
"additionalProperties": false,
"properties": {
"merge": {
"type": "boolean",
"description": "merge with global and project cors configuration"
},
"allowOrigins": {
"type": "array",
"description": "list of allowed origins",
"items": {
"type": "string"
}
},
"allowMethods": {
"type": "array",
"description": "list of allowed methods",
"items": {
"type": "string"
}
},
"allowHeaders": {
"type": "array",
"description": "list of allowed headers",
"items": {
"type": "string"
}
},
"allowCredentials": {
"type": "boolean",
"description": "allow credentials"
},
"exposeHeaders": {
"type": "array",
"description": "list of exposed headers",
"items": {
"type": "string"
}
},
"maxAge": {
"type": "integer",
"description": "max age in seconds"
}
}
},
"audit": {
"type": "object",
"description": "audit logging configuration for this collection",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean",
"description": "enable audit logging for this collection"
},
"actions": {
"type": "array",
"description": "list of actions to audit (create, update, delete, bulkCreate, bulkUpdate, bulkDelete, get)",
"items": {
"type": "string",
"enum": [
"create",
"update",
"delete",
"bulkCreate",
"bulkUpdate",
"bulkDelete",
"get"
]
}
}
}
},
"queryLimits": {
"type": "object",
"description": "query limit configuration for GET requests",
"additionalProperties": false,
"properties": {
"defaultLimit": {
"type": "integer",
"description": "default limit for GET queries if client doesn't specify one"
},
"maxLimit": {
"type": "integer",
"description": "maximum allowed limit for GET queries"
}
}
},
"readonlyFields": {
"type": "array",
"description": "fields that are read-only at collection level",
"items": {
"type": "string"
}
},
"hiddenFields": {
"type": "array",
"description": "fields that are hidden at collection level",
"items": {
"type": "string"
}
},
"search": {
"type": "array",
"description": "search configurations for the collection",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"description": "search config name (used in query parameter qName)"
},
"mode": {
"type": "string",
"description": "search mode",
"enum": [
"text",
"regex",
"eval",
"filter"
]
},
"fields": {
"type": "array",
"description": "fields to search in (for text/regex mode)",
"items": {
"type": "string"
}
},
"meta": {
"type": "object",
"description": "meta information",
"additionalProperties": true
},
"eval": {
"type": "string",
"description": "JS eval expression (for eval mode)"
},
"filter": {
"type": "object",
"description": "MongoDB filter template (for filter mode)",
"additionalProperties": true
}
},
"required": [
"name",
"mode"
]
}
},
"strictFields": {
"type": "boolean",
"description": "reject unknown fields not defined in the fields array"
}
},
"required": [
"name",
"permissions"
]
}
@@ -1,363 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server collection meta navigation configuration",
"description": "tibi-server collection navigation linter",
"type": "object",
"additionalProperties": true,
"patternProperties": {
"^x\\-": {
"description": "template property"
}
},
"required": [],
"properties": {
"name": {
"type": "string",
"description": "name of navigation"
},
"label": {
"$ref": "definitions.json#/definitions/i18nString"
},
"defaultImageFilter": {
"type": "string",
"description": "image filter name used for image previews"
},
"viewHint": {
"description": "default collection view hint or structured special view config",
"oneOf": [
{
"type": "string",
"enum": [
"table",
"cards",
"media"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"navigation": {
"type": "object",
"additionalProperties": false,
"properties": {
"nodesField": {
"type": "string",
"description": "root field containing the recursive node array"
},
"declaredTrees": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"label": {
"$ref": "definitions.json#/definitions/i18nString"
},
"singleton": {
"type": "object",
"description": "root-level field values that identify one declared tree slot",
"additionalProperties": true
},
"maxLevel": {
"type": "number"
}
},
"required": [
"singleton"
]
}
}
}
}
},
"required": [
"navigation"
]
}
]
},
"muiIcon": {
"type": "string",
"description": "material ui icon name"
},
"multiupload": {
"type": "object",
"description": "Configuration for multi-upload behavior.",
"properties": {
"fields": {
"type": "array",
"description": "Fields editable in the modal. If not set, all fields will be selected automatically.",
"items": {
"type": "object",
"properties": {
"source": {
"type": "string",
"description": "Name of the field."
}
},
"required": [
"source"
]
}
},
"prefilledFields": {
"type": "array",
"description": "Fields that should have default values. They won't be visible to the user but just an informational text for which fields will receive a default value.",
"items": {
"type": "object",
"properties": {
"source": {
"type": "string",
"description": "Name of the field."
},
"defaultValue": {
"type": "object",
"properties": {
"eval": {
"type": "string",
"description": "JavaScript evaluation string to determine the default value."
}
},
"required": [
"eval"
]
}
},
"required": [
"source",
"defaultValue"
]
}
}
},
"required": [
"fields"
]
},
"defaultSort": {
"type": "object",
"description": "default sort in admin ui lists",
"additionalProperties": false,
"properties": {
"field": {
"$ref": "definitions.json#/definitions/fieldSource"
},
"order": {
"description": "sort order",
"enum": [
"ASC",
"DESC",
"MANUALLY"
]
}
}
},
"defaultCallback": {
"description": "default action on entry, defaults to edit - can be one of: edit, view, Object with js eval",
"oneOf": [
{
"type": "string",
"enum": [
"edit",
"view"
]
},
{
"type": "object",
"properties": {
"eval": {
"type": "string",
"description": "js eval string of (entry) => {}"
}
},
"additionalProperties": false
}
]
},
"filter": {
"type": "object",
"description": "filter for prefiltering collection view"
},
"views": {
"type": "array",
"description": "list views",
"items": {
"oneOf": [
{
"type": "string",
"description": "YAML !include reference to an external view definition file"
},
{
"type": "object",
"properties": {
"mediaQuery": {
"type": "string",
"description": "css media query to select this view in ui"
},
"selectionPriority": {
"type": "number",
"description": "priority for selection based on media query"
},
"fileDropArea": {
"type": "object",
"properties": {
"label": {
"$ref": "definitions.json#/definitions/i18nString"
},
"helperText": {
"$ref": "definitions.json#/definitions/i18nString"
},
"targetField": {
"type": "string"
},
"pageAsDropArea": {
"type": "boolean"
}
}
}
},
"oneOf": [
{
"properties": {
"type": {
"enum": [
"simpleList",
"dashboardSimpleList"
]
},
"primaryText": {
"oneOf": [
{
"$ref": "definitions.json#/definitions/fieldSource"
},
{
"$ref": "definitions.json#/definitions/evalExpressions"
}
]
},
"secondaryText": {
"oneOf": [
{
"$ref": "definitions.json#/definitions/fieldSource"
},
{
"$ref": "definitions.json#/definitions/evalExpressions"
}
]
},
"tertiaryText": {
"oneOf": [
{
"$ref": "definitions.json#/definitions/fieldSource"
},
{
"$ref": "definitions.json#/definitions/evalExpressions"
}
]
}
},
"required": [
"type",
"primaryText"
]
},
{
"properties": {
"type": {
"enum": [
"table",
"dashboardTable"
]
},
"columns": {
"type": "array",
"items": {
"oneOf": [
{
"anyOf": [
{
"$ref": "definitions.json#/definitions/fieldSource"
},
{
"type": "object",
"properties": {
"label": {
"$ref": "definitions.json#/definitions/i18nString"
},
"renderValue": {
"description": "render value based on entry ($ variable)",
"$ref": "definitions.json#/definitions/evalObjectWithRaw"
}
}
}
]
},
{
"allOf": [
{
"$ref": "definitions.json#/definitions/evalExpressions"
},
{
"properties": {
"label": {
"$ref": "definitions.json#/definitions/i18nString"
}
}
}
]
}
]
},
"minItems": 1
}
},
"required": [
"type",
"columns"
]
},
{
"properties": {
"type": {
"const": "cardList"
},
"fields": {
"type": "array",
"items": {
"type": "object",
"properties": {
"source": {
"type": "string"
},
"type": {
"type": "string"
},
"label": {
"type": "string"
},
"filter": {
"type": "boolean"
}
},
"required": [
"source"
]
}
}
},
"required": [
"type",
"fields"
]
}
],
"required": [
"type"
]
}
]
}
}
}
}
-229
View File
@@ -1,229 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server config file",
"description": "tibi-server config.yml linter",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x\\-": {
"description": "template property"
}
},
"properties": {
"namespace": {
"type": "string",
"description": "suffix for mongo db database and part of api url, can be overwritten in database project settings"
},
"meta": {
"type": "object",
"description": "meta object used for admin ui configuration",
"additionalProperties": true,
"properties": {
"dashboard": {
"$ref": "dashboard.json#/properties/dashboard"
},
"imageUrl": {
"description": "project's teaser image url shown in admin ui",
"oneOf": [
{
"type": "string"
},
{
"$ref": "definitions.json#/definitions/evalObject"
}
]
}
}
},
"upload": {
"type": "object",
"description": "project-wide upload defaults and restrictions",
"additionalProperties": false,
"properties": {
"maxBodySize": {
"type": "string",
"description": "default request body size limit for collections in this project (e.g. '50MB')"
},
"allowedMimeTypes": {
"type": "array",
"description": "project-wide allowed MIME types for file uploads; empty means all types are allowed",
"items": {
"type": "string"
}
}
}
},
"collections": {
"type": "array",
"description": "list of collections in this project",
"items": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "collection.json"
}
]
}
},
"jobs": {
"type": "array",
"description": "list of jobs in this project",
"items": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "job.json"
}
]
}
},
"assets": {
"type": "array",
"description": "list of assets in this project",
"items": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "assets.json"
}
]
}
},
"cors": {
"type": "object",
"description": "cors configuration",
"additionalProperties": false,
"properties": {
"merge": {
"type": "boolean",
"description": "merge with global cors configuration"
},
"allowOrigins": {
"type": "array",
"description": "list of allowed origins",
"items": {
"type": "string"
}
},
"allowMethods": {
"type": "array",
"description": "list of allowed methods",
"items": {
"type": "string"
}
},
"allowHeaders": {
"type": "array",
"description": "list of allowed headers",
"items": {
"type": "string"
}
},
"allowCredentials": {
"type": "boolean",
"description": "allow credentials"
},
"exposeHeaders": {
"type": "array",
"description": "list of exposed headers",
"items": {
"type": "string"
}
},
"maxAge": {
"type": "integer",
"description": "max age in seconds"
}
}
},
"admin": {
"type": "object",
"description": "admin configuration",
"additionalProperties": false,
"properties": {
"tokens": {
"type": "array",
"description": "list of admin tokens",
"items": {
"type": "object",
"properties": {
"token": {
"type": "string",
"description": "admin token"
},
"allowReload": {
"type": "boolean",
"description": "allow reload"
}
}
}
}
}
},
"hook": {
"type": "object",
"description": "project-level hook configuration (cache and ratelimit)",
"additionalProperties": false,
"properties": {
"cache": {
"type": "object",
"description": "hook cache configuration",
"additionalProperties": false,
"properties": {
"maxEntries": {
"type": "integer",
"description": "maximum number of cache entries"
},
"defaultTTL": {
"type": "string",
"description": "default time-to-live (e.g. '5m', '1h')"
}
}
},
"ratelimit": {
"type": "object",
"description": "hook ratelimit configuration",
"additionalProperties": false,
"properties": {
"backoffInitialDelay": {
"type": "string",
"description": "initial backoff delay (e.g. '1s')"
},
"backoffMaxDelay": {
"type": "string",
"description": "maximum backoff delay (e.g. '5m')"
},
"backoffResetAfter": {
"type": "string",
"description": "reset backoff after this duration of no failures (e.g. '15m')"
},
"windowSize": {
"type": "string",
"description": "sliding window size (e.g. '1m')"
},
"windowMaxHits": {
"type": "integer",
"description": "maximum hits allowed per window"
}
}
}
}
},
"strictFields": {
"type": "boolean",
"description": "reject unknown fields not defined in the fields array (project-wide default)"
}
},
"required": [
"namespace"
]
}
-357
View File
@@ -1,357 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"dashboard": {
"type": "object",
"properties": {
"majorItems": {
"type": "array",
"items": {
"oneOf": [
{ "$ref": "#/definitions/sectionTitle" },
{ "$ref": "#/definitions/swiper" },
{ "$ref": "#/definitions/graph" },
{ "$ref": "#/definitions/table" },
{ "$ref": "#/definitions/reference" }
]
}
},
"minorItems": {
"type": "array",
"items": { "$ref": "#/definitions/minorItem" }
}
}
}
},
"required": ["dashboard"],
"definitions": {
"sectionTitle": {
"type": "object",
"properties": {
"type": { "type": "string", "enum": ["sectionTitle"] },
"title": { "type": "string" }
},
"required": ["type", "title"],
"additionalProperties": false
},
"swiper": {
"type": "object",
"properties": {
"type": { "type": "string", "enum": ["swiper"] },
"class": { "type": "string" },
"css": {
"type": "object",
"properties": {
"graph": {
"type": "object",
"properties": {
"wrapper": {
"$ref": "#/definitions/cssWithEval"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"containerProps": { "$ref": "#/definitions/containerProps" },
"elements": {
"type": "array",
"items": { "$ref": "#/definitions/graph" }
}
},
"required": ["type", "elements"],
"additionalProperties": false
},
"comparison": {
"$ref": "#/definitions/graph"
},
"graph": {
"type": "object",
"properties": {
"additionalApiParams": {
"$ref": "#/definitions/additionalApiParams"
},
"class": { "type": "string" },
"type": { "type": "string", "enum": ["graph", "comparison"] },
"containerProps": { "$ref": "#/definitions/containerProps" },
"css": {
"type": "object",
"properties": {
"graph": {
"type": "object",
"properties": {
"wrapper": {
"$ref": "#/definitions/cssWithEval"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"title": {
"oneOf": [
{
"type": "object",
"properties": {
"value": { "type": "string" },
"contentAfter": { "type": "string" },
"contentBefore": { "type": "string" },
"eval": { "type": "string" }
},
"required": ["value"]
},
{ "type": "string" },
{
"type": "object",
"properties": {
"de": { "type": "string" },
"en": { "type": "string" }
},
"required": ["de", "en"]
}
]
},
"subTitle": {
"oneOf": [
{ "type": "string" },
{
"type": "object",
"properties": {
"de": { "type": "string" },
"en": { "type": "string" }
},
"required": ["de", "en"]
}
]
},
"xAxis": { "type": "string", "enum": ["timeline"] },
"timeInterval": {
"type": "string",
"enum": ["day", "month", "year"]
},
"filter": { "type": "boolean" },
"dateTimeField": { "type": "string" },
"until": {
"type": "string",
"enum": ["lastWeek", "lastMonth", "lastYear", "allTime"]
},
"graphType": {
"type": "string",
"enum": ["bar", "line", "pie", "donut", "area"]
},
"graphs": {
"type": "array",
"items": { "$ref": "#/definitions/graphDetail" }
},
"defaultUntil": {
"type": "string",
"enum": ["lastWeek", "lastMonth", "lastYear", "allTime"]
},
"newPageRef": { "type": "boolean" },
"limit": { "type": "number" },
"value": { "type": "string", "enum": ["total", "amount"] },
"valueType": {
"type": "string",
"enum": ["absolute", "relative"]
},
"field": { "type": "string" },
"path": { "type": "string" },
"style": {
"type": "object",
"properties": {
"upper": { "type": "string" },
"lower": { "type": "string" }
}
},
"collection": { "type": "string" },
"subNavigation": { "type": "number" },
"graphBaseColor": { "type": "string" },
"multipleYAxes": { "type": "boolean" },
"timespan": {
"type": "string",
"enum": ["YTD", "QTD", "MTD"]
},
"backgroundLines": { "type": "boolean" },
"opacity": { "type": "number" },
"elements": {
"type": "array",
"items": { "$ref": "#/definitions/graph" }
}
},
"additionalProperties": false
},
"graphDetail": {
"type": "object",
"properties": {
"graphName": {
"type": "object",
"properties": {
"de": { "type": "string" },
"en": { "type": "string" }
},
"required": ["de", "en"]
},
"graphType": {
"type": "string",
"enum": ["bar", "line", "pie", "donut", "area"]
},
"yAxisTitle": { "type": "string" },
"yAxis": {
"type": "string",
"enum": ["sum", "amount"]
},
"field": { "type": "string" }
},
"required": ["graphName"]
},
"table": {
"type": "object",
"properties": {
"containerProps": { "$ref": "#/definitions/containerProps" },
"type": { "type": "string", "enum": ["table"] },
"filter": { "type": "boolean" },
"collection": { "type": "string" },
"title": {
"oneOf": [
{
"type": "object",
"properties": {
"de": { "type": "string" },
"en": { "type": "string" }
},
"required": ["de", "en"]
},
{ "type": "string" }
]
},
"subTitle": {
"oneOf": [
{ "type": "string" },
{
"type": "object",
"properties": {
"de": { "type": "string" },
"en": { "type": "string" }
},
"required": ["de", "en"]
}
]
},
"columns": {
"type": "array",
"items": { "type": "string" }
},
"filterGroups": {
"type": "array",
"items": { "type": "string" }
},
"additionalApiParams": {
"$ref": "#/definitions/additionalApiParams"
}
},
"required": ["type"],
"additionalProperties": false
},
"reference": {
"type": "object",
"properties": {
"type": { "type": "string", "enum": ["reference"] },
"newPageRef": { "type": "boolean" },
"collection": { "type": "string" },
"style": {
"type": "object",
"properties": {
"upper": { "type": "string" },
"lower": { "type": "string" }
}
},
"subNavigation": { "type": "number" }
},
"required": ["type"],
"additionalProperties": false
},
"minorItem": {
"type": "object",
"properties": {
"collection": { "type": "string" },
"subNavigation": { "type": "number" },
"newPageRef": { "type": "boolean" }
},
"required": ["collection"],
"additionalProperties": false
},
"containerProps": {
"type": "object",
"properties": {
"class": { "type": "string" },
"style": { "type": "string" },
"layout": {
"type": "object",
"properties": {
"breakBefore": { "type": "boolean" },
"breakAfter": { "type": "boolean" },
"size": {
"type": "object",
"properties": {
"default": { "type": "string" },
"small": { "type": "string" },
"large": { "type": "string" }
}
}
}
}
},
"additionalProperties": false
},
"additionalApiParams": {
"type": "object",
"properties": {
"offset": { "type": "number" },
"limit": { "type": "number" },
"sort": { "type": "string" },
"filter": { "type": "object", "additionalProperties": true },
"projection": { "type": "string" },
"count": { "type": "number", "enum": [1] }
},
"additionalProperties": false
},
"cssWithEval": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"eval": {
"type": "string"
}
},
"required": ["eval"],
"additionalProperties": false
},
{
"type": "object",
"patternProperties": {
"^[a-zA-Z_][a-zA-Z0-9_-]*$": {
"oneOf": [
{ "type": "string" },
{ "type": "number" }
]
}
},
"additionalProperties": false
}
]
}
}
}
-98
View File
@@ -1,98 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"evalObject": {
"type": "object",
"properties": {
"eval": {
"type": "string",
"description": "js code which must return same schema as value if directly defined"
}
}
},
"evalObjectWithRaw": {
"type": "object",
"properties": {
"eval": {
"type": "string",
"description": "js code which must return same schema as value if directly defined"
},
"raw": {
"type": "boolean",
"description": "if true, the result of the eval passed as pure html"
}
}
},
"i18nString": {
"oneOf": [
{
"type": "object",
"patternProperties": {
"^[a-z]$": {
"type": "string"
}
}
},
{
"type": "string"
}
]
},
"evalExpressions": {
"oneOf": [
{
"type": "object",
"additionalProperties": true,
"properties": {
"twig": {
"type": "string",
"description": "twig template"
},
"projection": {
"type": "string",
"description": "query projection to use"
}
},
"required": ["twig"]
},
{
"type": "object",
"additionalProperties": true,
"properties": {
"eval": {
"type": "string",
"description": "javascript code"
},
"projection": {
"type": "string",
"description": "query projection to use"
}
},
"required": ["eval"]
}
]
},
"fieldSource": {
"oneOf": [
{
"$ref": "#/definitions/fieldPath"
},
{
"type": "object",
"properties": {
"source": {
"$ref": "#/definitions/fieldPath"
}
}
}
]
},
"fieldPath": {
"type": "string",
"description": "field, sub fields separated with dot (.)",
"pattern": "^[a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+)*$"
}
}
}
-162
View File
@@ -1,162 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server field configuration",
"description": "tibi-server field linter",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x\\-": {
"description": "template property"
}
},
"properties": {
"name": {
"type": "string",
"description": "name of field",
"pattern": "^[0-9a-zA-Z_]+$"
},
"type": {
"enum": [
"string",
"string[]",
"number",
"number[]",
"boolean",
"object",
"object[]",
"file",
"file[]",
"date",
"any"
]
},
"index": {
"type": "array",
"items": {
"enum": [
"single",
"unique",
"text",
"sparse",
"background"
]
}
},
"subFields": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"type": "array",
"description": "sub fields of object",
"items": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "#"
}
]
}
}
]
},
"validator": {
"type": "object",
"description": "field validator",
"additionalProperties": false,
"properties": {
"required": {
"type": "boolean",
"description": "force field as required"
},
"allowZero": {
"type": "boolean",
"description": "allow for required fields that the value can be an empty string or 0 for number type"
},
"eval": {
"type": "string",
"description": "javascript validator which failes if evaluates to false or string as error message, with following variables: $this, $parent, $stack, $auth, context"
},
"minLength": {
"type": "number",
"description": "minimum string length"
},
"maxLength": {
"type": "number",
"description": "maximum string length"
},
"pattern": {
"type": "string",
"description": "regex pattern the value must match"
},
"min": {
"type": "number",
"description": "minimum value for number fields"
},
"max": {
"type": "number",
"description": "maximum value for number fields"
},
"in": {
"type": "array",
"description": "array of allowed values"
},
"maxFileSize": {
"type": "string",
"description": "maximum decoded file size for file and file[] fields (e.g. '500KB')"
},
"accept": {
"type": "array",
"description": "allowed MIME types for file and file[] fields; supports wildcards like 'image/*'",
"items": {
"type": "string"
}
}
}
},
"readonly": {
"description": "field-level readonly — boolean or JS eval expression",
"oneOf": [
{ "type": "boolean" },
{
"type": "object",
"additionalProperties": false,
"properties": {
"eval": { "type": "string", "description": "JS expression that returns boolean" }
},
"required": ["eval"]
}
]
},
"hidden": {
"description": "field-level hidden — boolean or JS eval expression",
"oneOf": [
{ "type": "boolean" },
{
"type": "object",
"additionalProperties": false,
"properties": {
"eval": { "type": "string", "description": "JS expression that returns boolean" }
},
"required": ["eval"]
}
]
},
"strictFields": {
"type": "boolean",
"description": "reject unknown sub-fields not defined in subFields"
},
"meta": {
"$ref": "fieldMeta.json"
}
},
"required": [
"name",
"type"
]
}
-17
View File
@@ -1,17 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server field array configuration",
"description": "tibi-server collection linter",
"type": "array",
"items": {
"oneOf": [
{
"$comment": "for include tag",
"type": "string"
},
{
"$ref": "field.json"
}
]
}
}
File diff suppressed because it is too large Load Diff
-148
View File
@@ -1,148 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server hooks configuration",
"description": "tibi-server hooks configuration",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x\\-": {
"description": "template property"
}
},
"properties": {
"get": {
"type": "object",
"description": "hooks for http GET",
"additionalProperties": false,
"properties": {
"read": {
"description": "hook before reading from database",
"$ref": "#/definitions/hookDef"
},
"return": {
"description": "hook before returning entries read from database",
"$ref": "#/definitions/hookDef"
},
"file": {
"description": "hook for file download requests (GET /collection/:id/:field/*path)",
"$ref": "#/definitions/hookDef"
}
}
},
"post": {
"type": "object",
"description": "hooks for http POST",
"additionalProperties": false,
"properties": {
"bind": {
"description": "hook before binding data from post request",
"$ref": "#/definitions/hookDef"
},
"validate": {
"description": "hook before validation data",
"$ref": "#/definitions/hookDef"
},
"create": {
"description": "hook before creating entry in database",
"$ref": "#/definitions/hookDef"
},
"return": {
"description": "hook before returning result (after database write)",
"$ref": "#/definitions/hookDef"
},
"bulkCreate": {
"description": "hook for bulk create (POST with JSON array) — optimised single-DB-call path",
"$ref": "#/definitions/hookDef"
},
"bulkReturn": {
"description": "hook before returning bulk create result",
"$ref": "#/definitions/hookDef"
}
}
},
"put": {
"type": "object",
"description": "hooks for http PUT",
"additionalProperties": false,
"properties": {
"bind": {
"description": "hook before binding data from put request",
"$ref": "#/definitions/hookDef"
},
"validate": {
"description": "hook before validation data",
"$ref": "#/definitions/hookDef"
},
"update": {
"description": "hook before updating entry in database",
"$ref": "#/definitions/hookDef"
},
"return": {
"description": "hook before returning result (after database write)",
"$ref": "#/definitions/hookDef"
},
"bulkUpdate": {
"description": "hook for bulk update (PUT without ID) — optimised single-DB-call path",
"$ref": "#/definitions/hookDef"
},
"bulkReturn": {
"description": "hook before returning bulk update result",
"$ref": "#/definitions/hookDef"
}
}
},
"delete": {
"type": "object",
"description": "hooks for http DELETE",
"additionalProperties": false,
"properties": {
"delete": {
"description": "hook before deleting entry from database",
"$ref": "#/definitions/hookDef"
},
"return": {
"description": "hook before returning result (after database write)",
"$ref": "#/definitions/hookDef"
},
"bulkDelete": {
"description": "hook for bulk delete (DELETE without ID) — optimised single-DB-call path",
"$ref": "#/definitions/hookDef"
},
"bulkReturn": {
"description": "hook before returning bulk delete result",
"$ref": "#/definitions/hookDef"
}
}
},
"audit": {
"type": "object",
"description": "hooks for audit log entries",
"additionalProperties": false,
"properties": {
"return": {
"description": "hook before returning audit log entries for this collection, can be used to remove sensitive fields from snapshots",
"$ref": "#/definitions/hookDef"
}
}
}
},
"definitions": {
"hookDef": {
"type": "object",
"properties": {
"type": {
"const": "javascript"
},
"file": {
"type": "string",
"description": "location of javascript hook file relative to config.yml base"
},
"timeout": {
"type": "integer",
"description": "execution timeout in seconds"
}
},
"required": ["type", "file"]
}
}
}
-102
View File
@@ -1,102 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server imageFilter configuration",
"description": "tibi-server imageFilter linter",
"type": "object",
"patternProperties": {
"^x\\-": {
"description": "template property"
},
"^[a-zA-Z0-9_-]+$": {
"type": "array",
"items": {
"type": "object",
"properties": {
"fit": {
"type": "boolean"
},
"fill": {
"type": "boolean"
},
"width": {
"type": "number"
},
"height": {
"type": "number"
},
"blur": {
"type": "number"
},
"brightness": {
"type": "number"
},
"contrast": {
"type": "number"
},
"gamma": {
"type": "number"
},
"saturation": {
"type": "number"
},
"sharpen": {
"type": "number"
},
"invert": {
"type": "boolean"
},
"grayscale": {
"type": "boolean"
},
"resampling": {
"enum": [
"lanczos",
"nearestNeighbor",
"hermite",
"linear",
"catmullRom",
"box",
"mitchellNetravili",
"bSpline",
"gaussian",
"bartlett",
"hann",
"hamming",
"blackman",
"welch",
"cosine"
]
},
"anchor": {
"enum": [
"center",
"topLeft",
"top",
"topRight",
"left",
"right",
"bottomLeft",
"bottom",
"bottomRight"
]
},
"quality": {
"type": "number"
},
"lossless": {
"type": "boolean"
},
"skipLargerDimension": {
"type": "boolean"
},
"skipLargerFilesize": {
"type": "boolean"
},
"outputType": {
"enum": ["jpg", "jpeg", "png", "webp"]
}
}
}
}
}
}
-50
View File
@@ -1,50 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server index configuration",
"description": "tibi-server index linter",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x\\-": {
"description": "template property"
}
},
"properties": {
"name": {
"type": "string",
"description": "name of index"
},
"key": {
"type": "array",
"description": "array of keys, minus in front for reverse order",
"items": {
"type": "string"
}
},
"unique": {
"type": "boolean",
"description": "unique index"
},
"dropDups": {
"type": "boolean",
"description": "drop duplicates"
},
"background": {
"type": "boolean",
"description": "build index in background"
},
"sparse": {
"type": "boolean",
"description": "sparse index"
},
"defaultLanguage": {
"type": "string",
"description": "default language for text index"
},
"languageOverride": {
"type": "string",
"description": "language override field name"
}
},
"required": ["key"]
}
-36
View File
@@ -1,36 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server cronjob configuration",
"description": "tibi-server cronjob linter",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x\\-": {
"description": "template property"
}
},
"properties": {
"meta": {
"type": "object",
"description": "meta object used to pass parameters to identify cronjob",
"additionalProperties": true
},
"cron": {
"type": "string",
"description": "cronjob time/interval specification"
},
"type": {
"const": "javascript",
"description": "type of job"
},
"file": {
"type": "string",
"description": "javascript file relative to config.yml"
},
"timeout": {
"type": "integer",
"description": "execution timeout in seconds"
}
},
"required": ["type", "file"]
}
-128
View File
@@ -1,128 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server permissions configuration",
"description": "tibi-server permissions linter",
"type": "object",
"additionalProperties": false,
"properties": {
"public": {
"description": "permissions for unauthorized public access",
"$ref": "#/definitions/permissionSet"
},
"user": {
"description": "permissions for authorized users (nativ tibi-server auth)",
"$ref": "#/definitions/permissionSet"
}
},
"patternProperties": {
"^x\\-": {
"description": "template property"
},
"^token:": {
"description": "permissions for header or query token",
"$ref": "#/definitions/permissionSet"
},
"^[a-zA-Z0-9_]+$": {
"description": "custom permissions",
"$ref": "#/definitions/permissionSet"
}
},
"required": ["public", "user"],
"definitions": {
"permissionSet": {
"type": "object",
"additionalProperties": false,
"properties": {
"methods": {
"type": "object",
"description": "permissions for http methods",
"additionalProperties": false,
"properties": {
"get": {
"oneOf": [
{ "type": "boolean" },
{
"type": "object",
"properties": {
"allow": { "type": "boolean", "description": "Allow GET." }
},
"required": ["allow"],
"additionalProperties": false
}
]
},
"post": {
"oneOf": [
{ "type": "boolean" },
{
"type": "object",
"properties": {
"allow": { "type": "boolean", "description": "Allow single-document POST." },
"bulk": { "type": "boolean", "description": "Allow bulk POST (JSON array body)." }
},
"required": ["allow"],
"additionalProperties": false
}
]
},
"put": {
"oneOf": [
{ "type": "boolean" },
{
"type": "object",
"properties": {
"allow": { "type": "boolean", "description": "Allow single-document PUT." },
"bulk": { "type": "boolean", "description": "Allow bulk PUT (without ID)." }
},
"required": ["allow"],
"additionalProperties": false
}
]
},
"delete": {
"oneOf": [
{ "type": "boolean" },
{
"type": "object",
"properties": {
"allow": { "type": "boolean", "description": "Allow single-document DELETE." },
"bulk": { "type": "boolean", "description": "Allow bulk DELETE (without ID)." }
},
"required": ["allow"],
"additionalProperties": false
}
]
}
}
},
"validProjections": {
"type": "array",
"description": "list of projection names this permission set is allowed to use",
"items": {
"type": "string"
}
},
"filter": {
"type": "object",
"description": "MongoDB filter applied to all queries for this permission set",
"additionalProperties": true
},
"readonlyFields": {
"type": "array",
"description": "fields that are read-only for this permission set",
"items": {
"type": "string"
}
},
"hiddenFields": {
"type": "array",
"description": "fields that are hidden for this permission set",
"items": {
"type": "string"
}
}
},
"required": ["methods"]
}
}
}
-31
View File
@@ -1,31 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema tibi-server imageFilter configuration",
"description": "tibi-server projections linter",
"type": "object",
"patternProperties": {
"^x\\-": {
"description": "template property"
},
"^[a-zA-Z0-9_-]+$": {
"type": "object",
"description": "dataset query projection config",
"properties": {
"select": {
"oneOf": [
{ "type": "null" },
{
"type": "object",
"description": "mongo db selector",
"patternProperties": {
"^[a-zA-Z0-9_]+(\\.[a-zA-Z0-9]+)*$": {
"enum": [0, 1]
}
}
}
]
}
}
}
}
}
+434
View File
@@ -0,0 +1,434 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "action.schema.json",
"title": "Tibi action config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"name": {
"type": "string",
"pattern": "^[0-9A-Za-z_-]+$"
},
"meta": {
"$ref": "action.schema.json#/definitions/actionMeta"
},
"permissions": {
"$ref": "action.schema.json#/definitions/actionPermissions"
},
"hooks": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "hooks.schema.json"
}
]
}
},
"required": [
"name"
],
"definitions": {
"actionField": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"name": {
"type": "string",
"pattern": "^[0-9A-Za-z_]+$"
},
"type": {
"type": "string",
"enum": [
"string",
"string[]",
"number",
"number[]",
"boolean",
"object",
"object[]",
"file",
"file[]",
"date",
"any"
]
},
"index": {
"type": "array",
"items": {
"type": "string",
"enum": [
"single",
"unique",
"text",
"sparse",
"background"
]
}
},
"subFields": {
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "action.schema.json#/definitions/actionField"
}
]
}
}
]
},
"validator": {
"$ref": "field.schema.json#/definitions/field/properties/validator"
},
"readonly": {
"$ref": "defs.schema.json#/definitions/boolOrEval"
},
"hidden": {
"$ref": "defs.schema.json#/definitions/boolOrEval"
},
"strictFields": {
"type": "boolean"
},
"meta": {
"$ref": "field-meta.schema.json"
}
},
"required": [
"name",
"type"
]
},
"actionMappedField": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"source": {
"$ref": "defs.schema.json#/definitions/fieldPath"
},
"name": {
"type": "string",
"pattern": "^[0-9A-Za-z_]+$"
},
"type": {
"type": "string",
"enum": [
"string",
"string[]",
"number",
"number[]",
"boolean",
"object",
"object[]",
"file",
"file[]",
"date",
"any"
]
},
"subFields": {
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "action.schema.json#/definitions/actionMappedField"
}
]
}
}
]
},
"meta": {
"$ref": "field-meta.schema.json"
}
},
"required": [
"type"
],
"anyOf": [
{
"required": [
"source"
]
},
{
"required": [
"name"
]
}
]
},
"actionFieldSection": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"title": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"description": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"fields": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "action.schema.json#/definitions/actionField"
}
]
}
}
}
},
"actionExecutionMeta": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"kind": {
"type": "string"
},
"cancellable": {
"type": "boolean"
}
}
},
"actionOutputProgressMapping": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"indexField": {
"$ref": "defs.schema.json#/definitions/fieldPath"
},
"countField": {
"$ref": "defs.schema.json#/definitions/fieldPath"
},
"statusField": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
}
]
},
"messageField": {
"$ref": "defs.schema.json#/definitions/fieldPath"
},
"fields": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "action.schema.json#/definitions/actionMappedField"
}
]
}
}
}
},
"actionOutputMappingSection": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"fields": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "action.schema.json#/definitions/actionMappedField"
}
]
}
}
}
},
"actionOutputMapping": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"summary": {
"$ref": "action.schema.json#/definitions/actionOutputMappingSection"
},
"details": {
"$ref": "action.schema.json#/definitions/actionOutputMappingSection"
},
"progress": {
"$ref": "action.schema.json#/definitions/actionOutputProgressMapping"
}
}
},
"actionOutputMeta": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"title": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"mapping": {
"$ref": "action.schema.json#/definitions/actionOutputMapping"
}
}
},
"actionMethodMeta": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"query": {
"$ref": "action.schema.json#/definitions/actionFieldSection"
},
"data": {
"$ref": "action.schema.json#/definitions/actionFieldSection"
},
"execution": {
"$ref": "action.schema.json#/definitions/actionExecutionMeta"
},
"output": {
"$ref": "action.schema.json#/definitions/actionOutputMeta"
}
}
},
"actionMeta": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"muiIcon": {
"type": "string"
},
"description": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"group": {
"type": "string"
},
"hide": {
"type": "boolean"
},
"methods": {
"type": "object",
"patternProperties": {
"^x-": {},
"^[a-zA-Z0-9_-]+$": {
"$ref": "action.schema.json#/definitions/actionMethodMeta"
}
},
"additionalProperties": false
}
}
},
"actionPermissionSet": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"methods": {
"type": "object",
"additionalProperties": false,
"properties": {
"get": {
"$ref": "defs.schema.json#/definitions/methodPermissionGet"
},
"post": {
"$ref": "defs.schema.json#/definitions/methodPermissionWrite"
}
}
}
},
"required": [
"methods"
]
},
"actionPermissions": {
"type": "object",
"additionalProperties": false,
"properties": {
"public": {
"$ref": "action.schema.json#/definitions/actionPermissionSet"
},
"user": {
"$ref": "action.schema.json#/definitions/actionPermissionSet"
}
},
"patternProperties": {
"^x-": {},
"^token:[^\\s]+$": {
"$ref": "action.schema.json#/definitions/actionPermissionSet"
},
"^[a-zA-Z0-9_]+$": {
"$ref": "action.schema.json#/definitions/actionPermissionSet"
}
},
"required": [
"public",
"user"
]
}
}
}
+22
View File
@@ -0,0 +1,22 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "asset.schema.json",
"title": "Tibi asset config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"name": {
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"name",
"path"
]
}
+380
View File
@@ -0,0 +1,380 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "collection-meta.schema.json",
"title": "Tibi collection meta config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"muiIcon": {
"type": "string"
},
"group": {
"type": "string"
},
"imageUrl": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"hide": {
"type": "boolean"
},
"singleton": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean"
},
"key": {
"type": "string"
}
},
"required": [
"enabled"
]
},
"subNavigation": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"muiIcon": {
"type": "string"
},
"filter": {
"type": "object",
"additionalProperties": true
},
"defaultSort": {
"type": "object",
"additionalProperties": false,
"properties": {
"field": {
"$ref": "defs.schema.json#/definitions/sortField"
},
"order": {
"type": "string",
"enum": [
"ASC",
"DESC"
]
}
},
"required": [
"field"
]
},
"setDefault": {
"type": "object",
"additionalProperties": false,
"description": "Pre-fill a field with a default value when creating a new entry while this subNav tab is active.",
"properties": {
"field": {
"type": "string"
},
"value": {}
},
"required": [
"field",
"value"
]
}
},
"required": [
"name"
]
}
},
"preview": {
"$ref": "defs.schema.json#/definitions/previewConfig"
},
"i18n": {
"oneOf": [
{
"type": "boolean",
"enum": [
false
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"defaultLanguage": {
"type": "string"
},
"languages": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"code": {
"type": "string"
},
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
}
},
"required": [
"code"
]
}
},
"entry": {
"type": "object",
"additionalProperties": false,
"properties": {
"languageField": {
"type": "string"
},
"groupField": {
"type": "string"
},
"clearFields": {
"type": "array",
"items": {
"type": "string"
}
},
"copyFields": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"languageField",
"groupField"
]
}
}
}
]
},
"defaultSort": {
"type": "object",
"additionalProperties": false,
"properties": {
"field": {
"$ref": "defs.schema.json#/definitions/sortField"
},
"order": {
"type": "string",
"enum": [
"ASC",
"DESC",
"MANUALLY"
]
}
},
"required": [
"field"
]
},
"viewHint": {
"oneOf": [
{
"type": "string",
"enum": [
"table",
"cards"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"media": {
"type": "object",
"additionalProperties": false,
"properties": {
"upload": {
"type": "object",
"additionalProperties": false,
"properties": {
"autoFill": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"ai": {
"type": "object",
"additionalProperties": false,
"properties": {
"targetField": {
"type": "string"
},
"prompt": {
"type": "string"
},
"image": {
"type": "object",
"additionalProperties": false,
"properties": {
"maxWidth": {
"type": "number",
"exclusiveMinimum": 0
},
"maxHeight": {
"type": "number",
"exclusiveMinimum": 0
},
"quality": {
"type": "number",
"exclusiveMinimum": 0,
"maximum": 1
}
}
}
}
}
}
},
"navigation": {
"type": "object",
"additionalProperties": false,
"properties": {
"nodesField": {
"type": "string"
},
"preview": {
"$ref": "defs.schema.json#/definitions/previewConfig"
},
"declaredTrees": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"singleton": {
"type": "object",
"additionalProperties": true
},
"maxLevel": {
"type": "number"
}
},
"required": [
"singleton"
]
}
}
}
}
},
"oneOf": [
{
"required": [
"media"
]
},
{
"required": [
"navigation"
]
}
]
}
]
},
"pagebuilder": {
"type": "object",
"additionalProperties": false,
"properties": {
"defaultViewport": {
"$ref": "defs.schema.json#/definitions/pagebuilderViewport"
},
"blockTypeField": {
"type": "string"
},
"blockRegistry": {
"type": "object",
"additionalProperties": false,
"properties": {
"file": {
"type": "string"
}
},
"required": [
"file"
]
},
"screenshot": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"field": {
"$ref": "defs.schema.json#/definitions/fieldPath"
},
"fileField": {
"$ref": "defs.schema.json#/definitions/fieldPath"
},
"screenWidth": {
"type": "integer",
"minimum": 1
},
"imageWidth": {
"type": "integer",
"minimum": 1
}
},
"required": [
"field",
"fileField"
]
}
}
}
},
"sidebar": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"group": {
"type": "string"
},
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
}
},
"required": [
"group"
]
}
},
"openapi": {
"$ref": "openapi.schema.json"
}
}
}
+431
View File
@@ -0,0 +1,431 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "collection.schema.json",
"title": "Tibi collection config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"name": {
"type": "string"
},
"defaultLanguage": {
"type": "string"
},
"uploadPath": {
"type": "string"
},
"upload": {
"$ref": "collection.schema.json#/definitions/uploadConfig"
},
"permissions": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "permissions.schema.json"
}
]
},
"projections": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "projections.schema.json"
}
]
},
"hooks": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "hooks.schema.json"
}
]
},
"meta": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "collection-meta.schema.json"
}
]
},
"imageFilter": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "image-filter.schema.json"
}
]
},
"fields": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "field-list.schema.json"
}
]
},
"indexes": {
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "collection.schema.json#/definitions/indexConfig"
}
]
}
}
]
},
"audit": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean"
},
"actions": {
"type": "array",
"items": {
"type": "string",
"enum": [
"create",
"update",
"delete",
"bulkCreate",
"bulkUpdate",
"bulkDelete"
]
}
}
}
},
"bulk": {
"type": "object",
"additionalProperties": false,
"properties": {
"optimize": {
"type": "object",
"additionalProperties": false,
"properties": {
"create": {
"type": "boolean"
},
"update": {
"type": "boolean"
},
"delete": {
"type": "boolean"
}
}
}
}
},
"queryLimits": {
"type": "object",
"additionalProperties": false,
"properties": {
"defaultLimit": {
"type": "integer",
"minimum": 0
},
"maxLimit": {
"type": "integer",
"minimum": 0
}
}
},
"readonlyFields": {
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
},
"hiddenFields": {
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
},
"strictFields": {
"type": "boolean"
},
"search": {
"type": "array",
"items": {
"$ref": "collection.schema.json#/definitions/searchConfig"
}
}
},
"required": [
"name",
"permissions"
],
"definitions": {
"uploadConfig": {
"type": "object",
"additionalProperties": false,
"properties": {
"maxBodySize": {
"type": "string"
},
"allowedMimeTypes": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"indexConfig": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"key": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"unique": {
"type": "boolean"
},
"dropDups": {
"type": "boolean"
},
"background": {
"type": "boolean"
},
"sparse": {
"type": "boolean"
},
"defaultLanguage": {
"type": "string"
},
"languageOverride": {
"type": "string"
}
},
"required": [
"key"
]
},
"searchConfig": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"mode": {
"type": "string",
"enum": [
"text",
"regex",
"eval",
"filter",
"ngram",
"vector",
"combined"
]
},
"fields": {
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
},
"meta": {
"type": "object",
"additionalProperties": true
},
"eval": {
"type": "string"
},
"filter": {
"type": "object",
"additionalProperties": true
},
"ngram": {
"type": "object",
"additionalProperties": false,
"properties": {
"sizes": {
"type": "array",
"items": {
"type": "integer",
"minimum": 1
}
},
"normalize": {
"type": "object",
"additionalProperties": false,
"properties": {
"use": {
"type": "array",
"items": {
"type": "string"
}
},
"eval": {
"type": "string"
}
}
}
}
},
"regex": {
"type": "object",
"additionalProperties": false,
"properties": {
"weights": {
"type": "object",
"additionalProperties": {
"type": "number"
}
},
"scoring": {
"type": "string",
"enum": [
"count",
"binary",
"log"
]
}
}
},
"score": {
"type": "object",
"additionalProperties": false,
"properties": {
"expr": {
"type": "object",
"additionalProperties": true
}
}
},
"vector": {
"type": "object",
"additionalProperties": false,
"properties": {
"provider": {
"type": "string"
},
"documentPrefix": {
"type": "string"
},
"queryPrefix": {
"type": "string"
},
"overflow": {
"type": "string",
"enum": [
"truncate",
"chunk"
]
},
"chunkSize": {
"type": "integer",
"minimum": 1
},
"chunkOverlap": {
"type": "integer",
"minimum": 0
}
},
"required": [
"provider"
]
},
"rrf": {
"type": "object",
"additionalProperties": false,
"properties": {
"k": {
"type": "integer",
"minimum": 1
},
"topK": {
"type": "integer",
"minimum": 1
},
"weights": {
"type": "object",
"additionalProperties": {
"type": "number"
}
},
"strategy": {
"type": "string",
"enum": ["rrf", "score_rrf", "score_sum", "rank_score", "hybrid"]
},
"normalize": {
"type": "string",
"enum": ["none", "minmax", "zscore"]
},
"scoreWeight": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"sourceConfig": {
"type": "object",
"additionalProperties": {
"type": "object",
"additionalProperties": false,
"properties": {
"scoreWeight": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"boost": {
"type": "number",
"minimum": 0
}
}
}
}
}
},
"async": {
"type": "boolean"
},
"autoRegenerate": {
"type": "boolean"
}
},
"required": [
"name",
"mode"
]
}
}
}
+508
View File
@@ -0,0 +1,508 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "defs.schema.json",
"title": "Shared definitions for Tibi config schemas",
"definitions": {
"i18nText": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"minProperties": 1,
"patternProperties": {
"^[a-z]{2}(-[A-Za-z0-9_]+)?$": {
"type": "string"
}
},
"additionalProperties": false
}
]
},
"fieldPath": {
"type": "string",
"pattern": "^[a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+)*$"
},
"evalString": {
"type": "object",
"additionalProperties": false,
"properties": {
"eval": {
"type": "string"
},
"select": {
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
}
},
"required": [
"eval"
]
},
"evalHtml": {
"type": "object",
"additionalProperties": false,
"properties": {
"eval": {
"type": "string"
},
"raw": {
"type": "boolean"
}
},
"required": [
"eval"
]
},
"boolOrEval": {
"oneOf": [
{
"type": "boolean"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"boolOrUiCondition": {
"oneOf": [
{
"type": "boolean"
},
{
"type": "string"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"uiCondition": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"sortField": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"source": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
},
"required": [
"source"
]
}
]
},
"pagebuilderViewport": {
"oneOf": [
{
"type": "integer",
"minimum": 1
},
{
"type": "string",
"enum": [
"desktop",
"tablet",
"phone"
]
}
]
},
"badgeVariant": {
"type": "string",
"enum": [
"success",
"error",
"warning",
"info",
"neutral"
]
},
"choiceItem": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": [
"string",
"number",
"boolean",
"null"
]
},
"value": {
"type": [
"string",
"number",
"boolean",
"null"
]
},
"name": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"description": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"badgeVariant": {
"$ref": "defs.schema.json#/definitions/badgeVariant"
},
"chipVariant": {
"$ref": "defs.schema.json#/definitions/badgeVariant"
},
"badgeStyle": {
"type": "object",
"description": "Flat inline CSS properties for badge/chip rendering. Supports camelCase, kebab-case, and CSS custom properties. `bg`/`text` are aliases for `background`/`color`.",
"additionalProperties": {
"type": [
"string",
"number",
"boolean"
]
}
},
"chipStyle": {
"type": "object",
"description": "Alias for badgeStyle with the same value shape.",
"additionalProperties": {
"type": [
"string",
"number",
"boolean"
]
}
}
},
"anyOf": [
{
"required": [
"id"
]
},
{
"required": [
"value"
]
}
],
"anyOfComment": "Choice labels are optional for now because some block-type helper lists are resolved elsewhere."
},
"choices": {
"oneOf": [
{
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/choiceItem"
}
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"endpoint": {
"type": "string"
},
"mapping": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"params": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"endpoint"
]
}
]
},
"previewTableColumn": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"source": {
"$ref": "defs.schema.json#/definitions/fieldPath"
},
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"align": {
"type": "string",
"enum": [
"left",
"center",
"right"
]
},
"eval": {
"type": "string"
},
"raw": {
"type": "boolean"
},
"select": {
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
}
},
"anyOf": [
{
"required": [
"source"
]
},
{
"required": [
"eval"
]
}
]
}
]
},
"previewSlots": {
"type": "object",
"additionalProperties": false,
"properties": {
"label": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"labelStyle": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"secondary": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"tertiary": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"badge": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"image": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"imageFallback": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"mediaFile": {
"$ref": "defs.schema.json#/definitions/fieldPath"
},
"eval": {
"type": "string"
},
"raw": {
"type": "boolean"
},
"select": {
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
},
"table": {
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/previewTableColumn"
}
}
},
"anyOf": [
{
"required": [
"label"
]
},
{
"required": [
"secondary"
]
},
{
"required": [
"tertiary"
]
},
{
"required": [
"badge"
]
},
{
"required": [
"image"
]
},
{
"required": [
"table"
]
}
]
},
"previewConfig": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"$ref": "defs.schema.json#/definitions/evalHtml"
},
{
"$ref": "defs.schema.json#/definitions/previewSlots"
}
]
},
"foreignRender": {
"oneOf": [
{
"$ref": "defs.schema.json#/definitions/fieldPath"
},
{
"$ref": "defs.schema.json#/definitions/evalHtml"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"defaultCollectionViews": {
"type": "boolean"
}
},
"required": [
"defaultCollectionViews"
]
},
{
"$ref": "defs.schema.json#/definitions/previewSlots"
}
]
},
"methodPermissionGet": {
"oneOf": [
{
"type": "boolean"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"allow": {
"type": "boolean"
}
},
"required": [
"allow"
]
}
]
},
"methodPermissionWrite": {
"oneOf": [
{
"type": "boolean"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"allow": {
"type": "boolean"
},
"bulk": {
"type": "boolean"
}
},
"required": [
"allow"
]
}
]
}
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "field-list.schema.json",
"title": "Tibi field list config",
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "field.schema.json"
}
]
}
}
+305
View File
@@ -0,0 +1,305 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "field-meta.schema.json",
"title": "Tibi field meta config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"widget": {
"type": "string",
"enum": [
"text",
"textarea",
"checkbox",
"switch",
"select",
"selectArray",
"chipArray",
"date",
"datetime",
"file",
"image",
"json",
"richtext",
"html",
"foreignKey",
"foreignKeyChipArray",
"foreignFile",
"foreignMedia",
"pagebuilder",
"pageBuilder",
"containerLessObject",
"containerLessObjectArray",
"color"
]
},
"i18n": {
"const": false
},
"helperText": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"hideLabel": {
"type": "boolean"
},
"hide": {
"type": "boolean"
},
"protected": {
"$ref": "defs.schema.json#/definitions/boolOrUiCondition"
},
"position": {
"type": "string",
"pattern": "^(main|sidebar|sidebar:.+)$"
},
"section": {
"type": "string"
},
"containerProps": {
"type": "object",
"additionalProperties": false,
"properties": {
"class": {
"type": "string"
},
"layout": {
"type": "object",
"additionalProperties": false,
"properties": {
"breakBefore": {
"type": "boolean"
},
"breakAfter": {
"type": "boolean"
},
"size": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"default": {
"type": "string"
},
"small": {
"type": "string"
},
"large": {
"type": "string"
}
}
}
]
}
}
}
}
},
"defaultValue": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
},
{
"type": "array"
},
{
"type": "object"
}
]
},
"dependsOn": {
"$ref": "defs.schema.json#/definitions/uiCondition"
},
"inputProps": {
"type": "object",
"additionalProperties": true
},
"choices": {
"$ref": "defs.schema.json#/definitions/choices"
},
"foreign": {
"type": "object",
"additionalProperties": false,
"properties": {
"collection": {
"type": "string"
},
"id": {
"type": "string"
},
"sort": {
"type": "string"
},
"projection": {
"type": "string"
},
"filter": {
"type": "object",
"additionalProperties": true
},
"createDefaults": {
"type": "object",
"additionalProperties": true
},
"subNavigation": {
"type": "integer",
"minimum": 0
},
"render": {
"$ref": "defs.schema.json#/definitions/foreignRender"
},
"autoFill": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"required": [
"collection"
]
},
"downscale": {
"type": "object",
"additionalProperties": false,
"properties": {
"maxWidth": {
"type": "number"
},
"maxHeight": {
"type": "number"
},
"quality": {
"type": "number"
}
}
},
"imageEditor": {
"oneOf": [
{
"type": "boolean"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"crop": {
"type": "boolean"
},
"rotate": {
"type": "boolean"
},
"flip": {
"type": "boolean"
},
"focalPoint": {
"type": "boolean"
},
"adjust": {
"type": "boolean"
},
"palette": {
"type": "boolean"
}
}
}
]
},
"drillDown": {
"type": "boolean"
},
"pageSize": {
"type": "integer",
"minimum": 0
},
"preview": {
"$ref": "defs.schema.json#/definitions/previewConfig"
},
"addElementLabel": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"filter": {
"oneOf": [
{
"type": "boolean",
"description": "Set to true to opt-in this field as a filterable field in the admin UI, or false to explicitly exclude it."
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"enum": [
"default",
"select",
"bool",
"boolean",
"input",
"number",
"foreignKey"
]
},
"facets": {
"type": "boolean"
}
}
}
]
},
"pagebuilder": {
"type": "object",
"additionalProperties": false,
"properties": {
"defaultViewport": {
"$ref": "defs.schema.json#/definitions/pagebuilderViewport"
},
"blockTypeField": {
"type": "string"
},
"mode": {
"type": "string",
"enum": [
"overlay",
"inline",
"both"
]
},
"blockRegistry": {
"type": "object",
"additionalProperties": false,
"properties": {
"file": {
"type": "string"
}
},
"required": [
"file"
]
}
}
},
"openapi": {
"$ref": "openapi.schema.json#/definitions/fieldOpenapi"
}
}
}
+171
View File
@@ -0,0 +1,171 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "field.schema.json",
"title": "Tibi field config",
"$ref": "#/definitions/field",
"definitions": {
"field": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"name": {
"type": "string",
"pattern": "^[0-9A-Za-z_]+$"
},
"type": {
"type": "string",
"enum": [
"string",
"string[]",
"number",
"number[]",
"boolean",
"object",
"object[]",
"file",
"file[]",
"date",
"any"
]
},
"index": {
"type": "array",
"items": {
"type": "string",
"enum": [
"single",
"unique",
"text",
"sparse",
"background"
]
}
},
"subFields": {
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/field"
}
]
}
}
]
},
"validator": {
"type": "object",
"additionalProperties": false,
"properties": {
"required": {
"type": "boolean"
},
"allowZero": {
"type": "boolean"
},
"format": {
"type": "string",
"enum": ["email", "url", "uuid", "slug"]
},
"eval": {
"type": "string"
},
"minItems": {
"type": "number"
},
"maxItems": {
"type": "number"
},
"minLength": {
"type": "number"
},
"maxLength": {
"type": "number"
},
"pattern": {
"type": "string"
},
"min": {
"type": "number"
},
"max": {
"type": "number"
},
"minDate": {
"type": "string"
},
"maxDate": {
"type": "string"
},
"minFileSize": {
"type": "string"
},
"in": {
"type": "array"
},
"maxFileSize": {
"type": "string"
},
"accept": {
"type": "array",
"items": {
"type": "string"
}
},
"image": {
"type": "object",
"additionalProperties": false,
"properties": {
"minWidth": {
"type": "number"
},
"maxWidth": {
"type": "number"
},
"minHeight": {
"type": "number"
},
"maxHeight": {
"type": "number"
},
"allowNonImages": {
"type": "boolean"
},
"allowUnknownDimensions": {
"type": "boolean"
}
}
}
}
},
"readonly": {
"$ref": "defs.schema.json#/definitions/boolOrEval"
},
"hidden": {
"$ref": "defs.schema.json#/definitions/boolOrEval"
},
"strictFields": {
"type": "boolean"
},
"meta": {
"$ref": "field-meta.schema.json"
}
},
"required": [
"name",
"type"
]
}
}
}
+145
View File
@@ -0,0 +1,145 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "hooks.schema.json",
"title": "Tibi hooks config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"get": {
"$ref": "hooks.schema.json#/definitions/getHooks"
},
"post": {
"$ref": "hooks.schema.json#/definitions/postHooks"
},
"put": {
"$ref": "hooks.schema.json#/definitions/putHooks"
},
"delete": {
"$ref": "hooks.schema.json#/definitions/deleteHooks"
},
"audit": {
"$ref": "hooks.schema.json#/definitions/auditHooks"
}
},
"definitions": {
"hook": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"const": "javascript"
},
"file": {
"type": "string"
},
"timeout": {
"type": "integer",
"minimum": 0
}
},
"required": [
"type",
"file"
]
},
"getHooks": {
"type": "object",
"additionalProperties": false,
"properties": {
"handle": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"read": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"return": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"file": {
"$ref": "hooks.schema.json#/definitions/hook"
}
}
},
"postHooks": {
"type": "object",
"additionalProperties": false,
"properties": {
"bind": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"validate": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"handle": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"create": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"return": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"bulkCreate": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"bulkReturn": {
"$ref": "hooks.schema.json#/definitions/hook"
}
}
},
"putHooks": {
"type": "object",
"additionalProperties": false,
"properties": {
"bind": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"validate": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"update": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"return": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"bulkUpdate": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"bulkReturn": {
"$ref": "hooks.schema.json#/definitions/hook"
}
}
},
"deleteHooks": {
"type": "object",
"additionalProperties": false,
"properties": {
"delete": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"return": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"bulkDelete": {
"$ref": "hooks.schema.json#/definitions/hook"
},
"bulkReturn": {
"$ref": "hooks.schema.json#/definitions/hook"
}
}
},
"auditHooks": {
"type": "object",
"additionalProperties": false,
"properties": {
"return": {
"$ref": "hooks.schema.json#/definitions/hook"
}
}
}
}
}
+110
View File
@@ -0,0 +1,110 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "image-filter.schema.json",
"title": "Tibi image filter config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {},
"^[a-zA-Z0-9_-]+$": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"width": {
"type": "number"
},
"height": {
"type": "number"
},
"fit": {
"type": "boolean"
},
"fill": {
"type": "boolean"
},
"resampling": {
"type": "string",
"enum": [
"nearestNeighbor",
"hermite",
"linear",
"catmullRom",
"lanczos",
"box",
"mitchellNetravili",
"bSpline",
"gaussian",
"bartlett",
"hann",
"hamming",
"blackman",
"welch",
"cosine"
]
},
"anchor": {
"type": "string",
"enum": [
"center",
"topLeft",
"top",
"topRight",
"left",
"right",
"bottomLeft",
"bottom",
"bottomRight"
]
},
"brightness": {
"type": "number"
},
"saturation": {
"type": "number"
},
"contrast": {
"type": "number"
},
"gamma": {
"type": "number"
},
"blur": {
"type": "number"
},
"sharpen": {
"type": "number"
},
"invert": {
"type": "boolean"
},
"grayscale": {
"type": "boolean"
},
"quality": {
"type": "number"
},
"lossless": {
"type": "boolean"
},
"skipLargerDimension": {
"type": "boolean"
},
"skipLargerFilesize": {
"type": "boolean"
},
"outputType": {
"type": "string",
"enum": [
"jpg",
"jpeg",
"png",
"webp"
]
}
}
}
}
}
}
+33
View File
@@ -0,0 +1,33 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "job.schema.json",
"title": "Tibi job config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"cron": {
"type": "string"
},
"type": {
"const": "javascript"
},
"file": {
"type": "string"
},
"timeout": {
"type": "integer",
"minimum": 0
},
"meta": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"type",
"file"
]
}
+187
View File
@@ -0,0 +1,187 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "openapi.schema.json",
"title": "Tibi OpenAPI collection config",
"description": "OpenAPI metadata for a collection, used to generate the project's OpenAPI 3.0 spec via /_openapi/:project",
"type": "object",
"additionalProperties": true,
"definitions": {
"i18nOrString": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"minProperties": 1,
"patternProperties": {
"^[a-z]{2}(-[A-Za-z0-9_]+)?$": {
"type": "string"
}
},
"additionalProperties": false
}
]
},
"codeSample": {
"type": "object",
"additionalProperties": true,
"properties": {
"lang": {
"type": "string",
"description": "Language identifier (e.g. Shell, JavaScript, Python)"
},
"label": {
"type": "string",
"description": "Display label for the code sample"
},
"source": {
"type": "string",
"description": "The code sample source"
}
},
"required": ["lang", "source"]
},
"responseObject": {
"type": "object",
"additionalProperties": true,
"properties": {
"description": {
"$ref": "#/definitions/i18nOrString"
},
"x-summary": {
"type": "string"
}
}
},
"operationObject": {
"type": "object",
"additionalProperties": true,
"properties": {
"disabled": {
"type": "boolean",
"description": "Exclude this operation from the generated OpenAPI spec"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "OpenAPI tags for grouping"
},
"summary": {
"$ref": "#/definitions/i18nOrString"
},
"description": {
"$ref": "#/definitions/i18nOrString"
},
"x-codeSamples": {
"type": "array",
"items": {
"$ref": "#/definitions/codeSample"
}
},
"parameters": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"type": "string"
},
"in": {
"type": "string",
"enum": ["query", "header", "path", "cookie"]
},
"description": {
"$ref": "#/definitions/i18nOrString"
},
"required": {
"type": "boolean"
},
"schema": {
"type": "object",
"additionalProperties": true
}
},
"required": ["name", "in"]
}
},
"responses": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/responseObject"
},
"propertyNames": {
"pattern": "^[1-5][0-9]{2}$|^default$"
}
},
"security": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"fieldOpenapi": {
"type": "object",
"description": "OpenAPI metadata for a collection field. Extra properties are merged into the field's schema object.",
"additionalProperties": true,
"properties": {
"disabled": {
"type": "boolean",
"description": "Exclude this field from the generated OpenAPI schema"
},
"description": {
"$ref": "#/definitions/i18nOrString"
},
"example": {},
"format": {
"type": "string",
"description": "OpenAPI format hint (e.g. date-time, email, uri)"
},
"enum": {
"type": "array",
"description": "Restrict values to a fixed set"
},
"deprecated": {
"type": "boolean"
}
}
}
},
"properties": {
"disabled": {
"type": "boolean",
"description": "Exclude this entire collection from the generated OpenAPI spec"
},
"get": {
"$ref": "#/definitions/operationObject",
"description": "OpenAPI operation overrides for the list endpoint (GET /{collection})"
},
"getOne": {
"$ref": "#/definitions/operationObject",
"description": "OpenAPI operation overrides for the single-entry endpoint (GET /{collection}/{id})"
},
"post": {
"$ref": "#/definitions/operationObject",
"description": "OpenAPI operation overrides for the create endpoint (POST /{collection})"
},
"put": {
"$ref": "#/definitions/operationObject",
"description": "OpenAPI operation overrides for the update endpoint (PUT /{collection}/{id})"
},
"delete": {
"$ref": "#/definitions/operationObject",
"description": "OpenAPI operation overrides for the delete endpoint (DELETE /{collection}/{id})"
}
}
}
+79
View File
@@ -0,0 +1,79 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "permissions.schema.json",
"title": "Tibi permissions config",
"type": "object",
"additionalProperties": false,
"properties": {
"public": {
"$ref": "permissions.schema.json#/definitions/permissionSet"
},
"user": {
"$ref": "permissions.schema.json#/definitions/permissionSet"
}
},
"patternProperties": {
"^x-": {},
"^token:[^\\s]+$": {
"$ref": "permissions.schema.json#/definitions/permissionSet"
},
"^[a-zA-Z0-9_]+$": {
"$ref": "permissions.schema.json#/definitions/permissionSet"
}
},
"required": [
"public",
"user"
],
"definitions": {
"permissionSet": {
"type": "object",
"additionalProperties": false,
"properties": {
"methods": {
"type": "object",
"additionalProperties": false,
"properties": {
"get": {
"$ref": "defs.schema.json#/definitions/methodPermissionGet"
},
"post": {
"$ref": "defs.schema.json#/definitions/methodPermissionWrite"
},
"put": {
"$ref": "defs.schema.json#/definitions/methodPermissionWrite"
},
"delete": {
"$ref": "defs.schema.json#/definitions/methodPermissionWrite"
}
}
},
"filter": {
"type": "object",
"additionalProperties": true
},
"validProjections": {
"type": "array",
"items": {
"type": "string"
}
},
"readonlyFields": {
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
},
"hiddenFields": {
"type": "array",
"items": {
"$ref": "defs.schema.json#/definitions/fieldPath"
}
}
},
"required": [
"methods"
]
}
}
}
+323
View File
@@ -0,0 +1,323 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "project.schema.json",
"title": "Tibi project config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"namespace": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]+$"
},
"meta": {
"type": "object",
"additionalProperties": false,
"properties": {
"imageUrl": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "defs.schema.json#/definitions/evalString"
}
]
},
"permissions": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
}
},
"required": [
"name"
]
}
},
"collectionGroups": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
},
"icon": {
"type": "string"
}
},
"required": [
"name"
]
}
},
"i18n": {
"type": "object",
"additionalProperties": false,
"properties": {
"defaultLanguage": {
"type": "string"
},
"languages": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"code": {
"type": "string"
},
"label": {
"$ref": "defs.schema.json#/definitions/i18nText"
}
},
"required": [
"code"
]
}
}
},
"required": [
"defaultLanguage",
"languages"
]
}
}
},
"upload": {
"$ref": "project.schema.json#/definitions/uploadConfig"
},
"collections": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "collection.schema.json"
}
]
}
},
"jobs": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "job.schema.json"
}
]
}
},
"actions": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "action.schema.json"
}
]
}
},
"assets": {
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "asset.schema.json"
}
]
}
},
"cors": {
"type": "object",
"additionalProperties": false,
"properties": {
"merge": {
"type": "boolean"
},
"allowOrigins": {
"type": "array",
"items": {
"type": "string"
}
},
"allowCredentials": {
"type": "boolean"
},
"allowHeaders": {
"type": "array",
"items": {
"type": "string"
}
},
"allowMethods": {
"type": "array",
"items": {
"type": "string"
}
},
"exposeHeaders": {
"type": "array",
"items": {
"type": "string"
}
},
"maxAge": {
"type": "integer",
"minimum": 0
}
}
},
"admin": {
"type": "object",
"additionalProperties": false,
"properties": {
"tokens": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"token": {
"type": "string"
},
"allowReload": {
"type": "boolean"
},
"allowRegenerateSearch": {
"type": "boolean"
},
"allowBackup": {
"type": "boolean",
"description": "Allow this token to download and restore project backups via the backup/restore API."
},
"allowSnapshots": {
"type": "boolean",
"description": "Allow this token to trigger, list, delete, restore, and download snapshots."
}
},
"required": [
"token"
]
}
}
}
},
"hook": {
"type": "object",
"additionalProperties": false,
"properties": {
"cache": {
"type": "object",
"additionalProperties": false,
"properties": {
"maxEntries": {
"type": "integer",
"minimum": 0
},
"defaultTTL": {
"type": "string"
}
}
},
"ratelimit": {
"type": "object",
"additionalProperties": false,
"properties": {
"backoffInitialDelay": {
"type": "string"
},
"backoffMaxDelay": {
"type": "string"
},
"backoffResetAfter": {
"type": "string"
},
"windowSize": {
"type": "string"
},
"windowMaxHits": {
"type": "integer",
"minimum": 0
}
}
}
}
},
"strictFields": {
"type": "boolean"
},
"snapshotPath": {
"type": "string",
"description": "Base directory for snapshot data, relative to configDir. Default: '{configDir}/snapshots'."
},
"snapshots": {
"type": "array",
"description": "List of snapshot profiles for automated point-in-time backups.",
"items": {
"oneOf": [
{
"type": "string"
},
{
"$ref": "snapshot.schema.json"
}
]
}
},
"legacy": {
"type": "object",
"additionalProperties": false,
"properties": {
"httpCodes": {
"type": "boolean"
}
}
}
},
"required": [
"namespace"
],
"definitions": {
"uploadConfig": {
"type": "object",
"additionalProperties": false,
"properties": {
"maxBodySize": {
"type": "string"
},
"allowedMimeTypes": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
+32
View File
@@ -0,0 +1,32 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "projections.schema.json",
"title": "Tibi projections config",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {},
"^[a-zA-Z0-9_]+$": {
"type": "object",
"additionalProperties": false,
"properties": {
"select": {
"type": [
"object",
"null"
],
"additionalProperties": {
"type": "integer",
"enum": [
0,
1
]
}
}
},
"required": [
"select"
]
}
}
}
+101
View File
@@ -0,0 +1,101 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "snapshot.schema.json",
"title": "Tibi snapshot config",
"description": "Configuration for automated point-in-time snapshots of project collections and media.",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-": {}
},
"properties": {
"name": {
"type": "string",
"description": "Unique identifier for this snapshot profile (e.g. 'content-navigation')"
},
"description": {
"type": "string",
"description": "Optional human-readable explanation of this snapshot profile"
},
"collections": {
"type": "array",
"description": "Collection filter: empty = all, include-mode = only listed, exclude-mode = all except listed. Mixed include+exclude is invalid.",
"items": {
"oneOf": [
{
"type": "string",
"description": "Shorthand for {name: '...', mode: 'include'}"
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"mode": {
"type": "string",
"enum": ["include", "exclude"],
"description": "'include' = only this collection, 'exclude' = all except this collection. Default 'include' when omitted."
}
},
"required": ["name"]
}
]
}
},
"includeMedia": {
"type": "boolean",
"description": "Whether to include media files (file/file[] fields) via hardlinks. Default: true.",
"default": true
},
"collectionDedup": {
"type": "boolean",
"description": "Enable SHA256-based deduplication of collection JSON exports. Identical exports share one canonical copy via hardlinks in .store/collections/. Default: false.",
"default": false
},
"mode": {
"type": "string",
"enum": ["json", "db", "both"],
"description": "Storage strategy for collection data. 'json' = BSON Extended JSON files on disk (current, implemented), 'db' = MongoDB $out copy (future), 'both' = both (future). Default: 'json'."
},
"retention": {
"type": "object",
"description": "Auto-pruning rules for old snapshot entries. Omit for unlimited retention.",
"additionalProperties": false,
"properties": {
"maxCount": {
"type": "integer",
"minimum": 1,
"description": "Maximum number of snapshot entries to keep. Oldest entries are pruned first."
},
"maxAge": {
"type": "string",
"description": "Maximum age of snapshot entries (e.g. '720h' = 30 days, '7d' = 7 days, '168h'). Entries older than this are pruned."
},
"maxSizeBytes": {
"type": "integer",
"minimum": 1,
"description": "Maximum total size of snapshot entries in bytes. Oldest entries are pruned first until under this limit."
}
}
},
"schedule": {
"type": "string",
"description": "Cron expression for automatic execution (e.g. '0 3 * * *' = daily 3am UTC, '@every 24h'). Empty = manual trigger only."
},
"permissions": {
"type": "array",
"description": "Bare permission names for team-based access (Phase 2). Empty = admin-only in Phase 1.",
"items": {
"type": "string"
}
},
"enabled": {
"type": "boolean",
"description": "Whether this snapshot profile is active. Disabled profiles are skipped by the scheduler but can still be triggered manually.",
"default": false
}
},
"required": ["name"]
}
+110
View File
@@ -0,0 +1,110 @@
import fs from "node:fs"
import path from "node:path"
import { fileURLToPath } from "node:url"
import Ajv from "ajv"
import addFormats from "ajv-formats"
import { globSync } from "glob"
import yaml from "js-yaml"
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const repoRoot = path.resolve(__dirname, "..")
const schemaDir = path.join(repoRoot, "schemas", "config")
const includeType = new yaml.Type("!include", {
kind: "scalar",
construct(data) {
return data ?? ""
},
})
const yamlSchema = yaml.DEFAULT_SCHEMA.extend([includeType])
const ajv = new Ajv({
allErrors: true,
strict: false,
})
addFormats(ajv)
const schemaFiles = globSync("*.schema.json", {
cwd: schemaDir,
absolute: true,
}).sort()
if (schemaFiles.length === 0) {
console.error("No schema files found in", schemaDir)
process.exit(1)
}
for (const filePath of schemaFiles) {
const schema = JSON.parse(fs.readFileSync(filePath, "utf8"))
ajv.addSchema(schema, schema.$id || path.basename(filePath))
}
for (const filePath of schemaFiles) {
const schema = JSON.parse(fs.readFileSync(filePath, "utf8"))
ajv.getSchema(schema.$id || path.basename(filePath))
}
const validations = [
{ schema: "project.schema.json", pattern: "demo-api/config.y*ml" },
{
schema: "collection.schema.json",
pattern: "demo-api/collections/*.y*ml",
},
{
schema: "field.schema.json",
pattern: "demo-api/collections/fields/*.y*ml",
},
{
schema: "field-list.schema.json",
pattern: "demo-api/collections/fieldLists/*.y*ml",
},
{ schema: "job.schema.json", pattern: "demo-api/jobs/*.y*ml" },
{ schema: "action.schema.json", pattern: "demo-api/actions/*.y*ml" },
{ schema: "asset.schema.json", pattern: "demo-api/assets/*.y*ml" },
]
let hasErrors = false
let validatedCount = 0
for (const { schema, pattern } of validations) {
const validate = ajv.getSchema(schema)
if (!validate) {
console.error(`Schema not registered: ${schema}`)
hasErrors = true
continue
}
const files = globSync(pattern, {
cwd: repoRoot,
absolute: true,
}).sort()
for (const filePath of files) {
const raw = fs.readFileSync(filePath, "utf8")
const parsed = yaml.load(raw, { schema: yamlSchema })
const valid = validate(parsed)
validatedCount += 1
if (!valid) {
hasErrors = true
console.error(
`\nValidation failed: ${path.relative(repoRoot, filePath)}`
)
for (const error of validate.errors || []) {
const location = error.instancePath || "/"
console.error(` ${location} ${error.message}`)
}
}
}
}
if (hasErrors) {
process.exit(1)
}
console.log(
`Validated ${validatedCount} YAML file(s) against ${schemaFiles.length} schema file(s).`
)