@live-change/vue3-ssr 0.1.7 → 0.2.1

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/Api.js ADDED
@@ -0,0 +1,238 @@
1
+ import { DaoProxy, DaoPrerenderCache, DaoCache, Path } from "@live-change/dao"
2
+ import validators from '@live-change/framework/lib/utils/validators.js'
3
+ import { hashCode, encodeNumber, uidGenerator, randomString } from '@live-change/uid'
4
+ import { ref, computed, watch } from "vue"
5
+
6
+ class Api extends DaoProxy {
7
+ constructor(source, settings = {}) {
8
+ super()
9
+ this.source = source
10
+ this.settings = settings
11
+
12
+ this.uidGenerator = () => { throw new Error("uid generator not initialized yet") }
13
+
14
+ this.createReactiveObject = this.settings.createReactiveObject
15
+
16
+ this.preFetchComponents = []
17
+ this.afterPreFetch = []
18
+
19
+ this.validators = validators
20
+
21
+ this.globals = {
22
+ $validators: validators
23
+ }
24
+ this.globalInstances = []
25
+ }
26
+
27
+ setup(settings = this.settings) {
28
+ this.settings = settings
29
+ this.createReactiveObject = this.settings.createReactiveObject
30
+ this.setupCaches()
31
+ this.setupMetadata()
32
+ }
33
+
34
+ setupCaches() {
35
+ let dao = this.source
36
+ if(this.settings.cache) {
37
+ const cacheSettings = (typeof this.settings.cache) == 'object' ? this.settings.cache : {}
38
+ this.dataCache = new DaoCache(dao, cacheSettings)
39
+ dao = this.dataCache
40
+ }
41
+ if(this.settings.ssr) {
42
+ this.prerenderCache = new DaoPrerenderCache(dao)
43
+ dao = this.prerenderCache
44
+ if(typeof window == 'undefined') {
45
+ this.prerenderCache.mode = 'save'
46
+ } else {
47
+ this.prerenderCache.mode = 'load'
48
+ this.prerenderCache.setCache(window[this.settings.ssrCacheGlobal || '__DAO_CACHE__'])
49
+ }
50
+ }
51
+ this.setDao(dao)
52
+ }
53
+
54
+ setupMetadata() {
55
+ const api = ref()
56
+ this.apiObservable = this.observable(['metadata', 'api'])
57
+ this.apiObservable.bindProperty(api, 'value')
58
+ const version = ref()
59
+ this.versionObservable = this.observable(['version', 'version'])
60
+ this.versionObservable.bindProperty(version, 'value')
61
+ const softwareVersion = computed(() => {
62
+ if(typeof window == 'undefined') return
63
+ return window[this.settings.ssrVersionGlobal || '__VERSION__']
64
+ })
65
+ const versionMismatch = computed(() => {
66
+ if(!version) return
67
+ if(!softwareVersion) return
68
+ return version.value != softwareVersion.value
69
+ })
70
+ const client = computed(() => {
71
+ return api?.value?.client
72
+ })
73
+ watch(() => api, (api) => {
74
+ console.log("API CHANGE!", api)
75
+ if(!api) return
76
+ console.log("API CHANGE!", api)
77
+ api.generateServicesApi()
78
+ })
79
+ this.metadata = {
80
+ api, version,
81
+ softwareVersion,
82
+ versionMismatch,
83
+ client
84
+ }
85
+ this.afterPreFetch.push(() => this.generateServicesApi())
86
+ }
87
+
88
+ generateServicesApi() {
89
+ const api = this
90
+ let apiInfo = api.metadata.api?.value
91
+ if(!apiInfo) {
92
+ const cachePath = '["metadata","api"]'
93
+ if(typeof window != 'undefined') {
94
+ const ssrCache = window[this.settings.ssrCacheGlobal || '__DAO_CACHE__']
95
+ if(ssrCache) {
96
+ for(const [daoPath, value] of ssrCache) {
97
+ if(daoPath == cachePath) apiInfo = value
98
+ }
99
+ }
100
+ } else {
101
+ apiInfo = this.prerenderCache.cache.get(cachePath)
102
+ }
103
+ }
104
+ console.trace("GENERATE API SERVICES!")
105
+ console.log("GENERATE SERVICES API", apiInfo)
106
+ const definitions = apiInfo?.services
107
+ if(JSON.stringify(definitions) == JSON.stringify(api.servicesApiDefinitions)) return
108
+ if(!definitions) throw new Error("API DEFINITIONS NOT FOUND! UNABLE TO GENERATE API!")
109
+ api.uidGenerator = uidGenerator(
110
+ apiInfo.client.user || (apiInfo.client.session ? apiInfo.client.session.slice(0, 16) : randomString(10) )
111
+ , 1, '[]')
112
+ //console.log("GENERATE API DEFINITIONS", definitions)
113
+ api.servicesApiDefinitions = definitions
114
+ let globalViews = {}
115
+ let globalFetch = (...args) => new Path(...args)
116
+ let globalActions = {}
117
+ for(const serviceDefinition of definitions) {
118
+ let views = { }
119
+ globalViews[serviceDefinition.name] = views
120
+ for(const viewName in serviceDefinition.views) {
121
+ views[viewName] = (params) => [serviceDefinition.name, viewName, params]
122
+ views[viewName].definition = serviceDefinition.views[viewName]
123
+ }
124
+ let fetch = { }
125
+ globalFetch[serviceDefinition.name] = fetch
126
+ for(const viewName in serviceDefinition.views) {
127
+ fetch[viewName] = (params) => new Path([serviceDefinition.name, viewName, params])
128
+ fetch[viewName].definition = serviceDefinition.views[viewName]
129
+ }
130
+ let actions = { }
131
+ globalActions[serviceDefinition.name] = actions
132
+ for(const actionName in serviceDefinition.actions) {
133
+ actions[actionName] = (params) => api.command([serviceDefinition.name, actionName], params)
134
+ actions[actionName].definition = serviceDefinition.actions[actionName]
135
+ }
136
+ }
137
+
138
+ api.views = globalViews
139
+ api.fetch = globalFetch
140
+ api.actions = globalActions
141
+ api.client = this.metadata.client
142
+ api.uid = api.uidGenerator
143
+
144
+ api.globals.$lc = api
145
+
146
+ /// Deprecated:
147
+ api.globals.$api = this
148
+ api.globals.$views = this.views
149
+ api.globals.$actions = this.actions
150
+ api.globals.$fetch = this.fetch
151
+
152
+ for(const glob of this.globalInstances) {
153
+ this.installInstanceProperties(glob)
154
+ }
155
+ }
156
+
157
+ addGlobalInstance(globalProperties) {
158
+ this.globalInstances.push(globalProperties)
159
+ this.installInstanceProperties(globalProperties)
160
+ }
161
+
162
+ installInstanceProperties(globalProperties) {
163
+ for(const key in this.globals) {
164
+ globalProperties[key] = this.globals[key]
165
+ }
166
+ }
167
+
168
+ async preFetch() {
169
+ let preFetchPromises = []
170
+ for(const component of this.preFetchComponents) {
171
+ if(component.$options.reactivePreFetch) {
172
+ const paths = component.$options.reactivePreFetch.apply(this.globals)
173
+ console.log("PREFETCH PATHS", JSON.stringify(paths))
174
+ const promise = this.get({ paths })/*.then(results => {
175
+ for(let { what, data } of results) {
176
+ this.prerenderCache.set(what, data)
177
+ }
178
+ })*/// It's useless because DaoPrerenderCache support paths
179
+ preFetchPromises.push(promise)
180
+ }
181
+ }
182
+ preFetchPromises.push(this.get({ paths: [
183
+ { what: ['metadata', 'api'] },
184
+ { what: ['version', 'version'] }
185
+ ]}))
186
+ console.log("PREFETCH WAIT!")
187
+ // const apiPromise = this.apiObservable.wait()
188
+ // apiPromise.then(res => console.log("API RES", res))
189
+ // const versionPromise = this.versionObservable.wait()
190
+ // versionPromise.then(res => console.log("VERSION RES", res))
191
+ // if(this.apiObservable.getValue() === undefined) preFetchPromises.push(apiPromise)
192
+ // if(this.versionObservable.getValue() === undefined) preFetchPromises.push(versionPromise)
193
+ await Promise.all(preFetchPromises)
194
+ console.log("PREFETCHED", this.metadata.api, this.metadata.version)
195
+ for(const afterPreFetch of this.afterPreFetch) {
196
+ afterPreFetch()
197
+ }
198
+ }
199
+
200
+ async preFetchRoute(route, router) {
201
+ let preFetchPromises = []
202
+ for(const matched of route.value.matched) {
203
+ for(const name in matched.components) {
204
+ const component = matched.components[name]
205
+ if(component.reactivePreFetch) {
206
+ let paths = component.reactivePreFetch.call(this.globals, route.value, router)
207
+ //console.log("ROUTE", route, "PREFETCH PATHS", JSON.stringify(paths))
208
+ const promise = this.get({ paths }).then(results => {
209
+ for(let { what, data } of results) {
210
+ this.prerenderCache.set(what, data)
211
+ }
212
+ })
213
+ preFetchPromises.push(promise)
214
+ }
215
+ }
216
+ }
217
+ return Promise.all(preFetchPromises)
218
+ }
219
+
220
+ command(method, args = {}) {
221
+ const _commandId = args._commandId || this.uidGenerator()
222
+ console.trace("COMMAND "+_commandId+":"+JSON.stringify(method))
223
+ return this.request(method, { ...args, _commandId })
224
+ }
225
+
226
+ reverseRange(range) {
227
+ return {
228
+ gt: range.lt,
229
+ gte: range.lte,
230
+ lt: range.gt == '' ? '\xFF\xFF\xFF\xFF' : range.gt,
231
+ lte: range.gte,
232
+ limit: range.limit,
233
+ reverse: !range.reverse
234
+ }
235
+ }
236
+ }
237
+
238
+ export default Api
package/clientApi.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createReactiveObject } from '@live-change/vue3-components'
2
- import * as lcapi from '@live-change/vue-api'
3
2
  import * as lcdao from '@live-change/dao'
4
3
  import { reactiveMixin, reactivePrefetchMixin, ReactiveObservableList } from '@live-change/dao-vue3'
5
4
  import SockJsConnection from '@live-change/dao-sockjs'
5
+ import Api from "./Api.js"
6
6
 
7
7
  function clientApi(settings = {}) {
8
8
  const dao = new lcdao.Dao(window.__CREDENTIALS__, {
@@ -13,9 +13,9 @@ function clientApi(settings = {}) {
13
13
 
14
14
  ...settings,
15
15
 
16
- fastAuth: !window.hasOwnProperty('__CREDENTIALS__'),
17
-
18
16
  connectionSettings: {
17
+ fastAuth: !window.hasOwnProperty('__CREDENTIALS__'),
18
+
19
19
  queueRequestsWhenDisconnected: true,
20
20
  requestSendTimeout: Infinity,
21
21
  requestTimeout: Infinity,
@@ -37,9 +37,10 @@ function clientApi(settings = {}) {
37
37
  }
38
38
  })
39
39
 
40
- const api = new lcapi.Api(dao)
40
+ const api = new Api(dao)
41
41
  api.setup({
42
42
  ssr: true,
43
+ cache: true,
43
44
  createReactiveObject(definition) {
44
45
  //console.log("CREATE REACTIVE OBJECT", definition)
45
46
  return createReactiveObject(definition, reactiveMixin(api), reactivePrefetchMixin(api) )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/vue3-ssr",
3
- "version": "0.1.7",
3
+ "version": "0.2.1",
4
4
  "description": "Live Change Framework - vue components",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -23,7 +23,6 @@
23
23
  "dependencies": {
24
24
  "debug": "^4.3.2",
25
25
  "vue": "^3.2.21",
26
- "@live-change/vue-api": "^0.1.10",
27
26
  "@live-change/uid": "^0.1.3"
28
27
  }
29
28
  }
package/serverApi.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createReactiveObject } from '@live-change/vue3-components'
2
- import { Api } from '@live-change/vue-api'
2
+ import Api from './Api.js'
3
3
  import { reactiveMixin, reactivePrefetchMixin } from '@live-change/dao-vue3'
4
4
 
5
5
 
package/getIp.js DELETED
@@ -1,12 +0,0 @@
1
- function getIp(connection) {
2
- let ip =
3
- connection.headers['x-real-ip'] ||
4
- connection.headers['x-forwarded-for'] ||
5
- connection.remoteAddress ||
6
- (connection.connection && connection.connection.remoteAddress)
7
- ip = ip.split(',')[0]
8
- ip = ip.split(':').slice(-1)[0] //in case the ip returned in a format: "::ffff:146.xxx.xxx.xxx"
9
- return ip
10
- }
11
-
12
- module.exports = getIp
package/serverDao.js DELETED
@@ -1,56 +0,0 @@
1
- const { Dao } = require("@live-change/dao")
2
- const DaoWebsocket = require("@live-change/dao-websocket")
3
-
4
- function reactiveObservableListConstructor(reactive) {
5
- class ReactiveObservableList extends Dao.ObservableList {
6
- constructor(value, what, dispose) {
7
- super(value, what, dispose, (data) => {
8
- if(data && typeof data == 'object') {
9
- const activated = reactive(data)
10
- return activated
11
- }
12
- return data
13
- })
14
- }
15
- }
16
- return ReactiveObservableList
17
- }
18
-
19
- function serverDao(credentials, ip, settings) {
20
- const serverHost = settings.remoteUrl || process.env.API_SERVER || "localhost:" + (process.env.API_PORT || 8002)
21
- const wsServer = `ws://${serverHost}/api/ws`
22
-
23
- return new Dao(credentials, {
24
- remoteUrl: wsServer,
25
- protocols: {
26
- 'ws': DaoWebsocket.client
27
- },
28
-
29
- ...settings,
30
-
31
- connectionSettings: {
32
- headers: {
33
- 'X-real-ip': ip,
34
- 'X-forwarded-for': ip
35
- },
36
- queueRequestsWhenDisconnected: true,
37
- requestSendTimeout: 2300,
38
- requestTimeout: 10000,
39
- queueActiveRequestsOnDisconnect: false,
40
- autoReconnectDelay: 200,
41
- logLevel: 1,
42
- /*connectionMonitorFactory: (connection) =>
43
- new ReactiveDao.ConnectionMonitorPinger(connection, {
44
- pingInterval: 50,
45
- pongInterval: 200
46
- })*/
47
- ...(settings && settings.connectionSettings)
48
- },
49
- defaultRoute: {
50
- type: "remote",
51
- generator: settings.reactive ? reactiveObservableListConstructor(settings.reactive) : Dao.ObservableList
52
- }
53
- })
54
- }
55
-
56
- module.exports = serverDao