@narrative.io/jsonforms-provider-protocols 1.0.3
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/LICENSE +21 -0
- package/README.md +200 -0
- package/dist/_virtual/_plugin-vue_export-helper.js +11 -0
- package/dist/_virtual/_plugin-vue_export-helper.js.map +1 -0
- package/dist/core/cache.d.ts +8 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +27 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/jsonpath.d.ts +2 -0
- package/dist/core/jsonpath.d.ts.map +1 -0
- package/dist/core/jsonpath.js +40 -0
- package/dist/core/jsonpath.js.map +1 -0
- package/dist/core/registry.d.ts +8 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +17 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/templating.d.ts +3 -0
- package/dist/core/templating.d.ts.map +1 -0
- package/dist/core/templating.js +32 -0
- package/dist/core/templating.js.map +1 -0
- package/dist/core/types.d.ts +44 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/jsonforms-provider-protocols.css +4 -0
- package/dist/protocols/rest_api.d.ts +22 -0
- package/dist/protocols/rest_api.d.ts.map +1 -0
- package/dist/protocols/rest_api.js +92 -0
- package/dist/protocols/rest_api.js.map +1 -0
- package/dist/vue/components/ProviderAutocomplete.vue.d.ts +9 -0
- package/dist/vue/components/ProviderAutocomplete.vue.d.ts.map +1 -0
- package/dist/vue/components/ProviderAutocomplete.vue.js +68 -0
- package/dist/vue/components/ProviderAutocomplete.vue.js.map +1 -0
- package/dist/vue/components/ProviderAutocomplete.vue2.js +5 -0
- package/dist/vue/components/ProviderAutocomplete.vue2.js.map +1 -0
- package/dist/vue/components/ProviderSelect.vue.d.ts +9 -0
- package/dist/vue/components/ProviderSelect.vue.d.ts.map +1 -0
- package/dist/vue/components/ProviderSelect.vue.js +8 -0
- package/dist/vue/components/ProviderSelect.vue.js.map +1 -0
- package/dist/vue/components/ProviderSelect.vue2.js +74 -0
- package/dist/vue/components/ProviderSelect.vue2.js.map +1 -0
- package/dist/vue/composables/useProvider.d.ts +14 -0
- package/dist/vue/composables/useProvider.d.ts.map +1 -0
- package/dist/vue/composables/useProvider.js +76 -0
- package/dist/vue/composables/useProvider.js.map +1 -0
- package/dist/vue/index.d.ts +19 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue/index.js +36 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/vue/testers.d.ts +2 -0
- package/dist/vue/testers.d.ts.map +1 -0
- package/dist/vue/testers.js +12 -0
- package/dist/vue/testers.js.map +1 -0
- package/package.json +100 -0
- package/src/core/cache.ts +23 -0
- package/src/core/jsonpath.ts +41 -0
- package/src/core/registry.ts +15 -0
- package/src/core/templating.ts +27 -0
- package/src/core/types.ts +46 -0
- package/src/index.ts +36 -0
- package/src/protocols/rest_api.ts +136 -0
- package/src/vue/components/ProviderAutocomplete.vue +54 -0
- package/src/vue/components/ProviderSelect.vue +70 -0
- package/src/vue/composables/useProvider.ts +111 -0
- package/src/vue/index.ts +44 -0
- package/src/vue/testers.ts +19 -0
- package/src/vue-shim.d.ts +9 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Narrative I/O
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# JSONForms Provider Protocols
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@narrative.io/jsonforms-provider-protocols)
|
|
4
|
+
[](https://github.com/narrative-io/jsonforms-provider-protocols/actions/workflows/ci.yml)
|
|
5
|
+
[](https://github.com/narrative-io/jsonforms-provider-protocols/actions/workflows/release-please.yml)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](http://www.typescriptlang.org/)
|
|
8
|
+
[](https://vuejs.org/)
|
|
9
|
+
[](https://jsonforms.io/)
|
|
10
|
+
|
|
11
|
+
A Vue 3 library that adds dynamic data provider capabilities to [JSONForms](https://jsonforms.io/), enabling form fields to fetch and display data from various sources like REST APIs, databases, and custom protocols.
|
|
12
|
+
|
|
13
|
+
## ✨ Features
|
|
14
|
+
|
|
15
|
+
- 🔌 **Protocol-based Architecture**: Extensible system for different data sources
|
|
16
|
+
- 🚀 **Vue 3 Integration**: Seamless integration with JSONForms Vue renderers
|
|
17
|
+
- 💾 **Built-in Caching**: TTL-based caching with configurable expiration
|
|
18
|
+
- 🔄 **Dynamic Data Loading**: Support for mount, focus, and query-based loading
|
|
19
|
+
- 🎯 **Template Support**: Dynamic URL and parameter templating
|
|
20
|
+
- 📦 **TypeScript Support**: Full TypeScript definitions included
|
|
21
|
+
- 🔐 **Authentication**: Flexible authentication mechanism support
|
|
22
|
+
|
|
23
|
+
## 📦 Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Using bun (recommended)
|
|
27
|
+
bun add @narrative.io/jsonforms-provider-protocols
|
|
28
|
+
|
|
29
|
+
# Using npm
|
|
30
|
+
npm install @narrative.io/jsonforms-provider-protocols
|
|
31
|
+
|
|
32
|
+
# Peer dependencies
|
|
33
|
+
bun add @jsonforms/vue @jsonforms/core vue
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 🚀 Quick Start
|
|
37
|
+
|
|
38
|
+
### 1. Register the Plugin
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { createApp } from 'vue'
|
|
42
|
+
import ProviderProtocols, { RestApiProtocol } from '@narrative.io/jsonforms-provider-protocols'
|
|
43
|
+
|
|
44
|
+
const app = createApp(App)
|
|
45
|
+
|
|
46
|
+
app.use(ProviderProtocols, {
|
|
47
|
+
protocols: [RestApiProtocol()]
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Configure Your Form
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"type": "Control",
|
|
56
|
+
"scope": "#/properties/country",
|
|
57
|
+
"options": {
|
|
58
|
+
"provider": {
|
|
59
|
+
"ref": "countries",
|
|
60
|
+
"protocol": "rest_api",
|
|
61
|
+
"config": {
|
|
62
|
+
"url": "https://api.example.com/countries",
|
|
63
|
+
"items": "$.data[*]",
|
|
64
|
+
"map": {
|
|
65
|
+
"label": "$.name",
|
|
66
|
+
"value": "$.code"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 3. Use in Vue
|
|
75
|
+
|
|
76
|
+
```vue
|
|
77
|
+
<script setup lang="ts">
|
|
78
|
+
import { JsonForms } from '@jsonforms/vue'
|
|
79
|
+
import { providerRenderers } from '@narrative.io/jsonforms-provider-protocols/vue'
|
|
80
|
+
import { markRaw, ref } from 'vue'
|
|
81
|
+
|
|
82
|
+
const data = ref({ country: null })
|
|
83
|
+
const handleChange = (event) => data.value = event.data
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<template>
|
|
87
|
+
<JsonForms
|
|
88
|
+
:data="data"
|
|
89
|
+
:schema="schema"
|
|
90
|
+
:uischema="uischema"
|
|
91
|
+
:renderers="markRaw(providerRenderers)"
|
|
92
|
+
@change="handleChange"
|
|
93
|
+
/>
|
|
94
|
+
</template>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 📖 Documentation
|
|
98
|
+
|
|
99
|
+
### Getting Started
|
|
100
|
+
- [Installation & Setup](./docs/getting-started.md)
|
|
101
|
+
- [Basic Examples](./docs/examples/simple-dropdown.md)
|
|
102
|
+
|
|
103
|
+
### Core Concepts
|
|
104
|
+
- [Protocols](./docs/protocols.md) - How to fetch and transform data
|
|
105
|
+
- [Authentication](./docs/authentication.md) - Configure and use authentication
|
|
106
|
+
- [Vue Components](./docs/components.md) - Available components and composables
|
|
107
|
+
- [API Reference](./docs/api/README.md) - Complete API documentation
|
|
108
|
+
|
|
109
|
+
### Examples
|
|
110
|
+
- [Simple Dropdown](./docs/examples/simple-dropdown.md)
|
|
111
|
+
- [Cascading Dropdowns](./docs/examples/cascading-dropdowns.md)
|
|
112
|
+
- [Autocomplete Search](./docs/examples/autocomplete-search.md)
|
|
113
|
+
- [Custom Protocols](./docs/examples/custom-protocol.md)
|
|
114
|
+
- [Custom Renderers](./docs/examples/custom-renderer.md)
|
|
115
|
+
- [More Examples](./docs/examples/README.md)
|
|
116
|
+
|
|
117
|
+
### Help & Troubleshooting
|
|
118
|
+
- [Troubleshooting Guide](./docs/troubleshooting.md)
|
|
119
|
+
- [GitHub Issues](https://github.com/narrative-io/jsonforms-provider-protocols/issues)
|
|
120
|
+
|
|
121
|
+
## 🔧 Key Concepts
|
|
122
|
+
|
|
123
|
+
### Protocols
|
|
124
|
+
Define how data is fetched and transformed:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const CustomProtocol: Protocol = {
|
|
128
|
+
protocol: 'my-api',
|
|
129
|
+
async resolve(config, context) {
|
|
130
|
+
const response = await fetch(config.url)
|
|
131
|
+
const data = await response.json()
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
items: data.map(item => ({
|
|
135
|
+
label: item.name,
|
|
136
|
+
value: item.id
|
|
137
|
+
})),
|
|
138
|
+
ttl: 300
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Template Variables
|
|
145
|
+
Create dynamic URLs using form data:
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"url": "https://api.example.com/countries/{{data.country}}/states",
|
|
150
|
+
"query": { "search": "{{ui.query}}" }
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Load Strategies
|
|
155
|
+
Control when data is fetched:
|
|
156
|
+
|
|
157
|
+
- `mount` - Load when component mounts (default)
|
|
158
|
+
- `onFocus` - Load when field receives focus
|
|
159
|
+
- `query` - Load when user types (autocomplete)
|
|
160
|
+
|
|
161
|
+
### Composables
|
|
162
|
+
Use providers directly in your components:
|
|
163
|
+
|
|
164
|
+
```vue
|
|
165
|
+
<script setup>
|
|
166
|
+
import { useProvider } from '@narrative.io/jsonforms-provider-protocols/vue'
|
|
167
|
+
|
|
168
|
+
const { items, loading, error, reload } = useProvider(binding, context)
|
|
169
|
+
</script>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 🛠 Development
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Install dependencies
|
|
176
|
+
bun install
|
|
177
|
+
|
|
178
|
+
# Run tests
|
|
179
|
+
bun test
|
|
180
|
+
|
|
181
|
+
# Build library
|
|
182
|
+
bun run build
|
|
183
|
+
|
|
184
|
+
# Type checking
|
|
185
|
+
bunx vue-tsc --noEmit
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 🤝 Contributing
|
|
189
|
+
|
|
190
|
+
Contributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) and check out the [issue tracker](https://github.com/narrative-io/jsonforms-provider-protocols/issues).
|
|
191
|
+
|
|
192
|
+
## 📄 License
|
|
193
|
+
|
|
194
|
+
MIT - see [LICENSE](./LICENSE) file for details.
|
|
195
|
+
|
|
196
|
+
## 🆘 Support
|
|
197
|
+
|
|
198
|
+
- [Documentation](./docs/)
|
|
199
|
+
- [GitHub Issues](https://github.com/narrative-io/jsonforms-provider-protocols/issues)
|
|
200
|
+
- [Troubleshooting Guide](./docs/troubleshooting.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_plugin-vue_export-helper.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AACA,qBAAa,QAAQ,CAAC,CAAC;IACrB,OAAO,CAAC,CAAC,CAA+B;IACxC,GAAG,CAAC,CAAC,EAAE,MAAM;IASb,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,SAAI;IAM/B,GAAG,CAAC,CAAC,EAAE,MAAM;CAGd;AACD,eAAO,MAAM,KAAK,mBAA0B,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class TTLCache {
|
|
2
|
+
m = /* @__PURE__ */ new Map();
|
|
3
|
+
get(k) {
|
|
4
|
+
const e = this.m.get(k);
|
|
5
|
+
if (!e) return void 0;
|
|
6
|
+
if (e.expiresAt !== 0 && Date.now() > e.expiresAt) {
|
|
7
|
+
this.m.delete(k);
|
|
8
|
+
return void 0;
|
|
9
|
+
}
|
|
10
|
+
return e.value;
|
|
11
|
+
}
|
|
12
|
+
set(k, v, ttlSec = 0) {
|
|
13
|
+
this.m.set(k, {
|
|
14
|
+
value: v,
|
|
15
|
+
expiresAt: ttlSec ? Date.now() + ttlSec * 1e3 : 0
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
del(k) {
|
|
19
|
+
this.m.delete(k);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const cache = new TTLCache();
|
|
23
|
+
export {
|
|
24
|
+
TTLCache,
|
|
25
|
+
cache
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sources":["../../src/core/cache.ts"],"sourcesContent":["type Entry<T> = { value: T; expiresAt: number };\nexport class TTLCache<T> {\n private m = new Map<string, Entry<T>>();\n get(k: string) {\n const e = this.m.get(k);\n if (!e) return undefined;\n if (e.expiresAt !== 0 && Date.now() > e.expiresAt) {\n this.m.delete(k);\n return undefined;\n }\n return e.value;\n }\n set(k: string, v: T, ttlSec = 0) {\n this.m.set(k, {\n value: v,\n expiresAt: ttlSec ? Date.now() + ttlSec * 1000 : 0,\n });\n }\n del(k: string) {\n this.m.delete(k);\n }\n}\nexport const cache = new TTLCache<unknown>();\n"],"names":[],"mappings":"AACO,MAAM,SAAY;AAAA,EACf,wBAAQ,IAAA;AAAA,EAChB,IAAI,GAAW;AACb,UAAM,IAAI,KAAK,EAAE,IAAI,CAAC;AACtB,QAAI,CAAC,EAAG,QAAO;AACf,QAAI,EAAE,cAAc,KAAK,KAAK,IAAA,IAAQ,EAAE,WAAW;AACjD,WAAK,EAAE,OAAO,CAAC;AACf,aAAO;AAAA,IACT;AACA,WAAO,EAAE;AAAA,EACX;AAAA,EACA,IAAI,GAAW,GAAM,SAAS,GAAG;AAC/B,SAAK,EAAE,IAAI,GAAG;AAAA,MACZ,OAAO;AAAA,MACP,WAAW,SAAS,KAAK,IAAA,IAAQ,SAAS,MAAO;AAAA,IAAA,CAClD;AAAA,EACH;AAAA,EACA,IAAI,GAAW;AACb,SAAK,EAAE,OAAO,CAAC;AAAA,EACjB;AACF;AACO,MAAM,QAAQ,IAAI,SAAA;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonpath.d.ts","sourceRoot":"","sources":["../../src/core/jsonpath.ts"],"names":[],"mappings":"AAAA,wBAAgB,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAwCxD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function jp(obj, path) {
|
|
2
|
+
if (path === "$") return [obj];
|
|
3
|
+
if (path === "") return [obj];
|
|
4
|
+
if (!path || typeof path !== "string") return [];
|
|
5
|
+
if (path.startsWith("$[*]")) {
|
|
6
|
+
if (!Array.isArray(obj)) return [];
|
|
7
|
+
const remainingPath = path.slice(4);
|
|
8
|
+
if (!remainingPath) return obj;
|
|
9
|
+
if (remainingPath.startsWith(".")) {
|
|
10
|
+
const subPath = remainingPath.slice(1);
|
|
11
|
+
const results = [];
|
|
12
|
+
for (const item of obj) {
|
|
13
|
+
results.push(...jp(item, subPath));
|
|
14
|
+
}
|
|
15
|
+
return results;
|
|
16
|
+
}
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const parts = path.replace(/^\$\./, "").split(".");
|
|
20
|
+
let current = [obj];
|
|
21
|
+
for (const part of parts) {
|
|
22
|
+
const next = [];
|
|
23
|
+
const m = part.match(/^(\w+)(\[\*\])?$/);
|
|
24
|
+
if (!m) return [];
|
|
25
|
+
const key = m[1];
|
|
26
|
+
if (!key) return [];
|
|
27
|
+
const star = !!m[2];
|
|
28
|
+
for (const c of current) {
|
|
29
|
+
const v = c?.[key];
|
|
30
|
+
if (star && Array.isArray(v)) next.push(...v);
|
|
31
|
+
else if (!star && v !== void 0) next.push(v);
|
|
32
|
+
}
|
|
33
|
+
current = next;
|
|
34
|
+
}
|
|
35
|
+
return current;
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
jp
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=jsonpath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonpath.js","sources":["../../src/core/jsonpath.ts"],"sourcesContent":["export function jp(obj: unknown, path: string): unknown[] {\n // naive: support \"$.a.b[*].c\" & \"$.items[*]\"\n if (path === \"$\") return [obj];\n if (path === \"\") return [obj]; // Empty string should behave like \"$\"\n if (!path || typeof path !== \"string\") return [];\n\n // Handle array at root with $[*]\n if (path.startsWith(\"$[*]\")) {\n if (!Array.isArray(obj)) return [];\n const remainingPath = path.slice(4); // Remove \"$[*]\"\n if (!remainingPath) return obj;\n if (remainingPath.startsWith(\".\")) {\n // Continue with remaining path for each array element\n const subPath = remainingPath.slice(1);\n const results: unknown[] = [];\n for (const item of obj) {\n results.push(...jp(item, subPath));\n }\n return results;\n }\n return [];\n }\n\n const parts = path.replace(/^\\$\\./, \"\").split(\".\");\n let current: unknown[] = [obj];\n for (const part of parts) {\n const next: unknown[] = [];\n const m = part.match(/^(\\w+)(\\[\\*\\])?$/);\n if (!m) return [];\n const key = m[1];\n if (!key) return [];\n const star = !!m[2];\n for (const c of current) {\n const v = (c as Record<string, unknown>)?.[key];\n if (star && Array.isArray(v)) next.push(...v);\n else if (!star && v !== undefined) next.push(v);\n }\n current = next;\n }\n return current;\n}\n"],"names":[],"mappings":"AAAO,SAAS,GAAG,KAAc,MAAyB;AAExD,MAAI,SAAS,IAAK,QAAO,CAAC,GAAG;AAC7B,MAAI,SAAS,GAAI,QAAO,CAAC,GAAG;AAC5B,MAAI,CAAC,QAAQ,OAAO,SAAS,iBAAiB,CAAA;AAG9C,MAAI,KAAK,WAAW,MAAM,GAAG;AAC3B,QAAI,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAA;AAChC,UAAM,gBAAgB,KAAK,MAAM,CAAC;AAClC,QAAI,CAAC,cAAe,QAAO;AAC3B,QAAI,cAAc,WAAW,GAAG,GAAG;AAEjC,YAAM,UAAU,cAAc,MAAM,CAAC;AACrC,YAAM,UAAqB,CAAA;AAC3B,iBAAW,QAAQ,KAAK;AACtB,gBAAQ,KAAK,GAAG,GAAG,MAAM,OAAO,CAAC;AAAA,MACnC;AACA,aAAO;AAAA,IACT;AACA,WAAO,CAAA;AAAA,EACT;AAEA,QAAM,QAAQ,KAAK,QAAQ,SAAS,EAAE,EAAE,MAAM,GAAG;AACjD,MAAI,UAAqB,CAAC,GAAG;AAC7B,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAkB,CAAA;AACxB,UAAM,IAAI,KAAK,MAAM,kBAAkB;AACvC,QAAI,CAAC,EAAG,QAAO,CAAA;AACf,UAAM,MAAM,EAAE,CAAC;AACf,QAAI,CAAC,IAAK,QAAO,CAAA;AACjB,UAAM,OAAO,CAAC,CAAC,EAAE,CAAC;AAClB,eAAW,KAAK,SAAS;AACvB,YAAM,IAAK,IAAgC,GAAG;AAC9C,UAAI,QAAQ,MAAM,QAAQ,CAAC,EAAG,MAAK,KAAK,GAAG,CAAC;AAAA,eACnC,CAAC,QAAQ,MAAM,OAAW,MAAK,KAAK,CAAC;AAAA,IAChD;AACA,cAAU;AAAA,EACZ;AACA,SAAO;AACT;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAA+B;IAC9C,QAAQ,CAAC,CAAC,EAAE,QAAQ;IAGpB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ;CAK5B;AAED,eAAO,MAAM,QAAQ,kBAAyB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class ProtocolRegistry {
|
|
2
|
+
drivers = /* @__PURE__ */ new Map();
|
|
3
|
+
register(p) {
|
|
4
|
+
this.drivers.set(p.protocol, p);
|
|
5
|
+
}
|
|
6
|
+
get(name) {
|
|
7
|
+
const p = this.drivers.get(name);
|
|
8
|
+
if (!p) throw new Error(`Protocol '${name}' not registered`);
|
|
9
|
+
return p;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const registry = new ProtocolRegistry();
|
|
13
|
+
export {
|
|
14
|
+
ProtocolRegistry,
|
|
15
|
+
registry
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sources":["../../src/core/registry.ts"],"sourcesContent":["import type { Protocol } from \"./types\";\n\nexport class ProtocolRegistry {\n private drivers = new Map<string, Protocol>();\n register(p: Protocol) {\n this.drivers.set(p.protocol, p);\n }\n get(name: string): Protocol {\n const p = this.drivers.get(name);\n if (!p) throw new Error(`Protocol '${name}' not registered`);\n return p;\n }\n}\n\nexport const registry = new ProtocolRegistry();\n"],"names":[],"mappings":"AAEO,MAAM,iBAAiB;AAAA,EACpB,8BAAc,IAAA;AAAA,EACtB,SAAS,GAAa;AACpB,SAAK,QAAQ,IAAI,EAAE,UAAU,CAAC;AAAA,EAChC;AAAA,EACA,IAAI,MAAwB;AAC1B,UAAM,IAAI,KAAK,QAAQ,IAAI,IAAI;AAC/B,QAAI,CAAC,EAAG,OAAM,IAAI,MAAM,aAAa,IAAI,kBAAkB;AAC3D,WAAO;AAAA,EACT;AACF;AAEO,MAAM,WAAW,IAAI,iBAAA;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templating.d.ts","sourceRoot":"","sources":["../../src/core/templating.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAY3D;AACD,wBAAgB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,CAAC,CAapE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
function renderTpl(str, ctx) {
|
|
2
|
+
return str.replace(/\{\{\s*([^}]+)\s*\}\}/g, (_, path) => {
|
|
3
|
+
const trimmedPath = path.trim();
|
|
4
|
+
return String(
|
|
5
|
+
trimmedPath.split(".").reduce((a, k) => {
|
|
6
|
+
if (a && typeof a === "object" && k in a) {
|
|
7
|
+
return a[k];
|
|
8
|
+
}
|
|
9
|
+
return void 0;
|
|
10
|
+
}, ctx) ?? ""
|
|
11
|
+
);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function renderObj(obj, ctx) {
|
|
15
|
+
if (!obj || typeof obj !== "object") return obj;
|
|
16
|
+
const out = Array.isArray(obj) ? [] : {};
|
|
17
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
18
|
+
if (typeof v === "string") {
|
|
19
|
+
out[k] = renderTpl(v, ctx);
|
|
20
|
+
} else if (v && typeof v === "object") {
|
|
21
|
+
out[k] = renderObj(v, ctx);
|
|
22
|
+
} else {
|
|
23
|
+
out[k] = v;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
renderObj,
|
|
30
|
+
renderTpl
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=templating.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templating.js","sources":["../../src/core/templating.ts"],"sourcesContent":["export function renderTpl(str: string, ctx: unknown): string {\n return str.replace(/\\{\\{\\s*([^}]+)\\s*\\}\\}/g, (_, path) => {\n const trimmedPath = path.trim();\n return String(\n trimmedPath.split(\".\").reduce((a: unknown, k: string) => {\n if (a && typeof a === \"object\" && k in a) {\n return (a as Record<string, unknown>)[k];\n }\n return undefined;\n }, ctx) ?? \"\",\n );\n });\n}\nexport function renderObj<T = unknown>(obj: unknown, ctx: unknown): T {\n if (!obj || typeof obj !== \"object\") return obj as T;\n const out: Record<string, unknown> | unknown[] = Array.isArray(obj) ? [] : {};\n for (const [k, v] of Object.entries(obj)) {\n if (typeof v === \"string\") {\n (out as Record<string, unknown>)[k] = renderTpl(v, ctx);\n } else if (v && typeof v === \"object\") {\n (out as Record<string, unknown>)[k] = renderObj(v, ctx);\n } else {\n (out as Record<string, unknown>)[k] = v;\n }\n }\n return out as T;\n}\n"],"names":[],"mappings":"AAAO,SAAS,UAAU,KAAa,KAAsB;AAC3D,SAAO,IAAI,QAAQ,0BAA0B,CAAC,GAAG,SAAS;AACxD,UAAM,cAAc,KAAK,KAAA;AACzB,WAAO;AAAA,MACL,YAAY,MAAM,GAAG,EAAE,OAAO,CAAC,GAAY,MAAc;AACvD,YAAI,KAAK,OAAO,MAAM,YAAY,KAAK,GAAG;AACxC,iBAAQ,EAA8B,CAAC;AAAA,QACzC;AACA,eAAO;AAAA,MACT,GAAG,GAAG,KAAK;AAAA,IAAA;AAAA,EAEf,CAAC;AACH;AACO,SAAS,UAAuB,KAAc,KAAiB;AACpE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAA2C,MAAM,QAAQ,GAAG,IAAI,CAAA,IAAK,CAAA;AAC3E,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,QAAI,OAAO,MAAM,UAAU;AACxB,UAAgC,CAAC,IAAI,UAAU,GAAG,GAAG;AAAA,IACxD,WAAW,KAAK,OAAO,MAAM,UAAU;AACpC,UAAgC,CAAC,IAAI,UAAU,GAAG,GAAG;AAAA,IACxD,OAAO;AACJ,UAAgC,CAAC,IAAI;AAAA,IACxC;AAAA,EACF;AACA,SAAO;AACT;"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type ProviderItem = {
|
|
2
|
+
label: string;
|
|
3
|
+
value: unknown;
|
|
4
|
+
meta?: Record<string, unknown>;
|
|
5
|
+
};
|
|
6
|
+
export type ProviderOutput = {
|
|
7
|
+
items: ProviderItem[];
|
|
8
|
+
ttl?: number;
|
|
9
|
+
etag?: string;
|
|
10
|
+
};
|
|
11
|
+
export type ProviderContext = {
|
|
12
|
+
data: unknown;
|
|
13
|
+
path: string;
|
|
14
|
+
signal: AbortSignal;
|
|
15
|
+
ui?: {
|
|
16
|
+
query?: string;
|
|
17
|
+
};
|
|
18
|
+
auth?: Record<string, unknown>;
|
|
19
|
+
};
|
|
20
|
+
export interface Protocol<Cfg = unknown> {
|
|
21
|
+
protocol: string;
|
|
22
|
+
resolve(cfg: Cfg, ctx: ProviderContext): Promise<ProviderOutput>;
|
|
23
|
+
}
|
|
24
|
+
export interface ProviderBinding {
|
|
25
|
+
ref: string;
|
|
26
|
+
protocol: string;
|
|
27
|
+
config?: unknown;
|
|
28
|
+
auth?: AuthConfig;
|
|
29
|
+
cacheTTL?: number;
|
|
30
|
+
load?: "mount" | "onFocus" | "query";
|
|
31
|
+
}
|
|
32
|
+
export type Mapping = {
|
|
33
|
+
label: string;
|
|
34
|
+
value: string;
|
|
35
|
+
meta?: Record<string, string>;
|
|
36
|
+
};
|
|
37
|
+
export interface AuthConfig {
|
|
38
|
+
use?: string;
|
|
39
|
+
apiKey?: string | (() => string);
|
|
40
|
+
bearer?: string | (() => string);
|
|
41
|
+
token?: string | (() => string);
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,WAAW,QAAQ,CAAC,GAAG,GAAG,OAAO;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;CACtC;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { App } from "vue";
|
|
2
|
+
import type { Protocol, AuthConfig } from "./core/types";
|
|
3
|
+
export { cache } from "./core/cache";
|
|
4
|
+
export * from "./core/jsonpath";
|
|
5
|
+
export { registry } from "./core/registry";
|
|
6
|
+
export * from "./core/templating";
|
|
7
|
+
export * from "./core/types";
|
|
8
|
+
export { RestApiProtocol } from "./protocols/rest_api";
|
|
9
|
+
export * as vue from "./vue";
|
|
10
|
+
export interface ProviderConfig {
|
|
11
|
+
protocols?: Protocol[];
|
|
12
|
+
auth?: AuthConfig;
|
|
13
|
+
}
|
|
14
|
+
declare const _default: {
|
|
15
|
+
install(app: App, opts?: ProviderConfig): void;
|
|
16
|
+
};
|
|
17
|
+
export default _default;
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAG/B,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAElC,cAAc,cAAc,CAAC;AAG7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAE7B,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;;iBAGc,GAAG,SAAS,cAAc;;AADzC,wBAYE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { cache } from "./core/cache.js";
|
|
2
|
+
import { registry } from "./core/registry.js";
|
|
3
|
+
import { jp } from "./core/jsonpath.js";
|
|
4
|
+
import { renderObj, renderTpl } from "./core/templating.js";
|
|
5
|
+
import { RestApiProtocol } from "./protocols/rest_api.js";
|
|
6
|
+
import * as vue_index from "./vue/index.js";
|
|
7
|
+
const index = {
|
|
8
|
+
install(app, opts) {
|
|
9
|
+
const reg = registry;
|
|
10
|
+
if (opts?.protocols) {
|
|
11
|
+
for (const p of opts.protocols) {
|
|
12
|
+
reg.register(p);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
app.provide("providerRegistry", reg);
|
|
16
|
+
app.provide("providerCache", cache);
|
|
17
|
+
app.provide("providerAuth", opts?.auth ?? {});
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export {
|
|
21
|
+
RestApiProtocol,
|
|
22
|
+
cache,
|
|
23
|
+
index as default,
|
|
24
|
+
jp,
|
|
25
|
+
registry,
|
|
26
|
+
renderObj,
|
|
27
|
+
renderTpl,
|
|
28
|
+
vue_index as vue
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import type { App } from \"vue\";\nimport { cache as globalCache } from \"./core/cache\";\nimport { registry as globalRegistry } from \"./core/registry\";\nimport type { Protocol, AuthConfig } from \"./core/types\";\n\nexport { cache } from \"./core/cache\";\nexport * from \"./core/jsonpath\";\nexport { registry } from \"./core/registry\";\nexport * from \"./core/templating\";\n// Core exports\nexport * from \"./core/types\";\n\n// Protocol exports\nexport { RestApiProtocol } from \"./protocols/rest_api\";\n\n// Vue exports\nexport * as vue from \"./vue\";\n\nexport interface ProviderConfig {\n protocols?: Protocol[];\n auth?: AuthConfig;\n}\n\nexport default {\n install(app: App, opts?: ProviderConfig) {\n const reg = globalRegistry;\n if (opts?.protocols) {\n for (const p of opts.protocols) {\n reg.register(p);\n }\n }\n app.provide(\"providerRegistry\", reg);\n app.provide(\"providerCache\", globalCache);\n app.provide(\"providerAuth\", opts?.auth ?? {});\n },\n};\n"],"names":["globalRegistry","globalCache"],"mappings":";;;;;;AAuBA,MAAA,QAAe;AAAA,EACb,QAAQ,KAAU,MAAuB;AACvC,UAAM,MAAMA;AACZ,QAAI,MAAM,WAAW;AACnB,iBAAW,KAAK,KAAK,WAAW;AAC9B,YAAI,SAAS,CAAC;AAAA,MAChB;AAAA,IACF;AACA,QAAI,QAAQ,oBAAoB,GAAG;AACnC,QAAI,QAAQ,iBAAiBC,KAAW;AACxC,QAAI,QAAQ,gBAAgB,MAAM,QAAQ,CAAA,CAAE;AAAA,EAC9C;AACF;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Protocol, AuthConfig } from "../core/types";
|
|
2
|
+
export type RestApiCfg = {
|
|
3
|
+
url: string;
|
|
4
|
+
method?: "GET" | "POST";
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
query?: Record<string, unknown>;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
items: string;
|
|
9
|
+
map: {
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
meta?: Record<string, string>;
|
|
13
|
+
};
|
|
14
|
+
paginate?: {
|
|
15
|
+
cursorPath: string;
|
|
16
|
+
param: string;
|
|
17
|
+
maxPages?: number;
|
|
18
|
+
};
|
|
19
|
+
auth?: AuthConfig;
|
|
20
|
+
};
|
|
21
|
+
export declare const RestApiProtocol: () => Protocol<RestApiCfg>;
|
|
22
|
+
//# sourceMappingURL=rest_api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rest_api.d.ts","sourceRoot":"","sources":["../../src/protocols/rest_api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,QAAQ,EAGR,UAAU,EACX,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IACrE,QAAQ,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,CAAC;AA0DF,eAAO,MAAM,eAAe,QAAO,QAAQ,CAAC,UAAU,CA0DpD,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { jp } from "../core/jsonpath.js";
|
|
2
|
+
import { renderTpl, renderObj } from "../core/templating.js";
|
|
3
|
+
function buildAuthHeaders(auth, globalAuth) {
|
|
4
|
+
const headers = {};
|
|
5
|
+
if (!auth) return headers;
|
|
6
|
+
if (auth.use && globalAuth?.[auth.use]) {
|
|
7
|
+
const globalValue = globalAuth[auth.use];
|
|
8
|
+
const value = typeof globalValue === "function" ? globalValue() : globalValue;
|
|
9
|
+
if (auth.use === "apiKey") {
|
|
10
|
+
headers["X-API-Key"] = String(value);
|
|
11
|
+
} else if (auth.use === "bearer") {
|
|
12
|
+
headers["Authorization"] = `Bearer ${value}`;
|
|
13
|
+
} else if (auth.use === "token") {
|
|
14
|
+
headers["Authorization"] = `Token ${value}`;
|
|
15
|
+
}
|
|
16
|
+
return headers;
|
|
17
|
+
}
|
|
18
|
+
if (auth.apiKey) {
|
|
19
|
+
const value = typeof auth.apiKey === "function" ? auth.apiKey() : auth.apiKey;
|
|
20
|
+
headers["X-API-Key"] = String(value);
|
|
21
|
+
}
|
|
22
|
+
if (auth.bearer) {
|
|
23
|
+
const value = typeof auth.bearer === "function" ? auth.bearer() : auth.bearer;
|
|
24
|
+
headers["Authorization"] = `Bearer ${value}`;
|
|
25
|
+
}
|
|
26
|
+
if (auth.token) {
|
|
27
|
+
const value = typeof auth.token === "function" ? auth.token() : auth.token;
|
|
28
|
+
headers["Authorization"] = `Token ${value}`;
|
|
29
|
+
}
|
|
30
|
+
for (const [key, value] of Object.entries(auth)) {
|
|
31
|
+
if (!["use", "apiKey", "bearer", "token"].includes(key) && value !== void 0) {
|
|
32
|
+
const authValue = typeof value === "function" ? value() : value;
|
|
33
|
+
headers[key] = String(authValue);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return headers;
|
|
37
|
+
}
|
|
38
|
+
const RestApiProtocol = () => ({
|
|
39
|
+
protocol: "rest_api",
|
|
40
|
+
async resolve(cfg, ctx) {
|
|
41
|
+
const ac = ctx.signal;
|
|
42
|
+
const out = [];
|
|
43
|
+
let cursor = null;
|
|
44
|
+
let page = 0;
|
|
45
|
+
do {
|
|
46
|
+
const url = new URL(renderTpl(cfg.url, { data: ctx.data, ui: ctx.ui }));
|
|
47
|
+
const q = renderObj(cfg.query ?? {}, {
|
|
48
|
+
data: ctx.data,
|
|
49
|
+
ui: ctx.ui
|
|
50
|
+
});
|
|
51
|
+
for (const [k, v] of Object.entries(q))
|
|
52
|
+
if (v !== void 0 && v !== "") url.searchParams.set(k, String(v));
|
|
53
|
+
if (cursor && cfg.paginate)
|
|
54
|
+
url.searchParams.set(cfg.paginate.param, String(cursor));
|
|
55
|
+
const baseHeaders = renderObj(cfg.headers ?? {}, {
|
|
56
|
+
data: ctx.data
|
|
57
|
+
});
|
|
58
|
+
const authHeaders = buildAuthHeaders(cfg.auth, ctx.auth);
|
|
59
|
+
const headers = { ...baseHeaders, ...authHeaders };
|
|
60
|
+
const method = cfg.method ?? "GET";
|
|
61
|
+
const requestInit = {
|
|
62
|
+
method,
|
|
63
|
+
headers,
|
|
64
|
+
signal: ac
|
|
65
|
+
};
|
|
66
|
+
if (method !== "GET" && cfg.body) {
|
|
67
|
+
requestInit.body = JSON.stringify(
|
|
68
|
+
renderObj(cfg.body, { data: ctx.data })
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const res = await fetch(url.toString(), requestInit);
|
|
72
|
+
if (!res.ok) throw new Error(`REST ${res.status}`);
|
|
73
|
+
const json = await res.json();
|
|
74
|
+
const items = jp(json, cfg.items);
|
|
75
|
+
for (const it of items) {
|
|
76
|
+
const label = jp(it, cfg.map.label)[0];
|
|
77
|
+
const value = jp(it, cfg.map.value)[0];
|
|
78
|
+
const meta = cfg.map.meta ? Object.fromEntries(
|
|
79
|
+
Object.entries(cfg.map.meta).map(([k, p]) => [k, jp(it, p)[0]])
|
|
80
|
+
) : void 0;
|
|
81
|
+
out.push({ label: String(label ?? ""), value, meta });
|
|
82
|
+
}
|
|
83
|
+
cursor = cfg.paginate ? jp(json, cfg.paginate.cursorPath)[0] : null;
|
|
84
|
+
page += 1;
|
|
85
|
+
} while (cfg.paginate && cursor && page < (cfg.paginate.maxPages ?? 5));
|
|
86
|
+
return { items: out, ttl: 300 };
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
export {
|
|
90
|
+
RestApiProtocol
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=rest_api.js.map
|