@radio-garden/ditojs-admin 2.85.2-0.5067ad799
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -0
- package/dist/dito-admin.css +1 -0
- package/dist/dito-admin.es.js +12106 -0
- package/dist/dito-admin.umd.js +7 -0
- package/package.json +96 -0
- package/src/DitoAdmin.js +293 -0
- package/src/DitoComponent.js +34 -0
- package/src/DitoContext.js +318 -0
- package/src/DitoTypeComponent.js +42 -0
- package/src/DitoUser.js +12 -0
- package/src/appState.js +12 -0
- package/src/components/DitoAccount.vue +60 -0
- package/src/components/DitoAffix.vue +68 -0
- package/src/components/DitoAffixes.vue +200 -0
- package/src/components/DitoButtons.vue +80 -0
- package/src/components/DitoClipboard.vue +186 -0
- package/src/components/DitoContainer.vue +374 -0
- package/src/components/DitoCreateButton.vue +146 -0
- package/src/components/DitoDialog.vue +242 -0
- package/src/components/DitoDraggable.vue +117 -0
- package/src/components/DitoEditButtons.vue +135 -0
- package/src/components/DitoErrors.vue +83 -0
- package/src/components/DitoForm.vue +521 -0
- package/src/components/DitoFormInner.vue +26 -0
- package/src/components/DitoFormNested.vue +17 -0
- package/src/components/DitoHeader.vue +84 -0
- package/src/components/DitoLabel.vue +200 -0
- package/src/components/DitoMenu.vue +186 -0
- package/src/components/DitoNavigation.vue +40 -0
- package/src/components/DitoNotifications.vue +170 -0
- package/src/components/DitoPagination.vue +42 -0
- package/src/components/DitoPane.vue +334 -0
- package/src/components/DitoPanel.vue +256 -0
- package/src/components/DitoPanels.vue +61 -0
- package/src/components/DitoRoot.vue +524 -0
- package/src/components/DitoSchema.vue +846 -0
- package/src/components/DitoSchemaInlined.vue +97 -0
- package/src/components/DitoScopes.vue +76 -0
- package/src/components/DitoSidebar.vue +50 -0
- package/src/components/DitoSpinner.vue +95 -0
- package/src/components/DitoTableCell.vue +64 -0
- package/src/components/DitoTableHead.vue +121 -0
- package/src/components/DitoTabs.vue +103 -0
- package/src/components/DitoTrail.vue +124 -0
- package/src/components/DitoTreeItem.vue +420 -0
- package/src/components/DitoUploadFile.vue +199 -0
- package/src/components/DitoVNode.vue +14 -0
- package/src/components/DitoView.vue +143 -0
- package/src/components/index.js +42 -0
- package/src/directives/resize.js +83 -0
- package/src/index.js +1 -0
- package/src/mixins/ContextMixin.js +68 -0
- package/src/mixins/DataMixin.js +131 -0
- package/src/mixins/DitoMixin.js +591 -0
- package/src/mixins/DomMixin.js +29 -0
- package/src/mixins/EmitterMixin.js +158 -0
- package/src/mixins/ItemMixin.js +144 -0
- package/src/mixins/LoadingMixin.js +23 -0
- package/src/mixins/NumberMixin.js +118 -0
- package/src/mixins/OptionsMixin.js +304 -0
- package/src/mixins/PulldownMixin.js +63 -0
- package/src/mixins/ResourceMixin.js +398 -0
- package/src/mixins/RouteMixin.js +190 -0
- package/src/mixins/SchemaParentMixin.js +33 -0
- package/src/mixins/SortableMixin.js +49 -0
- package/src/mixins/SourceMixin.js +734 -0
- package/src/mixins/TextMixin.js +26 -0
- package/src/mixins/TypeMixin.js +280 -0
- package/src/mixins/ValidationMixin.js +119 -0
- package/src/mixins/ValidatorMixin.js +57 -0
- package/src/mixins/ValueMixin.js +31 -0
- package/src/styles/_base.scss +17 -0
- package/src/styles/_button.scss +191 -0
- package/src/styles/_imports.scss +3 -0
- package/src/styles/_info.scss +19 -0
- package/src/styles/_layout.scss +19 -0
- package/src/styles/_pulldown.scss +38 -0
- package/src/styles/_scroll.scss +13 -0
- package/src/styles/_settings.scss +88 -0
- package/src/styles/_table.scss +223 -0
- package/src/styles/_tippy.scss +45 -0
- package/src/styles/style.scss +9 -0
- package/src/types/DitoTypeButton.vue +143 -0
- package/src/types/DitoTypeCheckbox.vue +27 -0
- package/src/types/DitoTypeCheckboxes.vue +65 -0
- package/src/types/DitoTypeCode.vue +199 -0
- package/src/types/DitoTypeColor.vue +272 -0
- package/src/types/DitoTypeComponent.vue +31 -0
- package/src/types/DitoTypeComputed.vue +50 -0
- package/src/types/DitoTypeDate.vue +99 -0
- package/src/types/DitoTypeLabel.vue +23 -0
- package/src/types/DitoTypeList.vue +364 -0
- package/src/types/DitoTypeMarkup.vue +700 -0
- package/src/types/DitoTypeMultiselect.vue +522 -0
- package/src/types/DitoTypeNumber.vue +66 -0
- package/src/types/DitoTypeObject.vue +136 -0
- package/src/types/DitoTypePanel.vue +18 -0
- package/src/types/DitoTypeProgress.vue +40 -0
- package/src/types/DitoTypeRadio.vue +45 -0
- package/src/types/DitoTypeSection.vue +80 -0
- package/src/types/DitoTypeSelect.vue +133 -0
- package/src/types/DitoTypeSlider.vue +66 -0
- package/src/types/DitoTypeSpacer.vue +11 -0
- package/src/types/DitoTypeSwitch.vue +40 -0
- package/src/types/DitoTypeText.vue +101 -0
- package/src/types/DitoTypeTextarea.vue +48 -0
- package/src/types/DitoTypeTreeList.vue +193 -0
- package/src/types/DitoTypeUpload.vue +503 -0
- package/src/types/index.js +30 -0
- package/src/utils/SchemaGraph.js +147 -0
- package/src/utils/accessor.js +75 -0
- package/src/utils/agent.js +47 -0
- package/src/utils/data.js +92 -0
- package/src/utils/filter.js +266 -0
- package/src/utils/math.js +14 -0
- package/src/utils/options.js +48 -0
- package/src/utils/path.js +5 -0
- package/src/utils/resource.js +44 -0
- package/src/utils/route.js +53 -0
- package/src/utils/schema.js +1121 -0
- package/src/utils/type.js +81 -0
- package/src/utils/uid.js +15 -0
- package/src/utils/units.js +5 -0
- package/src/validators/_creditcard.js +6 -0
- package/src/validators/_decimals.js +11 -0
- package/src/validators/_domain.js +6 -0
- package/src/validators/_email.js +6 -0
- package/src/validators/_hostname.js +6 -0
- package/src/validators/_integer.js +6 -0
- package/src/validators/_max.js +6 -0
- package/src/validators/_min.js +6 -0
- package/src/validators/_password.js +5 -0
- package/src/validators/_range.js +6 -0
- package/src/validators/_required.js +9 -0
- package/src/validators/_url.js +6 -0
- package/src/validators/index.js +12 -0
- package/src/verbs.js +17 -0
- package/types/index.d.ts +3298 -0
- package/types/tests/admin.test-d.ts +27 -0
- package/types/tests/component-buttons.test-d.ts +44 -0
- package/types/tests/component-list.test-d.ts +159 -0
- package/types/tests/component-misc.test-d.ts +137 -0
- package/types/tests/component-object.test-d.ts +69 -0
- package/types/tests/component-section.test-d.ts +174 -0
- package/types/tests/component-select.test-d.ts +107 -0
- package/types/tests/components.test-d.ts +81 -0
- package/types/tests/context.test-d.ts +31 -0
- package/types/tests/fixtures.ts +24 -0
- package/types/tests/form.test-d.ts +109 -0
- package/types/tests/instance.test-d.ts +20 -0
- package/types/tests/schema-features.test-d.ts +402 -0
- package/types/tests/variance.test-d.ts +125 -0
- package/types/tests/view.test-d.ts +146 -0
package/package.json
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@radio-garden/ditojs-admin",
|
|
3
|
+
"version": "2.85.2-0.5067ad799",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Dito.js Admin is a schema based admin interface for Dito.js Server, featuring auto-generated views and forms and built with Vue.js",
|
|
6
|
+
"repository": "https://github.com/ditojs/dito/tree/master/packages/admin",
|
|
7
|
+
"author": "Jürg Lehni <juerg@scratchdisk.com> (http://scratchdisk.com)",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"module": "./dist/dito-admin.es.js",
|
|
10
|
+
"main": "./dist/dito-admin.umd.js",
|
|
11
|
+
"types": "./types/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./types/index.d.ts",
|
|
15
|
+
"import": "./dist/dito-admin.es.js",
|
|
16
|
+
"require": "./dist/dito-admin.umd.js"
|
|
17
|
+
},
|
|
18
|
+
"./style.css": "./dist/dito-admin.css",
|
|
19
|
+
"./src": "./src/index.js",
|
|
20
|
+
"./imports.scss": "./src/styles/_imports.scss"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"src/",
|
|
24
|
+
"dist/",
|
|
25
|
+
"types/"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "vite build",
|
|
29
|
+
"watch": "pnpm run build --mode 'development' --watch",
|
|
30
|
+
"prepare": "pnpm run build",
|
|
31
|
+
"types": "tsc --noEmit types/index.d.ts"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">= 20.0.0"
|
|
35
|
+
},
|
|
36
|
+
"browserslist": [
|
|
37
|
+
"> 1%",
|
|
38
|
+
"last 2 versions",
|
|
39
|
+
"not ie > 0",
|
|
40
|
+
"not ie_mob > 0"
|
|
41
|
+
],
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@ditojs/ui": "workspace:^",
|
|
44
|
+
"@ditojs/utils": "workspace:^",
|
|
45
|
+
"@kyvg/vue3-notification": "^3.4.2",
|
|
46
|
+
"@lk77/vue3-color": "^3.0.6",
|
|
47
|
+
"@tiptap/core": "^3.20.1",
|
|
48
|
+
"@tiptap/extension-blockquote": "^3.20.1",
|
|
49
|
+
"@tiptap/extension-bold": "^3.20.1",
|
|
50
|
+
"@tiptap/extension-bullet-list": "^3.20.1",
|
|
51
|
+
"@tiptap/extension-code": "^3.20.1",
|
|
52
|
+
"@tiptap/extension-code-block": "^3.20.1",
|
|
53
|
+
"@tiptap/extension-document": "^3.20.1",
|
|
54
|
+
"@tiptap/extension-hard-break": "^3.20.1",
|
|
55
|
+
"@tiptap/extension-heading": "^3.20.1",
|
|
56
|
+
"@tiptap/extension-history": "^3.20.1",
|
|
57
|
+
"@tiptap/extension-horizontal-rule": "^3.20.1",
|
|
58
|
+
"@tiptap/extension-italic": "^3.20.1",
|
|
59
|
+
"@tiptap/extension-link": "^3.20.1",
|
|
60
|
+
"@tiptap/extension-list": "^3.20.1",
|
|
61
|
+
"@tiptap/extension-list-item": "^3.20.1",
|
|
62
|
+
"@tiptap/extension-ordered-list": "^3.20.1",
|
|
63
|
+
"@tiptap/extension-paragraph": "^3.20.1",
|
|
64
|
+
"@tiptap/extension-strike": "^3.20.1",
|
|
65
|
+
"@tiptap/extension-subscript": "^3.20.1",
|
|
66
|
+
"@tiptap/extension-superscript": "^3.20.1",
|
|
67
|
+
"@tiptap/extension-text": "^3.20.1",
|
|
68
|
+
"@tiptap/extension-text-style": "^3.20.1",
|
|
69
|
+
"@tiptap/extension-underline": "^3.20.1",
|
|
70
|
+
"@tiptap/extensions": "^3.20.1",
|
|
71
|
+
"@tiptap/pm": "^3.20.1",
|
|
72
|
+
"@tiptap/vue-3": "^3.20.1",
|
|
73
|
+
"@vueuse/integrations": "^14.2.1",
|
|
74
|
+
"codeflask": "^1.4.1",
|
|
75
|
+
"filesize": "^11.0.13",
|
|
76
|
+
"filesize-parser": "^1.5.1",
|
|
77
|
+
"focus-trap": "^8.0.0",
|
|
78
|
+
"nanoid": "^5.1.6",
|
|
79
|
+
"sortablejs": "^1.15.7",
|
|
80
|
+
"tinycolor2": "^1.6.0",
|
|
81
|
+
"tippy.js": "^6.3.7",
|
|
82
|
+
"tiptap-footnotes": "^3.0.1",
|
|
83
|
+
"type-fest": "^5.4.4",
|
|
84
|
+
"vue": "^3.5.30",
|
|
85
|
+
"vue-multiselect": "^3.4.0",
|
|
86
|
+
"vue-router": "^5.0.3",
|
|
87
|
+
"vue-upload-component": "^3.1.17"
|
|
88
|
+
},
|
|
89
|
+
"devDependencies": {
|
|
90
|
+
"@ditojs/build": "workspace:^",
|
|
91
|
+
"typescript": "^5.9.3",
|
|
92
|
+
"vite": "^7.3.1"
|
|
93
|
+
},
|
|
94
|
+
"gitHead": "5067ad799",
|
|
95
|
+
"gitBranch": "chore/improve-ts-types"
|
|
96
|
+
}
|
package/src/DitoAdmin.js
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { createApp, h as createElement } from 'vue'
|
|
2
|
+
import { createRouter, createWebHistory } from 'vue-router'
|
|
3
|
+
import VueNotifications from '@kyvg/vue3-notification'
|
|
4
|
+
import {
|
|
5
|
+
isString,
|
|
6
|
+
isAbsoluteUrl,
|
|
7
|
+
assignDeeply,
|
|
8
|
+
hyphenate,
|
|
9
|
+
camelize,
|
|
10
|
+
defaultFormats
|
|
11
|
+
} from '@ditojs/utils'
|
|
12
|
+
import * as components from './components/index.js'
|
|
13
|
+
import * as types from './types/index.js'
|
|
14
|
+
import DitoRoot from './components/DitoRoot.vue'
|
|
15
|
+
import DitoTypeComponent from './DitoTypeComponent.js'
|
|
16
|
+
import ResizeDirective from './directives/resize.js'
|
|
17
|
+
import { getResource } from './utils/resource.js'
|
|
18
|
+
import { formatQuery } from './utils/route.js'
|
|
19
|
+
import verbs from './verbs.js'
|
|
20
|
+
|
|
21
|
+
export default class DitoAdmin {
|
|
22
|
+
constructor(el, {
|
|
23
|
+
// `dito` contains the base and api settings passed from `AdminController`
|
|
24
|
+
dito = {},
|
|
25
|
+
api,
|
|
26
|
+
views = {},
|
|
27
|
+
...options
|
|
28
|
+
} = {}) {
|
|
29
|
+
this.el = el
|
|
30
|
+
// Merge in `api` settings as passed from `config.admin` and through the
|
|
31
|
+
// `AdminController` with `api` values from from 'admin/index.js'
|
|
32
|
+
// NOTE: `AdminController` provides `dito.api.base`
|
|
33
|
+
this.api = api = assignDeeply({ base: '/' }, dito.api, api)
|
|
34
|
+
this.options = options
|
|
35
|
+
|
|
36
|
+
// Setup default api settings:
|
|
37
|
+
api.locale ||= 'en-US'
|
|
38
|
+
api.formats = assignDeeply({}, defaultFormats, api.formats)
|
|
39
|
+
api.request ||= options => request(api, options)
|
|
40
|
+
api.getApiUrl ||= options => getApiUrl(api, options)
|
|
41
|
+
api.isApiUrl ||= url => isApiUrl(api, url)
|
|
42
|
+
// Setting `api.normalizePaths = true (plural) sets both:
|
|
43
|
+
// `api.normalizePath = hyphenate` and `api.denormalizePath = camelize`
|
|
44
|
+
api.normalizePath ||= api.normalizePaths ? hyphenate : val => val
|
|
45
|
+
api.denormalizePath ||= api.normalizePaths ? camelize : val => val
|
|
46
|
+
|
|
47
|
+
// Allow definition of defaults for admin component types, nested per type:
|
|
48
|
+
// api.defaults = {
|
|
49
|
+
// 'multiselect': {
|
|
50
|
+
// selectable: true
|
|
51
|
+
// },
|
|
52
|
+
// 'fake-type': schema => {
|
|
53
|
+
// // Return defaults, or directly modify the schema:
|
|
54
|
+
// Object.assign(schema, {
|
|
55
|
+
// type: 'real-type',
|
|
56
|
+
// format: ({ value }) => `Formatted ${value}`,
|
|
57
|
+
// process: ({ value }) => `Processed ${value}`
|
|
58
|
+
// })
|
|
59
|
+
// }
|
|
60
|
+
// }
|
|
61
|
+
|
|
62
|
+
api.defaults ||= {}
|
|
63
|
+
|
|
64
|
+
// Allow the configuration of all auth resources, like so:
|
|
65
|
+
// api.users = {
|
|
66
|
+
// path: '/admins',
|
|
67
|
+
// // These are the defaults:
|
|
68
|
+
// login: {
|
|
69
|
+
// path: 'login',
|
|
70
|
+
// method: 'post'
|
|
71
|
+
// },
|
|
72
|
+
// logout: {
|
|
73
|
+
// path: 'logout',
|
|
74
|
+
// method: 'post'
|
|
75
|
+
// },
|
|
76
|
+
// session: {
|
|
77
|
+
// path: 'session',
|
|
78
|
+
// method: 'get'
|
|
79
|
+
// }
|
|
80
|
+
// }
|
|
81
|
+
const users = getResource(api.users, {
|
|
82
|
+
type: 'collection'
|
|
83
|
+
}) || {}
|
|
84
|
+
users.login = getResource(users.login || 'login', {
|
|
85
|
+
method: 'post',
|
|
86
|
+
parent: users
|
|
87
|
+
})
|
|
88
|
+
users.logout = getResource(users.logout || 'logout', {
|
|
89
|
+
method: 'post',
|
|
90
|
+
parent: users
|
|
91
|
+
})
|
|
92
|
+
users.session = getResource(users.session || 'session', {
|
|
93
|
+
method: 'get',
|
|
94
|
+
parent: users
|
|
95
|
+
})
|
|
96
|
+
api.users = users
|
|
97
|
+
|
|
98
|
+
// Allow overriding of resource path handlers:
|
|
99
|
+
// api.resources = {
|
|
100
|
+
// collection(resource) {
|
|
101
|
+
// return resource.parent
|
|
102
|
+
// ? `${resource.path}?${resource.parent.path}_id=${
|
|
103
|
+
// resource.parent.id}`
|
|
104
|
+
// : resource.path
|
|
105
|
+
// }
|
|
106
|
+
// }
|
|
107
|
+
|
|
108
|
+
api.resources = {
|
|
109
|
+
any(resource) {
|
|
110
|
+
const handler = this[resource?.type] || this.default
|
|
111
|
+
return resource && handler.call(this, resource)
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
default(resource) {
|
|
115
|
+
const parentPath = this.any(resource.parent)
|
|
116
|
+
return parentPath
|
|
117
|
+
? `${parentPath}/${resource.path}`
|
|
118
|
+
: resource.path
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
collection(resource) {
|
|
122
|
+
return this.default(resource)
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
member(resource) {
|
|
126
|
+
return `${this.default(resource)}/${resource.id}`
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
upload(resource) {
|
|
130
|
+
// Dito.js Server handles upload routes on the collection resource:
|
|
131
|
+
return `${this.collection(resource.parent)}/upload/${resource.path}`
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
...api.resources
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Allow overriding / extending of headers:
|
|
138
|
+
// api.headers = {
|
|
139
|
+
// 'Content-Type': 'application/json'
|
|
140
|
+
// }
|
|
141
|
+
api.headers = {
|
|
142
|
+
'Content-Type': 'application/json',
|
|
143
|
+
...api.headers
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (isString(el)) {
|
|
147
|
+
el = document.querySelector(el)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const app = (this.app = createApp({
|
|
151
|
+
components: {
|
|
152
|
+
DitoRoot,
|
|
153
|
+
VueNotifications,
|
|
154
|
+
// This may only be needed to avoid tree-shacking of these components,
|
|
155
|
+
// since they actually handle registry internally already.
|
|
156
|
+
// TODO: Remove this once we have a better solution.
|
|
157
|
+
...components,
|
|
158
|
+
...types
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
// Most injects are defined as functions, to preserve reactiveness across
|
|
162
|
+
// provide/inject, see:
|
|
163
|
+
// https://github.com/vuejs/vue/issues/7017#issuecomment-480906691
|
|
164
|
+
provide: {
|
|
165
|
+
api,
|
|
166
|
+
// A default list of verbs are provided by $verbs() and can be
|
|
167
|
+
// overridden at any point in the component hierarchy.
|
|
168
|
+
$verbs: () => verbs,
|
|
169
|
+
// Provide defaults so DitoMixin can inject them for all components:
|
|
170
|
+
// inject: [ '$isPopulated', '$schemaComponent', '$routeComponent' ]
|
|
171
|
+
$views: () => {},
|
|
172
|
+
$isPopulated: () => true,
|
|
173
|
+
$parentComponent: () => null,
|
|
174
|
+
$schemaComponent: () => null,
|
|
175
|
+
$schemaParentComponent: () => null,
|
|
176
|
+
$routeComponent: () => null,
|
|
177
|
+
$dataComponent: () => null,
|
|
178
|
+
$sourceComponent: () => null,
|
|
179
|
+
$resourceComponent: () => null,
|
|
180
|
+
$dialogComponent: () => null,
|
|
181
|
+
$panelComponent: () => null,
|
|
182
|
+
$tabComponent: () => null
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
render: () =>
|
|
186
|
+
createElement(DitoRoot, {
|
|
187
|
+
ref: 'root',
|
|
188
|
+
class: dito.settings.rootClass,
|
|
189
|
+
unresolvedViews: views,
|
|
190
|
+
options
|
|
191
|
+
})
|
|
192
|
+
}))
|
|
193
|
+
|
|
194
|
+
// Prevent endless loops of error messages during render functions by
|
|
195
|
+
// setting a custom error handler.
|
|
196
|
+
app.config.errorHandler = console.error
|
|
197
|
+
|
|
198
|
+
app.use(VueNotifications, {
|
|
199
|
+
componentName: 'VueNotifications',
|
|
200
|
+
name: 'notify'
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
app.directive('resize', ResizeDirective)
|
|
204
|
+
|
|
205
|
+
app.use(
|
|
206
|
+
createRouter({
|
|
207
|
+
// Start with a catch-all route, to be replaced by the actual routes
|
|
208
|
+
// once the schemas are loaded, to prevent vue-router from complaining,
|
|
209
|
+
// see: `resolveViews()` in `DitoRoot` for the actual route setup.
|
|
210
|
+
routes: [
|
|
211
|
+
{
|
|
212
|
+
name: 'catch-all',
|
|
213
|
+
path: '/:_(.*)',
|
|
214
|
+
components: {}
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
history: createWebHistory(dito.base),
|
|
218
|
+
linkActiveClass: '',
|
|
219
|
+
linkExactActiveClass: ''
|
|
220
|
+
})
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
el.classList.add('dito-app')
|
|
224
|
+
app.mount(el)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
register(type, options) {
|
|
228
|
+
return DitoTypeComponent.register(type, options)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
class RequestError extends Error {
|
|
233
|
+
constructor(response) {
|
|
234
|
+
super(
|
|
235
|
+
`Request failed with status code: ${response.status} (${
|
|
236
|
+
response.statusText
|
|
237
|
+
})`
|
|
238
|
+
)
|
|
239
|
+
this.response = response
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function request(api, {
|
|
244
|
+
url,
|
|
245
|
+
method = 'get',
|
|
246
|
+
query = null,
|
|
247
|
+
headers = null,
|
|
248
|
+
data = null,
|
|
249
|
+
signal = null
|
|
250
|
+
}) {
|
|
251
|
+
const isApiUrl = api.isApiUrl(url)
|
|
252
|
+
|
|
253
|
+
const response = await fetch(api.getApiUrl({ url, query }), {
|
|
254
|
+
method: method.toUpperCase(),
|
|
255
|
+
...(data && { body: JSON.stringify(data) }),
|
|
256
|
+
headers: {
|
|
257
|
+
...(isApiUrl && api.headers),
|
|
258
|
+
...headers
|
|
259
|
+
},
|
|
260
|
+
credentials:
|
|
261
|
+
isApiUrl && api.cors?.credentials
|
|
262
|
+
? 'include'
|
|
263
|
+
: 'same-origin',
|
|
264
|
+
signal
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
if (response.headers.get('Content-Type')?.includes('application/json')) {
|
|
268
|
+
response.data = await response.json()
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (!response.ok) {
|
|
272
|
+
throw new RequestError(response)
|
|
273
|
+
}
|
|
274
|
+
return response
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function isApiUrl(api, url) {
|
|
278
|
+
return !isAbsoluteUrl(url) || url.startsWith(api.url)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function getApiUrl(api, { url, query }) {
|
|
282
|
+
if (!url.startsWith(api.url) && !isAbsoluteUrl(url)) {
|
|
283
|
+
url = combineUrls(api.url, url)
|
|
284
|
+
}
|
|
285
|
+
// Support optional query parameters, to be are added to the URL.
|
|
286
|
+
const search = formatQuery(query)
|
|
287
|
+
return search ? `${url}${url.includes('?') ? '&' : '?'}${search}` : url
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function combineUrls(baseUrl, relativeUrl) {
|
|
291
|
+
// Use same approach as axios `combineURLs()` to join baseUrl & relativeUrl:
|
|
292
|
+
return `${baseUrl.replace(/\/+$/, '')}/${relativeUrl.replace(/^\/+/, '')}`
|
|
293
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import DitoMixin from './mixins/DitoMixin.js'
|
|
2
|
+
import { getTypeComponent } from './utils/schema.js'
|
|
3
|
+
import { resolveMergedOptions } from './utils/options.js'
|
|
4
|
+
import { isPlainObject } from '@ditojs/utils'
|
|
5
|
+
|
|
6
|
+
const components = {}
|
|
7
|
+
|
|
8
|
+
// @vue/component
|
|
9
|
+
export default {
|
|
10
|
+
mixins: [DitoMixin],
|
|
11
|
+
// Make sure that registered components are present in all DitoComponent.
|
|
12
|
+
components,
|
|
13
|
+
|
|
14
|
+
component(name, definition) {
|
|
15
|
+
if (definition) {
|
|
16
|
+
if (isPlainObject(definition)) {
|
|
17
|
+
definition = resolveMergedOptions({
|
|
18
|
+
extends: this,
|
|
19
|
+
name,
|
|
20
|
+
...definition
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
components[name] = definition
|
|
24
|
+
}
|
|
25
|
+
if (!(name in components)) {
|
|
26
|
+
throw new Error(`Component "${name}" not registered`)
|
|
27
|
+
}
|
|
28
|
+
return components[name]
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
methods: {
|
|
32
|
+
getTypeComponent
|
|
33
|
+
}
|
|
34
|
+
}
|