diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..9402e22 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,16 @@ +{ + "printWidth": 80, + "tabWidth": 4, + "singleQuote": false, + "trailingComma": "es5", + "semi": false, + "newline-before-return": true, + "no-duplicate-variable": [true, "check-parameters"], + "no-var-keyword": true, + + "svelteSortOrder": "scripts-styles-markup", + "svelteStrictMode": true, + "svelteBracketNewLine": true, + "svelteAllowShorthand": true, + "svelteIndentScriptAndStyle": true +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3d2cefc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "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" + }, + "editor.formatOnSave": true +} \ No newline at end of file diff --git a/demo-api/collections/fields/testfield.yml b/demo-api/collections/fields/testfield.yml new file mode 100644 index 0000000..c47ee99 --- /dev/null +++ b/demo-api/collections/fields/testfield.yml @@ -0,0 +1,6 @@ +name: testfield +type: string +meta: + label: + de: test + \ No newline at end of file diff --git a/demo-api/collections/global/test-permissions.yml b/demo-api/collections/global/test-permissions.yml new file mode 100644 index 0000000..1d6e6d2 --- /dev/null +++ b/demo-api/collections/global/test-permissions.yml @@ -0,0 +1,22 @@ +# yaml-language-server: $schema=../../../schemas/api-config/permissions.json + +public: + methods: + get: true + post: false + put: false + delete: false + +user: + methods: + get: true + post: true + put: true + delete: true + +token:abc: + methods: + get: true + post: true + put: true + delete: true \ No newline at end of file diff --git a/demo-api/collections/mycol.yml b/demo-api/collections/mycol.yml index 4d2a1c8..3cf4f89 100644 --- a/demo-api/collections/mycol.yml +++ b/demo-api/collections/mycol.yml @@ -9,19 +9,8 @@ meta: columns: - title -permissions: - public: - methods: - get: true - post: false - put: false - delete: false - user: - methods: - get: true - post: true - put: false - delete: false +permissions: !include global/test-permissions.yml + hooks: get: diff --git a/schemas/api-config/collection.json b/schemas/api-config/collection.json new file mode 100644 index 0000000..8d89e2d --- /dev/null +++ b/schemas/api-config/collection.json @@ -0,0 +1,187 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "JSON Schema WMBasic collection configuration", + "description": "WMBasic collection linter", + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "collection name, part of api path" + }, + "uploadPath": { + "type": "string", + "description": "relative to config.yml, path for file uploads" + }, + "meta": { + "type": "object", + "description": "meta object used for admin ui configuration", + "additionalProperties": true, + "properties": { + "label": { + "$ref": "field.json#/definitions/i18nString" + }, + "muiIcon": { + "type": "string", + "description": "material ui icon name" + }, + "rowIdentTpl": { + "description": "template which evaluates to short string to identify entry in pe. select boxes", + "$ref": "field.json#/definitions/evalExpressions" + }, + "defaultSort": { + "type": "object", + "description": "default sort in admin ui lists", + "additionalProperties": false, + "properties": { + "field": { + "$ref": "field.json#/definitions/fieldSource" + }, + "order": { + "description": "sort order", + "enum": ["ASC", "DESC"] + } + } + }, + "views": { + "type": "array", + "description": "list views", + "items": { + "type": "object", + "properties": { + "mediaQuery": { + "type": "string", + "description": "css media query to select this view in ui" + } + }, + "oneOf": [ + { + "properties": { + "type": { + "const": "simpleList" + }, + "primaryText": { + "oneOf": [ + { + "$ref": "field.json#/definitions/fieldSource" + }, + { + "$ref": "field.json#/definitions/evalExpressions" + } + ] + }, + "secondaryText": { + "oneOf": [ + { + "$ref": "field.json#/definitions/fieldSource" + }, + { + "$ref": "field.json#/definitions/evalExpressions" + } + ] + }, + "tertiaryText": { + "oneOf": [ + { + "$ref": "field.json#/definitions/fieldSource" + }, + { + "$ref": "field.json#/definitions/evalExpressions" + } + ] + } + }, + "required": ["type", "primaryText"] + }, + { + "properties": { + "type": { + "const": "table" + }, + "columns": { + "type": "array", + "items": { + "oneOf": [ + { + "anyOf": [ + { + "$ref": "field.json#/definitions/fieldSource" + }, + { + "type": "object", + "properties": { + "label": { + "$ref": "field.json#/definitions/i18nString" + } + } + } + ] + }, + { + "allOf": [ + { + "$ref": "field.json#/definitions/evalExpressions" + }, + { + "properties": { + "label": { + "$ref": "field.json#/definitions/i18nString" + } + } + } + ] + } + ] + }, + "minItems": 1 + } + }, + "required": ["type", "columns"] + } + ], + "required": ["type"] + } + } + } + }, + "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": { + "type": "array", + "description": "fields of collection", + "items": { + "oneOf": [ + { + "$comment": "for include tag" + }, + { + "$ref": "field.json" + } + ] + } + } + }, + "required": ["name", "permissions"] +} diff --git a/schemas/api-config/config.json b/schemas/api-config/config.json new file mode 100644 index 0000000..674e305 --- /dev/null +++ b/schemas/api-config/config.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "JSON Schema WMBasic config file", + "description": "WMBasic config.yml linter", + "type": "object", + "additionalProperties": false, + "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": { + "imageUrl": { + "type": "string", + "description": "project's teaser image url shown in admin ui" + } + } + }, + "collections": { + "oneOf": [ + { + "$comment": "for include tag", + "type": "string" + }, + { + "type": "array", + "description": "list of collections in this project", + "items": { + "$ref": "collection.json" + } + } + ] + } + }, + "required": ["namespace"] +} diff --git a/schemas/api-config/field.json b/schemas/api-config/field.json new file mode 100644 index 0000000..ce81b27 --- /dev/null +++ b/schemas/api-config/field.json @@ -0,0 +1,194 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "JSON Schema WMBasic field configuration", + "description": "WMBasic field linter", + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "name of field", + "pattern": "^[0-9a-zA-Z_]+$" + }, + "type": { + "enum": [ + "string", + "string[]", + "number", + "number[]", + "boolean", + "object", + "object[]", + "any" + ] + }, + "index": { + "type": "array", + "items": { + "enum": ["single", "unique", "text"] + } + }, + "subFields": { + "type": "array", + "description": "sub fields of object", + "items": { + "$ref": "#" + } + }, + "meta": { + "type": "object", + "description": "meta object of field", + "properties": { + "label": { + "$ref": "#/definitions/i18nString" + }, + "helperText": { + "$ref": "#/definitions/i18nString" + }, + "widget": { + "description": "ui widget", + "enum": [ + "richtext", + "richText", + "html", + "checkbox", + "select", + "selectArray", + "date", + "file", + "image" + ] + }, + "choices": { + "type": "array", + "description": "choices to select from", + "items": { + "type": "object", + "properties": { + "name": { + "description": "name is human readable value", + "$ref": "#/definitions/i18nString" + }, + "chipStyle": { + "$ref": "https://raw.githubusercontent.com/rcorp/css-schema/master/schema.json" + } + }, + "oneOf": [ + { + "properties": { + "id": { + "type": "number" + } + } + }, + { + "properties": { + "id": { + "type": "string" + } + } + } + ], + "required": ["id", "name"] + } + }, + "valueMap": { + "type": "object", + "description": "map values to icons", + "patternProperties": { + ".*": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "muiIcon": { + "type": "string" + }, + "style": { + "$ref": "https://raw.githubusercontent.com/rcorp/css-schema/master/schema.json" + } + } + } + ] + } + } + } + } + } + }, + "required": ["name", "type"], + "definitions": { + "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_]+)*$" + } + } +} diff --git a/schemas/api-config/hooks.json b/schemas/api-config/hooks.json new file mode 100644 index 0000000..b73357b --- /dev/null +++ b/schemas/api-config/hooks.json @@ -0,0 +1,92 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "JSON Schema WMBasic hooks configuration", + "description": "WMBasic hooks linter", + "type": "object", + "additionalProperties": false, + "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" + } + } + }, + "post": { + "type": "object", + "description": "hooks for http POST", + "additionalProperties": false, + "properties": { + "bind": { + "description": "hook before binding data from post request", + "$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" + } + } + }, + "put": { + "type": "object", + "description": "hooks for http PUT", + "additionalProperties": false, + "properties": { + "bind": { + "description": "hook before binding data from put request", + "$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" + } + } + }, + "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" + } + } + } + }, + "definitions": { + "hookDef": { + "type": "object", + "properties": { + "type": { + "const": "javascript" + }, + "file": { + "type": "string", + "description": "location of javascript hook file relative to config.yml base" + } + }, + "required": ["type", "file"] + } + } +} diff --git a/schemas/api-config/imageFilter.json b/schemas/api-config/imageFilter.json new file mode 100644 index 0000000..1e5e802 --- /dev/null +++ b/schemas/api-config/imageFilter.json @@ -0,0 +1,63 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "JSON Schema WMBasic imageFilter configuration", + "description": "WMBasic imageFilter linter", + "type": "object", + "patternProperties": { + "^[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": [ + "lancos", + "nearestNeighbor", + "linear", + "catmullRom" + ] + }, + "quality": { + "type": "number" + } + } + } + } + } +} diff --git a/schemas/api-config/permissions.json b/schemas/api-config/permissions.json new file mode 100644 index 0000000..dfba35b --- /dev/null +++ b/schemas/api-config/permissions.json @@ -0,0 +1,43 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "JSON Schema WMBasic permissions configuration", + "description": "WMBasic permissions linter", + "type": "object", + "additionalProperties": false, + "properties": { + "public": { + "description": "permissions for unauthorized public access", + "$ref": "#/definitions/permissionSet" + }, + "user": { + "description": "permissions for authorized users (nativ wmbasic auth)", + "$ref": "#/definitions/permissionSet" + } + }, + "patternProperties": { + "^token:": { + "description": "permissions for header or query token", + "$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": { "type": "boolean" }, + "post": { "type": "boolean" }, + "put": { "type": "boolean" }, + "delete": { "type": "boolean" } + } + } + } + } + } +} diff --git a/schemas/api-config/projections.json b/schemas/api-config/projections.json new file mode 100644 index 0000000..5f230e9 --- /dev/null +++ b/schemas/api-config/projections.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "JSON Schema WMBasic imageFilter configuration", + "description": "WMBasic imageFilter linter", + "patternProperties": { + "^[a-zA-Z0-9_-]$": { + "type": "object", + "description": "dataset query projection config", + "properties": { + "select": { + "type": "object", + "description": "mongo db selector", + "patternProperties": { + "^[a-zA-Z0-9_]+(\\.[a-zA-Z0-9]+)*$": { + "enum": [0, 1] + } + } + } + } + } + } +}