@iankibetsh/vue-streamline 1.3.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,7 @@
1
- # Streamline Vue Plugin
1
+ # Streamline Vue Plugin (DEPRECATED — moved into @iankibetsh/sh-core)
2
+
3
+
4
+ > **⚠️ Deprecated as of v2.** The streamline implementation now ships inside [`@iankibetsh/sh-core`](https://www.npmjs.com/package/@iankibetsh/sh-core) — import `useStreamline` / `getActionUrl` from there. v2 of this package is a thin re-export shim kept for backward compatibility; the `streamlineHeaders` option is ignored (auth is handled by the sh-core API client).
2
5
 
3
6
  A robust Vue 3 plugin designed for seamless integration with Streamline backend services. It delivers reactive state management, intelligent caching, and dynamic action invocation.
4
7
 
package/package.json CHANGED
@@ -1,28 +1,33 @@
1
1
  {
2
- "name": "@iankibetsh/vue-streamline",
3
- "version": "1.3.6",
4
- "description": "Vue library for streamlining laravel backend services with @iankibet/streamline composer package",
5
- "type": "module",
6
- "scripts": {
7
- "dev": "vite",
8
- "build": "vite build",
9
- "preview": "vite preview"
10
- },
11
- "exports": {
12
- ".": "./src/index.js"
13
- },
14
- "keywords": [],
15
- "author": "Iankibet",
16
- "license": "ISC",
17
- "devDependencies": {
18
- "@vitejs/plugin-vue": "^6",
19
- "vite": "^7"
20
- },
21
- "peerDependencies": {
22
- "@iankibetsh/shframework": "^5",
23
- "vue": "^3"
24
- },
25
- "publishConfig": {
26
- "access": "public"
27
- }
28
- }
2
+ "name": "@iankibetsh/vue-streamline",
3
+ "version": "2.0.0",
4
+ "description": "DEPRECATED compatibility shim: streamline now lives in @iankibetsh/sh-core. Vue library for streamlining laravel backend services with @iankibet/streamline composer package",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "exports": {
12
+ ".": "./src/index.js"
13
+ },
14
+ "files": [
15
+ "src/index.js",
16
+ "src/plugins"
17
+ ],
18
+ "keywords": [],
19
+ "author": "Iankibet",
20
+ "license": "ISC",
21
+ "devDependencies": {
22
+ "@iankibetsh/sh-core": "file:../sh-core",
23
+ "@vitejs/plugin-vue": "^6",
24
+ "vite": "^8"
25
+ },
26
+ "peerDependencies": {
27
+ "@iankibetsh/sh-core": "^1",
28
+ "vue": "^3.5"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ }
33
+ }
package/src/index.js CHANGED
@@ -1,8 +1,7 @@
1
- import useStreamline from './composables/useStreamline.js'
2
- import getActionUrl from './composables/getActionUrl.js'
1
+ // v2: vue-streamline is a compatibility shim over @iankibetsh/sh-core,
2
+ // which now ships streamline as a first-class module. New code should
3
+ // import from '@iankibetsh/sh-core' directly.
3
4
  import streamline from './plugins/streamline.js'
4
- export {
5
- useStreamline,
6
- getActionUrl,
7
- streamline
8
- }
5
+
6
+ export { useStreamline, getActionUrl } from '@iankibetsh/sh-core'
7
+ export { streamline }
@@ -1,13 +1,21 @@
1
+ // v2: thin compat shim. The streamline implementation now lives in
2
+ // @iankibetsh/sh-core; this plugin only maps the old options onto the
3
+ // injection keys / window globals the core composable reads.
1
4
  const streamline = {
2
- install(app, options) {
3
- app.provide('streamlineUrl', options.streamlineUrl ?? '/api/streamline')
4
- // app.provide('streamlineHeaders', options.streamlineHeaders)
5
- app.provide('enableCache', options.enableCache ?? true)
6
-
7
- // put them on window
8
- window.streamlineUrl = options.streamlineUrl ?? '/api/streamline'
9
- window.enableCache = options.enableCache ?? true
5
+ install (app, options = {}) {
6
+ const streamlineUrl = options.streamlineUrl ?? '/api/streamline'
7
+ const enableCache = options.enableCache ?? true
8
+
9
+ app.provide('streamlineUrl', streamlineUrl)
10
+ app.provide('enableCache', enableCache)
11
+
12
+ window.streamlineUrl = streamlineUrl
13
+ window.enableCache = enableCache
14
+
15
+ if (options.streamlineHeaders) {
16
+ console.warn('[vue-streamline] `streamlineHeaders` is deprecated and ignored: requests are authenticated by the @iankibetsh/sh-core API client (bearer or cookie strategy).')
17
+ }
10
18
  }
11
19
  }
12
20
 
13
- export default streamline
21
+ export default streamline
@@ -1,34 +0,0 @@
1
- # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
- # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
-
4
- name: Node.js Package
5
-
6
- on:
7
- release:
8
- types: [created]
9
-
10
- jobs:
11
- build:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@v4
15
- - uses: actions/setup-node@v4
16
- with:
17
- node-version: 20
18
- - run: npm ci
19
- # - run: npm test
20
-
21
- publish-npm:
22
- needs: build
23
- runs-on: ubuntu-latest
24
- steps:
25
- - uses: actions/checkout@v4
26
- - uses: actions/setup-node@v4
27
- with:
28
- node-version: 20
29
- registry-url: https://registry.npmjs.org/
30
- - run: npm ci
31
- - run: npm run build
32
- - run: npm publish
33
- env:
34
- NODE_AUTH_TOKEN: ${{secrets.npm_token}}
@@ -1,3 +0,0 @@
1
- {
2
- "recommendations": ["Vue.volar"]
3
- }
package/index.html DELETED
@@ -1,12 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Streamline Framework</title>
7
- </head>
8
- <body>
9
- <div id="app"></div>
10
- <script type="module" src="/src/main.js"></script>
11
- </body>
12
- </html>
package/public/vite.svg DELETED
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
package/src/App.vue DELETED
@@ -1,66 +0,0 @@
1
- <script setup>
2
- import useStreamline from './composables/useStreamline.js'
3
- import { onMounted, ref, toRefs,computed } from 'vue'
4
- import SimpleGetActionUrl from './SimpleGetActionUrl.vue'
5
-
6
- const {loading, service:paybillService, getActionUrl,props,confirmAction} = useStreamline('mpesa/paybill',32)
7
-
8
- const existing = computed(()=>props.paybill)
9
- const foundPaybill = ref(null)
10
-
11
- onMounted(()=>{
12
- // paybillService.getPaybill(32).then(res=>{
13
- // foundPaybill.value = res
14
- // })
15
- })
16
- const findPaybill = async ()=>{
17
- // const res = confirmAction('Are you sure?')
18
- // res.getPaybill(32).then(res=>{
19
- // foundPaybill.value = res
20
- // })
21
- foundPaybill.value = await paybillService.confirm().getPaybill(32, {name: 'ian'})
22
- .catch(err=>{
23
- console.log(err)
24
- })
25
- }
26
- const refresh = ()=>{
27
- paybillService.refresh()
28
- }
29
- </script>
30
-
31
- <template>
32
- <div>
33
- <hr/>
34
- <h3>Destructed: {{ testKey }}</h3>
35
- <h3>Original: {{ props.testKey }}</h3>
36
- <h3>Original: {{ props.testKey }}</h3>
37
- <h3>Original: {{ props.testKey }}</h3>
38
- <h3>Original: {{ props.testKey }}</h3>
39
- <h3 class="text-success" >Loading : {{ loading }}</h3>
40
- <h1 @click="findPaybill">Get Paybill</h1>
41
- <h1 @click="refresh">Refresh</h1>
42
- {{ foundPaybill }}
43
- </div>
44
- <div class="alert alert-info">
45
- <h2>Existing</h2>
46
- <p>
47
- {{ existing }}
48
- </p>
49
- </div>
50
- <simple-get-action-url/>
51
- </template>
52
-
53
- <style scoped>
54
- .logo {
55
- height: 6em;
56
- padding: 1.5em;
57
- will-change: filter;
58
- transition: filter 300ms;
59
- }
60
- .logo:hover {
61
- filter: drop-shadow(0 0 2em #646cffaa);
62
- }
63
- .logo.vue:hover {
64
- filter: drop-shadow(0 0 2em #42b883aa);
65
- }
66
- </style>
@@ -1,11 +0,0 @@
1
- <script setup>
2
- import getActionUrl from './composables/getActionUrl.js'
3
- </script>
4
-
5
- <template>
6
- <h3>Sample Action Url: {{ getActionUrl('users:listUsers','admin','active') }}</h3>
7
- </template>
8
-
9
- <style scoped>
10
-
11
- </style>
@@ -1,7 +0,0 @@
1
- import useStreamline from './useStreamline.js'
2
-
3
-
4
- export default function getActionUrl(actionSlug, ...args) {
5
- const { getActionUrl } = useStreamline('')
6
- return getActionUrl(actionSlug, ...args)
7
- }
@@ -1,166 +0,0 @@
1
- import { inject, onMounted, reactive, ref } from 'vue'
2
- import { shApis, shRepo } from '@iankibetsh/shframework'
3
- import Cache from '../utils/cache'
4
-
5
- const useStreamline = (stream, ...initialArgs) => {
6
- let formData = {}
7
- const loading = ref(false)
8
- const propertiesFetched = ref(false)
9
- const confirmationMessage = ref(null)
10
-
11
- // Cache key for local storage, include initialArgs in the key
12
- const cacheKey = `streamline_${stream}_${initialArgs.join('_')}`
13
-
14
- // Inject headers and API endpoint
15
- const streamlineUrl = inject('streamlineUrl', window.streamlineUrl)
16
- const enableCache = inject('enableCache', window.enableCache ?? true)
17
-
18
- const originalProps = reactive({})
19
-
20
- // Proxy to intercept access
21
- const props = new Proxy(originalProps, {
22
- get(target, property, receiver) {
23
- if (!propertiesFetched.value) {
24
- fetchServiceProperties().then(() => target[property])
25
- }
26
- return Reflect.get(target, property, receiver) // Return the actual value
27
- },
28
- set(target, property, value, receiver) {
29
- return Reflect.set(target, property, value, receiver) // Update the value
30
- }
31
- })
32
-
33
- const fetchServiceProperties = async (force) => {
34
- if (!force) {
35
- if (loading.value || propertiesFetched.value) return
36
- }
37
-
38
- try {
39
- loading.value = true
40
- const response = await shApis.doPost(streamlineUrl, {
41
- action: 'onMounted',
42
- stream,
43
- params: initialArgs
44
- })
45
- assignProperties(response.data)
46
- if (enableCache) {
47
- await Cache.set(cacheKey, response.data)
48
- }
49
- } catch (error) {
50
- console.error(`Error fetching properties for stream ${stream}`, error)
51
- throw error
52
- } finally {
53
- propertiesFetched.value = true
54
- loading.value = false
55
- }
56
- }
57
-
58
- const assignProperties = (data) => {
59
- Object.assign(service, data.properties)
60
- Object.assign(originalProps, data.properties)
61
- }
62
-
63
- const handler = {
64
- get(target, prop, receiver) {
65
- if (prop in target) {
66
- return target[prop]
67
- }
68
-
69
- return (...args) => {
70
- if (prop === 'refresh' || prop === 'reload') {
71
- return fetchServiceProperties(true)
72
- }
73
- if (prop === 'confirm') {
74
- return confirmAction(args[0] ?? 'Are you sure?')
75
- }
76
- let repo = null
77
- const data = {
78
- action: prop,
79
- stream,
80
- ...formData,
81
- params: args,
82
- initialParams: initialArgs
83
- }
84
- args.forEach(arg => {
85
- if (arg && typeof arg === 'object' && !Array.isArray(arg)) {
86
- Object.assign(data, arg)
87
- }
88
- })
89
- if (confirmationMessage.value) {
90
- repo = shRepo.runPlainRequest(streamlineUrl, null, confirmationMessage.value, data)
91
- } else {
92
- repo = shApis
93
- .doPost(streamlineUrl, data);
94
- }
95
-
96
- loading.value = true
97
- return repo.then((response) => {
98
- loading.value = false
99
- if (confirmationMessage.value) {
100
- confirmationMessage.value = null
101
-
102
- if (!response.isConfirmed) {
103
- return
104
- }
105
- if (response.value?.success) {
106
- return response.value.response
107
- } else {
108
- // throw error
109
- throw response.value.error
110
- }
111
-
112
- }
113
-
114
- return response.data
115
- })
116
- .catch((error) => {
117
- loading.value = false
118
- console.error(`Error calling ${prop} on stream ${stream}`, error)
119
- throw error
120
- })
121
- }
122
- }
123
- }
124
- const getActionUrl = (action, ...args) => {
125
- let newStream = stream
126
- if (action.includes(':')) {
127
- [newStream, action] = action.split(':')
128
- }
129
- const post = {
130
- action,
131
- stream: newStream,
132
- params: args
133
- }
134
- return `${streamlineUrl}?${new URLSearchParams(post).toString()}`
135
- }
136
-
137
- const service = reactive({})
138
-
139
- // Confirmation wrapper
140
- const confirmAction = (message) => {
141
- confirmationMessage.value = message
142
- return new Proxy(service, handler)
143
- }
144
-
145
- onMounted(async () => {
146
- if (enableCache) {
147
- const cachedData = await Cache.get(cacheKey)
148
- if (cachedData) {
149
- assignProperties(cachedData)
150
- }
151
- }
152
- if (initialArgs.length > 0) {
153
- fetchServiceProperties()
154
- }
155
- })
156
-
157
- return {
158
- loading,
159
- service: new Proxy(service, handler),
160
- getActionUrl,
161
- confirmAction,
162
- props
163
- }
164
- }
165
-
166
- export default useStreamline
package/src/main.js DELETED
@@ -1,21 +0,0 @@
1
- import { createApp } from 'vue'
2
- import './style.css'
3
- import App from './App.vue'
4
- import streamline from './plugins/streamline.js'
5
- import { ShFrontend } from '@iankibetsh/shframework'
6
-
7
- const streamlineHeaders = {
8
- Authorization: 'Bearer ' + localStorage.getItem('access_token')
9
- }
10
- const streamlineUrl = 'http://2022-sharasms.test/api/streamline'
11
- const app = createApp(App)
12
- app.use(ShFrontend, {
13
- baseApiUrl: 'http://2022-sharasms.test/api'
14
- })
15
- app.use(streamline,{
16
- streamlineHeaders,
17
- streamlineUrl,
18
- enableCache: true
19
- })
20
-
21
- app.mount('#app')
package/src/style.css DELETED
@@ -1,79 +0,0 @@
1
- :root {
2
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3
- line-height: 1.5;
4
- font-weight: 400;
5
-
6
- color-scheme: light dark;
7
- color: rgba(255, 255, 255, 0.87);
8
- background-color: #242424;
9
-
10
- font-synthesis: none;
11
- text-rendering: optimizeLegibility;
12
- -webkit-font-smoothing: antialiased;
13
- -moz-osx-font-smoothing: grayscale;
14
- }
15
-
16
- a {
17
- font-weight: 500;
18
- color: #646cff;
19
- text-decoration: inherit;
20
- }
21
- a:hover {
22
- color: #535bf2;
23
- }
24
-
25
- body {
26
- margin: 0;
27
- display: flex;
28
- place-items: center;
29
- min-width: 320px;
30
- min-height: 100vh;
31
- }
32
-
33
- h1 {
34
- font-size: 3.2em;
35
- line-height: 1.1;
36
- }
37
-
38
- button {
39
- border-radius: 8px;
40
- border: 1px solid transparent;
41
- padding: 0.6em 1.2em;
42
- font-size: 1em;
43
- font-weight: 500;
44
- font-family: inherit;
45
- background-color: #1a1a1a;
46
- cursor: pointer;
47
- transition: border-color 0.25s;
48
- }
49
- button:hover {
50
- border-color: #646cff;
51
- }
52
- button:focus,
53
- button:focus-visible {
54
- outline: 4px auto -webkit-focus-ring-color;
55
- }
56
-
57
- .card {
58
- padding: 2em;
59
- }
60
-
61
- #app {
62
- max-width: 1280px;
63
- margin: 0 auto;
64
- padding: 2rem;
65
- text-align: center;
66
- }
67
-
68
- @media (prefers-color-scheme: light) {
69
- :root {
70
- color: #213547;
71
- background-color: #ffffff;
72
- }
73
- a:hover {
74
- color: #747bff;
75
- }
76
- button {
77
- background-color: #f9f9f9;
78
- }
79
- }
@@ -1,113 +0,0 @@
1
- const DB_NAME = 'streamline_cache'
2
- const STORE_NAME = 'properties'
3
- const DB_VERSION = 1
4
-
5
- const openDB = () => {
6
- return new Promise((resolve, reject) => {
7
- const request = indexedDB.open(DB_NAME, DB_VERSION)
8
-
9
- request.onupgradeneeded = (event) => {
10
- const db = event.target.result
11
- if (!db.objectStoreNames.contains(STORE_NAME)) {
12
- db.createObjectStore(STORE_NAME)
13
- }
14
- }
15
-
16
- request.onsuccess = (event) => {
17
- resolve(event.target.result)
18
- }
19
-
20
- request.onerror = (event) => {
21
- reject(event.target.error)
22
- }
23
- })
24
- }
25
-
26
- const Cache = {
27
- async get(key) {
28
- try {
29
- const db = await openDB()
30
- return new Promise((resolve, reject) => {
31
- const transaction = db.transaction(STORE_NAME, 'readonly')
32
- const store = transaction.objectStore(STORE_NAME)
33
- const request = store.get(key)
34
-
35
- request.onsuccess = () => {
36
- resolve(request.result)
37
- }
38
-
39
- request.onerror = () => {
40
- reject(request.error)
41
- }
42
- })
43
- } catch (error) {
44
- console.error('Error getting from IndexedDB cache', error)
45
- return null
46
- }
47
- },
48
-
49
- async set(key, value) {
50
- try {
51
- const db = await openDB()
52
- return new Promise((resolve, reject) => {
53
- const transaction = db.transaction(STORE_NAME, 'readwrite')
54
- const store = transaction.objectStore(STORE_NAME)
55
- const request = store.put(value, key)
56
-
57
- request.onsuccess = () => {
58
- resolve()
59
- }
60
-
61
- request.onerror = () => {
62
- reject(request.error)
63
- }
64
- })
65
- } catch (error) {
66
- console.error('Error setting in IndexedDB cache', error)
67
- }
68
- },
69
-
70
- async delete(key) {
71
- try {
72
- const db = await openDB()
73
- return new Promise((resolve, reject) => {
74
- const transaction = db.transaction(STORE_NAME, 'readwrite')
75
- const store = transaction.objectStore(STORE_NAME)
76
- const request = store.delete(key)
77
-
78
- request.onsuccess = () => {
79
- resolve()
80
- }
81
-
82
- request.onerror = () => {
83
- reject(request.error)
84
- }
85
- })
86
- } catch (error) {
87
- console.error('Error deleting from IndexedDB cache', error)
88
- }
89
- },
90
-
91
- async clear() {
92
- try {
93
- const db = await openDB()
94
- return new Promise((resolve, reject) => {
95
- const transaction = db.transaction(STORE_NAME, 'readwrite')
96
- const store = transaction.objectStore(STORE_NAME)
97
- const request = store.clear()
98
-
99
- request.onsuccess = () => {
100
- resolve()
101
- }
102
-
103
- request.onerror = () => {
104
- reject(request.error)
105
- }
106
- })
107
- } catch (error) {
108
- console.error('Error clearing IndexedDB cache', error)
109
- }
110
- }
111
- }
112
-
113
- export default Cache
package/vite.config.js DELETED
@@ -1,23 +0,0 @@
1
- // vite.config.js
2
- import { defineConfig } from 'vite';
3
- import vue from '@vitejs/plugin-vue';
4
-
5
- export default defineConfig({
6
- plugins: [vue()],
7
- build: {
8
- lib: {
9
- entry: './src/index.js',
10
- name: 'VueStreamline',
11
- fileName: (format) => `vue-streamline.${format}.js`,
12
- },
13
- rollupOptions: {
14
- // Make sure to externalize deps that shouldn't be bundled into your library
15
- external: ['vue'],
16
- output: {
17
- globals: {
18
- vue: 'Vue',
19
- },
20
- },
21
- },
22
- },
23
- });