Skip to content

Commit

Permalink
$mol_service refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
zerkalica committed Nov 2, 2024
1 parent 00dcb49 commit 33b1fc6
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 104 deletions.
10 changes: 7 additions & 3 deletions notify/notify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ namespace $ {
}

static show( info: $mol_notify_info ) {
this.$.$mol_service_worker.send(info)
this.$.$mol_service.send(info)
}

}

export class $mol_notify_service extends $mol_service_plugin_notify {
static override message_data(data: {}) {
static override data(data: {}) {
if ('uri' in data && 'message' in data) {
this.show(data as $mol_notify_info)
return true
Expand All @@ -31,5 +31,9 @@ namespace $ {
static show(info: $mol_notify_info) {}

}


export namespace $mol_service_plugin {
export let $mol_notify_service = $.$mol_notify_service
}

}
11 changes: 4 additions & 7 deletions notify/notify.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace $ {

export class $mol_notify_service_web extends $mol_notify_service {
static override show({ context: title, message: body, uri: data }: $mol_notify_info) {
const registration = this.$.$mol_service_worker_web.registration()
const registration = this.$.$mol_service_web.registration()
const tag = data
const existen = registration.getNotifications({ tag })

Expand All @@ -50,7 +50,7 @@ namespace $ {
}

static override notification( notification: Notification ) {
const matched = this.$.$mol_service_worker_web.clients_filter({ includeUncontrolled: true, type: 'window' })
const matched = this.$.$mol_service_web.clients_filter({ includeUncontrolled: true, type: 'window' })
const last = matched.at(-1)

if( last ) {
Expand All @@ -60,15 +60,12 @@ namespace $ {
return null
}

this.$.$mol_service_worker_web.window_open( notification.data )
this.$.$mol_service_web.window_open( notification.data )
return null
}
}

$.$mol_notify_service = $mol_notify_service_web

export namespace $mol_service {
export const $mol_notify_service = $mol_notify_service_web
}

$mol_service_plugin.$mol_notify_service = $mol_notify_service_web
}
4 changes: 4 additions & 0 deletions offline/offline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ namespace $ {
return clone
}
}

export namespace $mol_service_plugin {
export let $mol_offline = $.$mol_offline
}
}
8 changes: 2 additions & 6 deletions offline/offline.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@ namespace $ {
}

static override activate() {
return this.$.$mol_service_worker_web.claim()
return this.$.$mol_service_web.claim()
}
}

$.$mol_offline = $mol_offline_web

export namespace $mol_service {
export const $mol_offline = $mol_offline_web
}

$mol_service_plugin.$mol_offline = $mol_offline_web
}
41 changes: 41 additions & 0 deletions service/channel/channel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace $ {
export class $mol_service_channel extends $mol_object {
protected channel = new MessageChannel()

timeout() { return 20000 }

out() { return this.channel.port2 }

result() { return $mol_wire_sync(this).result_async() }

result_async() {
return new Promise<unknown>((resolve, reject) => {
const channel = this.channel

const handler = setTimeout(
() => reject(new Error('Channel timeout', { cause: channel })),
this.timeout()
)

this.destructor = () => {
clearTimeout(handler)
reject(new Error('Channel cancelled'))
}

channel.port1.onmessage = event => {
clearTimeout(handler)
const data = event.data
const message = data?.error ?? (data?.result ? null : 'empty data')
if (message) return reject(new Error(message, { cause: event }))

resolve(event.data.result)
}

channel.port1.onmessageerror = event => {
clearTimeout(handler)
reject(new Error('Can\'t be deserialized: ' + event.data, { cause: event }))
}
})
}
}
}
18 changes: 9 additions & 9 deletions service/plugin/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
namespace $ {
export class $mol_service_plugin extends $mol_object {
export namespace $mol_service_plugin {
let _
}

export class $mol_service_plugin_base extends $mol_object {
static install() { return null as unknown }
static activate() { return null as unknown }
static message_data(data: {}) { return null as unknown }

static service() { return this.$.$mol_service_worker }
static data(data: {}) { return null as unknown }
}

export class $mol_service_plugin_cache extends $mol_service_plugin {
export class $mol_service_plugin_cache extends $mol_service_plugin_base {
static blocked(request: Request) { return false }
static modify(request: Request, waitUntil: (promise: Promise<unknown>) => void) {
return null as null | Response
}
static modify(request: Request) { return null as null | Response }
}

export class $mol_service_plugin_notify extends $mol_service_plugin {
export class $mol_service_plugin_notify extends $mol_service_plugin_base {
static notification(e: unknown) { return null as unknown }
}
}
32 changes: 30 additions & 2 deletions service/service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
namespace $.$mol_service {
let _
namespace $ {
export class $mol_service extends $mol_object {
static path() { return 'web.js' }

static send_timeout() { return 20000 }

@ $mol_action
static send(data: {}) { return null as unknown }

@ $mol_mem
static prepare(next?: $mol_service_prepare_event) {
return next ? next : null
}

@ $mol_mem
static prepare_choise() { return $mol_wire_sync(this).choise_promise()?.outcome ?? null }

static choise_promise() { return this.prepare()?.userChoise }

static blocked_response() {
return new Response(
null,
{
status: 418,
statusText: 'Blocked'
},
)
}
}

}
73 changes: 27 additions & 46 deletions service/worker/worker.web.ts → service/service.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace $ {

export class $mol_service_worker_web extends $mol_service_worker {
export class $mol_service_web extends $mol_service {
protected static in_worker() { return typeof window === 'undefined' }

@ $mol_mem
Expand Down Expand Up @@ -40,7 +40,7 @@ namespace $ {
}

@ $mol_mem
static registration_events_attached() {
protected static registration_events_attached() {
const reg = this.registration()
if (reg.waiting) this.state(null)
else if (reg.installing) this.update_found()
Expand Down Expand Up @@ -85,14 +85,14 @@ namespace $ {

@ $mol_mem
static plugins() {
return Object.values(this.$.$mol_service) as (
typeof $mol_service_plugin
return Object.values(this.$.$mol_service_plugin) as (
typeof $mol_service_plugin_base
| typeof $mol_service_plugin_notify
| typeof $mol_service_plugin_cache
)[]
}

protected static log_plugin_error(plugin: typeof $mol_service_plugin, error: unknown) {
protected static log_plugin_error(plugin: typeof $mol_service_plugin_base, error: unknown) {
if ($mol_fail_catch(error)) {
;(error as Error).message = `${plugin.toString()}: ${(error as Error).message}`
console.error(error)
Expand All @@ -104,6 +104,7 @@ namespace $ {
const scope = self as unknown as ServiceWorkerGlobalScope

scope.addEventListener( 'install' , event => {
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting#examples
scope.skipWaiting()
event.waitUntil($mol_wire_async(this).install(event))
})
Expand Down Expand Up @@ -158,43 +159,22 @@ namespace $ {
}

@ $mol_action
protected static post_message(data: unknown) {
const channel = this.$.$mol_service_channel.make({
timeout: () => this.send_timeout()
})

this.registration_ready().active!.postMessage(data, [ channel.out() ])

return channel
}

static override send(data: {}) {
if (this.in_worker()) {
throw new Error('Worker can\'t send messages, use clients api')
}

return $mol_wire_sync(this).send_async(data)
}

@ $mol_action
static send_async(data: Record<string, unknown>) {
const active = this.registration_ready().active!

// https://github.com/GoogleChrome/samples/blob/gh-pages/service-worker/post-message/demo.js
return new Promise<unknown>((reject, resolve) => {
const channel = new MessageChannel()

const handler = setTimeout(
() => reject(new Error('Service worker not responding', { cause: channel })),
this.send_timeout()
)

channel.port1.onmessage = event => {
clearTimeout(handler)
const data = event.data
const message = data?.error ?? (data?.result ? null : 'empty data')
if (message) return reject(new Error(message, { cause: event }))

resolve(event.data.result)
}

channel.port1.onmessageerror = event => {
clearTimeout(handler)
reject(new Error('Can\'t be deserialized: ' + event.data, { cause: event }))
}

active.postMessage(data, [ channel.port2 ])
})
return this.post_message(data).result()
}

static message(event: $mol_service_message_event) {
Expand All @@ -203,7 +183,7 @@ namespace $ {

for (const plugin of this.plugins()) {
try {
const result = plugin.message_data(data)
const result = plugin.data(data)
if (result) return event.result(result)
} catch (error) {
event.error(error as Error)
Expand Down Expand Up @@ -257,29 +237,30 @@ namespace $ {
}

@ $mol_action
static block(event: FetchEvent) {
static block(request: Request) {
for (const plugin of this.plugins()) {
if ( ! ( plugin.prototype instanceof $mol_service_plugin_cache ) ) continue

try {
if ((plugin as typeof $mol_service_plugin_cache).blocked(event.request)) {
return event.respondWith(this.blocked_response())
if ((plugin as typeof $mol_service_plugin_cache).blocked(request)) {
return this.blocked_response()
}
} catch (error) {
this.log_plugin_error(plugin, error)
}
}
return null
}

static fetch(event: FetchEvent) {
this.block(event)
const waitUntil = event.waitUntil.bind(event)
const response = this.block(event.request)
if (response) return event.respondWith(response)

for (const plugin of this.plugins()) {
if ( ! ( plugin.prototype instanceof $mol_service_plugin_cache ) ) continue

try {
const response = (plugin as typeof $mol_service_plugin_cache).modify(event.request, waitUntil)
const response = (plugin as typeof $mol_service_plugin_cache).modify(event.request)
if (response) return event.respondWith(response)
} catch (error) {
this.log_plugin_error(plugin, error)
Expand All @@ -288,8 +269,8 @@ namespace $ {
}
}

$.$mol_service_worker = $mol_service_worker_web
$.$mol_service = $mol_service_web

$mol_service_worker_web.init()
$mol_service_web.init()

}
31 changes: 0 additions & 31 deletions service/worker/worker.ts

This file was deleted.

0 comments on commit 33b1fc6

Please sign in to comment.