@stone-js/starters 0.8.10 → 0.8.12
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/basic-react-declarative/package.json +5 -5
- package/basic-react-imperative/package.json +5 -5
- package/basic-react-native-declarative/App.tsx +16 -182
- package/basic-react-native-declarative/README.md +136 -21
- package/basic-react-native-declarative/app/Application.ts +17 -6
- package/basic-react-native-declarative/app/HomeScreen.tsx +80 -0
- package/basic-react-native-declarative/app/PortalMark.tsx +32 -0
- package/basic-react-native-declarative/app/WelcomeView.tsx +146 -0
- package/basic-react-native-declarative/app/theme.ts +66 -0
- package/basic-react-native-declarative/app.json +10 -3
- package/basic-react-native-declarative/assets/android-icon-background.png +0 -0
- package/basic-react-native-declarative/assets/android-icon-foreground.png +0 -0
- package/basic-react-native-declarative/assets/android-icon-monochrome.png +0 -0
- package/basic-react-native-declarative/assets/favicon.png +0 -0
- package/basic-react-native-declarative/assets/icon.png +0 -0
- package/basic-react-native-declarative/assets/logo-dark.png +0 -0
- package/basic-react-native-declarative/assets/logo-light.png +0 -0
- package/basic-react-native-declarative/assets/splash-icon.png +0 -0
- package/basic-react-native-declarative/index.ts +16 -8
- package/basic-react-native-declarative/metro.config.js +9 -3
- package/basic-react-native-declarative/package.json +9 -4
- package/basic-react-native-declarative/tests/Application.spec.ts +41 -43
- package/basic-react-native-declarative/tests/stubs/react-native.ts +42 -0
- package/basic-react-native-declarative/tsconfig.json +0 -1
- package/basic-react-native-declarative/vitest.config.ts +13 -5
- package/basic-react-native-imperative/App.tsx +26 -0
- package/basic-react-native-imperative/LICENSE +21 -0
- package/basic-react-native-imperative/README.md +150 -0
- package/basic-react-native-imperative/app/Application.ts +25 -0
- package/basic-react-native-imperative/app/HomeScreen.tsx +84 -0
- package/basic-react-native-imperative/app/PortalMark.tsx +32 -0
- package/basic-react-native-imperative/app/WelcomeView.tsx +146 -0
- package/basic-react-native-imperative/app/theme.ts +66 -0
- package/basic-react-native-imperative/app.json +32 -0
- package/basic-react-native-imperative/assets/android-icon-background.png +0 -0
- package/basic-react-native-imperative/assets/android-icon-foreground.png +0 -0
- package/basic-react-native-imperative/assets/android-icon-monochrome.png +0 -0
- package/basic-react-native-imperative/assets/favicon.png +0 -0
- package/basic-react-native-imperative/assets/icon.png +0 -0
- package/basic-react-native-imperative/assets/logo-dark.png +0 -0
- package/basic-react-native-imperative/assets/logo-light.png +0 -0
- package/basic-react-native-imperative/assets/splash-icon.png +0 -0
- package/basic-react-native-imperative/babel.config.js +16 -0
- package/basic-react-native-imperative/index.ts +30 -0
- package/basic-react-native-imperative/metro.config.js +13 -0
- package/basic-react-native-imperative/package.json +46 -0
- package/basic-react-native-imperative/tests/Application.spec.ts +63 -0
- package/basic-react-native-imperative/tests/stubs/react-native.ts +42 -0
- package/basic-react-native-imperative/tsconfig.json +15 -0
- package/basic-react-native-imperative/vitest.config.ts +35 -0
- package/basic-service-declarative/package.json +4 -4
- package/basic-service-imperative/package.json +4 -4
- package/continuum-showcase/package.json +9 -9
- package/full-react-declarative/app/layout/AppLayout/AppLayout.tsx +1 -1
- package/full-react-declarative/app/layout/ErrorLayout/ErrorLayout.tsx +1 -1
- package/full-react-declarative/app/layout/SecurityLayout/SecurityLayout.tsx +1 -1
- package/full-react-declarative/package.json +10 -10
- package/full-react-imperative/app/layout/AppLayout/AppLayout.tsx +1 -1
- package/full-react-imperative/app/layout/ErrorLayout/ErrorLayout.tsx +1 -1
- package/full-react-imperative/app/layout/SecurityLayout/SecurityLayout.tsx +1 -1
- package/full-react-imperative/app/layout/SettingsLayout/SettingsLayout.tsx +1 -1
- package/full-react-imperative/package.json +10 -10
- package/full-service-declarative/package.json +10 -10
- package/full-service-imperative/package.json +10 -10
- package/package.json +29 -15
- package/standard-react-declarative/package.json +9 -9
- package/standard-react-imperative/package.json +9 -9
- package/standard-service-declarative/package.json +7 -7
- package/standard-service-imperative/package.json +7 -7
- package/basic-react-native-declarative/adapter/NativeAdapter.ts +0 -108
- package/basic-react-native-declarative/adapter/NativeErrorHandler.ts +0 -53
- package/basic-react-native-declarative/adapter/NativeEventSource.ts +0 -58
- package/basic-react-native-declarative/adapter/RawResponseWrapper.ts +0 -30
- package/basic-react-native-declarative/adapter/declarations.ts +0 -40
- package/basic-react-native-declarative/adapter/middleware.ts +0 -73
- package/basic-react-native-declarative/adapter/nativeAdapterBlueprint.ts +0 -51
- package/basic-react-native-declarative/adapter/renderSink.ts +0 -52
- package/basic-react-native-declarative/app/WelcomeController.ts +0 -66
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { RawResponseWrapper } from './RawResponseWrapper'
|
|
2
|
-
import { NativeAdapterContext, NativeResponse, RawNativeResponseOptions } from './declarations'
|
|
3
|
-
import { NativeEventSource, NativeNavigationEvent, nativeEventSource } from './NativeEventSource'
|
|
4
|
-
import { Adapter, AdapterEventBuilder, AdapterEventHandlerType, IBlueprint } from '@stone-js/core'
|
|
5
|
-
import { IncomingBrowserEvent, IncomingBrowserEventOptions, OutgoingBrowserResponse } from '@stone-js/browser-core'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Native proof-of-concept adapter for Stone.js.
|
|
9
|
-
*
|
|
10
|
-
* Captures navigation intents from the in-memory event source, normalizes them
|
|
11
|
-
* into `IncomingBrowserEvent` instances, sends them through the kernel and
|
|
12
|
-
* executes the deferred render effect. It is the exact native counterpart of
|
|
13
|
-
* `BrowserAdapter`, with the event source replacing `window`.
|
|
14
|
-
*
|
|
15
|
-
* Temporary by design: it prefigures `@stone-js/react-native-adapter`, which
|
|
16
|
-
* will capture real deep links (`Linking`) and app-state changes on top of the
|
|
17
|
-
* same skeleton.
|
|
18
|
-
*/
|
|
19
|
-
export class NativeAdapter extends Adapter<
|
|
20
|
-
NativeNavigationEvent,
|
|
21
|
-
NativeResponse,
|
|
22
|
-
NativeEventSource,
|
|
23
|
-
IncomingBrowserEvent,
|
|
24
|
-
IncomingBrowserEventOptions,
|
|
25
|
-
OutgoingBrowserResponse,
|
|
26
|
-
NativeAdapterContext
|
|
27
|
-
> {
|
|
28
|
-
private unsubscribe?: () => void
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Creates an instance of the `NativeAdapter`.
|
|
32
|
-
*
|
|
33
|
-
* @param blueprint - The application blueprint.
|
|
34
|
-
* @returns A new instance of `NativeAdapter`.
|
|
35
|
-
*/
|
|
36
|
-
static create (blueprint: IBlueprint): NativeAdapter {
|
|
37
|
-
return new this(blueprint)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Executes the adapter: subscribes to navigation intents and dispatches the
|
|
42
|
-
* initial event, exactly like the browser adapter dispatches its synthetic
|
|
43
|
-
* first navigation on startup.
|
|
44
|
-
*
|
|
45
|
-
* Idempotent: running again tears down the previous subscription first.
|
|
46
|
-
*/
|
|
47
|
-
public async run<ExecutionResultType = undefined>(): Promise<ExecutionResultType> {
|
|
48
|
-
await this.executeHooks('onStart')
|
|
49
|
-
|
|
50
|
-
const eventHandler = this.resolveEventHandler()
|
|
51
|
-
|
|
52
|
-
await this.executeEventHandlerHooks('onInit', eventHandler)
|
|
53
|
-
|
|
54
|
-
this.unsubscribe?.()
|
|
55
|
-
this.unsubscribe = nativeEventSource.subscribe((rawEvent) => {
|
|
56
|
-
void this.eventListener(eventHandler, rawEvent)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
await this.eventListener(eventHandler, { url: nativeEventSource.initialUrl })
|
|
60
|
-
|
|
61
|
-
return undefined as ExecutionResultType
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Tear down the adapter: remove the navigation subscription and run the
|
|
66
|
-
* `onStop` hooks. Safe to call multiple times.
|
|
67
|
-
*/
|
|
68
|
-
public async stop (): Promise<void> {
|
|
69
|
-
if (this.unsubscribe === undefined) { return }
|
|
70
|
-
this.unsubscribe()
|
|
71
|
-
this.unsubscribe = undefined
|
|
72
|
-
await this.executeHooks('onStop')
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Processes one navigation intent through the kernel.
|
|
77
|
-
*
|
|
78
|
-
* @param eventHandler - The resolved kernel event handler.
|
|
79
|
-
* @param rawEvent - The raw navigation event.
|
|
80
|
-
* @returns The platform response.
|
|
81
|
-
*/
|
|
82
|
-
protected async eventListener (
|
|
83
|
-
eventHandler: AdapterEventHandlerType<IncomingBrowserEvent, OutgoingBrowserResponse>,
|
|
84
|
-
rawEvent: NativeNavigationEvent
|
|
85
|
-
): Promise<NativeResponse> {
|
|
86
|
-
const incomingEventBuilder = AdapterEventBuilder.create<IncomingBrowserEventOptions, IncomingBrowserEvent>({
|
|
87
|
-
resolver: (options) => IncomingBrowserEvent.create(options)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
const rawResponseBuilder = AdapterEventBuilder.create<RawNativeResponseOptions, RawResponseWrapper>({
|
|
91
|
-
resolver: (options) => RawResponseWrapper.create(options)
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
const context: NativeAdapterContext = {
|
|
95
|
-
rawEvent,
|
|
96
|
-
executionContext: nativeEventSource,
|
|
97
|
-
rawResponseBuilder,
|
|
98
|
-
incomingEventBuilder
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
return await this.sendEventThroughDestination(context, eventHandler)
|
|
103
|
-
} catch (error: any) {
|
|
104
|
-
const builder = await this.handleError(error, context)
|
|
105
|
-
return await this.buildRawResponse({ ...context, rawResponseBuilder: builder })
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { emitNativeError } from './renderSink'
|
|
2
|
-
import { NativeResponse } from './declarations'
|
|
3
|
-
import { NativeEventSource, NativeNavigationEvent } from './NativeEventSource'
|
|
4
|
-
import {
|
|
5
|
-
ILogger,
|
|
6
|
-
IBlueprint,
|
|
7
|
-
LoggerResolver,
|
|
8
|
-
AdapterErrorContext,
|
|
9
|
-
IAdapterErrorHandler,
|
|
10
|
-
defaultLoggerResolver,
|
|
11
|
-
AdapterEventBuilderType
|
|
12
|
-
} from '@stone-js/core'
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* NativeErrorHandler options.
|
|
16
|
-
*/
|
|
17
|
-
export interface NativeErrorHandlerOptions {
|
|
18
|
-
blueprint: IBlueprint
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Adapter-level error handler: logs the error and surfaces it on screen
|
|
23
|
-
* through the render sink, so a broken chain is visible instead of silent.
|
|
24
|
-
*/
|
|
25
|
-
export class NativeErrorHandler implements IAdapterErrorHandler<NativeNavigationEvent, NativeResponse, NativeEventSource> {
|
|
26
|
-
private readonly logger: ILogger
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Create a NativeErrorHandler.
|
|
30
|
-
*
|
|
31
|
-
* @param options - NativeErrorHandler options.
|
|
32
|
-
*/
|
|
33
|
-
constructor ({ blueprint }: NativeErrorHandlerOptions) {
|
|
34
|
-
this.logger = blueprint.get<LoggerResolver>('stone.logger.resolver', defaultLoggerResolver)(blueprint)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Handle an error.
|
|
39
|
-
*
|
|
40
|
-
* @param error - The error to handle.
|
|
41
|
-
* @param context - The context of the adapter.
|
|
42
|
-
* @returns The raw response builder.
|
|
43
|
-
*/
|
|
44
|
-
public handle (
|
|
45
|
-
error: Error,
|
|
46
|
-
context: AdapterErrorContext<NativeNavigationEvent, NativeResponse, NativeEventSource>
|
|
47
|
-
): AdapterEventBuilderType<NativeResponse> {
|
|
48
|
-
this.logger.error(error.message, { error })
|
|
49
|
-
emitNativeError(error)
|
|
50
|
-
|
|
51
|
-
return context.rawResponseBuilder
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The native cause captured by the adapter: an intent to show a URL.
|
|
3
|
-
*
|
|
4
|
-
* On a real device this is what a deep link, a push-notification tap or an
|
|
5
|
-
* in-app navigation collapses to. The proof-of-concept models all of them as
|
|
6
|
-
* one tiny in-memory event source; the future `@stone-js/react-native-adapter`
|
|
7
|
-
* will plug `Linking` and `AppState` into the exact same shape.
|
|
8
|
-
*/
|
|
9
|
-
export interface NativeNavigationEvent {
|
|
10
|
-
/** The URL to resolve, e.g. `stone://app/hello/Noowow`. */
|
|
11
|
-
url: string
|
|
12
|
-
/** Optional navigation metadata, mirroring the browser's `history.state`. */
|
|
13
|
-
metadata?: unknown
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* A navigation listener registered by the adapter.
|
|
18
|
-
*/
|
|
19
|
-
export type NativeNavigationListener = (event: NativeNavigationEvent) => void
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* The in-memory navigation event source: the native counterpart of `window`
|
|
23
|
-
* for the browser adapter. It is pure JavaScript, so the same code runs under
|
|
24
|
-
* React Native, Node (tests) and anywhere else.
|
|
25
|
-
*/
|
|
26
|
-
export class NativeEventSource {
|
|
27
|
-
/** The synthetic first event, dispatched when the adapter starts. */
|
|
28
|
-
public readonly initialUrl = 'stone://app/'
|
|
29
|
-
|
|
30
|
-
private readonly listeners = new Set<NativeNavigationListener>()
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Register a navigation listener.
|
|
34
|
-
*
|
|
35
|
-
* @param listener - The listener to register.
|
|
36
|
-
* @returns A teardown function removing the listener.
|
|
37
|
-
*/
|
|
38
|
-
subscribe (listener: NativeNavigationListener): () => void {
|
|
39
|
-
this.listeners.add(listener)
|
|
40
|
-
return () => { this.listeners.delete(listener) }
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Emit a navigation intent, exactly like the router does in the browser
|
|
45
|
-
* through the `@stonejs/router.navigate` custom event.
|
|
46
|
-
*
|
|
47
|
-
* @param url - The URL to navigate to.
|
|
48
|
-
* @param metadata - Optional navigation metadata.
|
|
49
|
-
*/
|
|
50
|
-
navigate (url: string, metadata?: unknown): void {
|
|
51
|
-
this.listeners.forEach((listener) => listener({ url, metadata }))
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* The application-wide event source instance.
|
|
57
|
-
*/
|
|
58
|
-
export const nativeEventSource = new NativeEventSource()
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { IRawResponseWrapper } from '@stone-js/core'
|
|
2
|
-
import { NativeResponse, RawNativeResponseOptions } from './declarations'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Wraps the raw native response: the platform effect is the deferred `render`
|
|
6
|
-
* closure contributed by the response middleware, executed once the kernel has
|
|
7
|
-
* resolved the outgoing response.
|
|
8
|
-
*/
|
|
9
|
-
export class RawResponseWrapper implements IRawResponseWrapper<NativeResponse> {
|
|
10
|
-
/**
|
|
11
|
-
* Factory method to create an instance of `RawResponseWrapper`.
|
|
12
|
-
*
|
|
13
|
-
* @param options - The raw response options.
|
|
14
|
-
* @returns A new instance of `RawResponseWrapper`.
|
|
15
|
-
*/
|
|
16
|
-
static create (options: RawNativeResponseOptions): RawResponseWrapper {
|
|
17
|
-
return new this(options)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
private constructor (private readonly options: RawNativeResponseOptions) {}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Execute the deferred render effect and return its result.
|
|
24
|
-
*
|
|
25
|
-
* @returns The platform response.
|
|
26
|
-
*/
|
|
27
|
-
async respond (): Promise<NativeResponse> {
|
|
28
|
-
return await this.options?.render?.()
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { RawResponseWrapper } from './RawResponseWrapper'
|
|
2
|
-
import { NativeEventSource, NativeNavigationEvent } from './NativeEventSource'
|
|
3
|
-
import { AdapterContext, IAdapterEventBuilder, RawResponseOptions } from '@stone-js/core'
|
|
4
|
-
import { IncomingBrowserEvent, IncomingBrowserEventOptions, OutgoingBrowserResponse } from '@stone-js/browser-core'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* The platform identifier exposed on every incoming event's source.
|
|
8
|
-
*/
|
|
9
|
-
export const NATIVE_PLATFORM = 'react-native'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The raw platform response. The native platform has no transport response:
|
|
13
|
-
* the effect is a render, so the raw response is whatever the renderer returns.
|
|
14
|
-
*/
|
|
15
|
-
export type NativeResponse = unknown
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Raw response options carrying the deferred `render` effect, mirroring the
|
|
19
|
-
* browser adapter's contract.
|
|
20
|
-
*/
|
|
21
|
-
export interface RawNativeResponseOptions extends RawResponseOptions {
|
|
22
|
-
render?: () => NativeResponse | Promise<NativeResponse>
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* The adapter context for the native proof-of-concept adapter.
|
|
27
|
-
*/
|
|
28
|
-
export type NativeAdapterContext = AdapterContext<
|
|
29
|
-
NativeNavigationEvent,
|
|
30
|
-
NativeResponse,
|
|
31
|
-
NativeEventSource,
|
|
32
|
-
IncomingBrowserEvent,
|
|
33
|
-
IncomingBrowserEventOptions,
|
|
34
|
-
OutgoingBrowserResponse
|
|
35
|
-
>
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The response builder used by the native adapter middleware.
|
|
39
|
-
*/
|
|
40
|
-
export type NativeAdapterResponseBuilder = IAdapterEventBuilder<RawNativeResponseOptions, RawResponseWrapper>
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { emitNativeRender } from './renderSink'
|
|
2
|
-
import { NextMiddleware } from '@stone-js/core'
|
|
3
|
-
import { CookieCollection } from '@stone-js/browser-core'
|
|
4
|
-
import { NATIVE_PLATFORM, NativeAdapterContext, NativeAdapterResponseBuilder } from './declarations'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Transforms the raw navigation event into the intention: an
|
|
8
|
-
* `IncomingBrowserEvent`, reused as-is from `@stone-js/browser-core`.
|
|
9
|
-
*
|
|
10
|
-
* This is the native mirror of the browser adapter's IncomingEventMiddleware:
|
|
11
|
-
* `location` comes from the event's URL instead of `window.location`, and the
|
|
12
|
-
* cookie collection is purely in memory (no `document`).
|
|
13
|
-
*/
|
|
14
|
-
export class IncomingEventMiddleware {
|
|
15
|
-
/**
|
|
16
|
-
* Handle the incoming raw event.
|
|
17
|
-
*
|
|
18
|
-
* @param context - The adapter context.
|
|
19
|
-
* @param next - The next middleware.
|
|
20
|
-
* @returns The response builder.
|
|
21
|
-
*/
|
|
22
|
-
async handle (
|
|
23
|
-
context: NativeAdapterContext,
|
|
24
|
-
next: NextMiddleware<NativeAdapterContext, NativeAdapterResponseBuilder>
|
|
25
|
-
): Promise<NativeAdapterResponseBuilder> {
|
|
26
|
-
const url = new URL(context.rawEvent.url)
|
|
27
|
-
|
|
28
|
-
context
|
|
29
|
-
.incomingEventBuilder
|
|
30
|
-
.add('url', url)
|
|
31
|
-
.add('queryString', url.search)
|
|
32
|
-
.add('protocol', url.protocol.replace(':', ''))
|
|
33
|
-
.add('metadata', context.rawEvent.metadata ?? {})
|
|
34
|
-
.add('cookies', CookieCollection.create(undefined, {}))
|
|
35
|
-
.add('source', {
|
|
36
|
-
rawEvent: context.rawEvent,
|
|
37
|
-
platform: NATIVE_PLATFORM,
|
|
38
|
-
rawContext: context.executionContext
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
return await next(context)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Contributes the deferred render effect: once the kernel has produced the
|
|
47
|
-
* outgoing response, hand it to the registered render target.
|
|
48
|
-
*
|
|
49
|
-
* This is the native mirror of the role `BrowserResponseMiddleware` plays for
|
|
50
|
-
* the browser platform in `@stone-js/use-react`.
|
|
51
|
-
*/
|
|
52
|
-
export class ResponseMiddleware {
|
|
53
|
-
/**
|
|
54
|
-
* Handle the outgoing response.
|
|
55
|
-
*
|
|
56
|
-
* @param context - The adapter context.
|
|
57
|
-
* @param next - The next middleware.
|
|
58
|
-
* @returns The response builder.
|
|
59
|
-
*/
|
|
60
|
-
async handle (
|
|
61
|
-
context: NativeAdapterContext,
|
|
62
|
-
next: NextMiddleware<NativeAdapterContext, NativeAdapterResponseBuilder>
|
|
63
|
-
): Promise<NativeAdapterResponseBuilder> {
|
|
64
|
-
context.rawResponseBuilder.add('render', () => {
|
|
65
|
-
if (context.outgoingResponse !== undefined) {
|
|
66
|
-
emitNativeRender(context.outgoingResponse)
|
|
67
|
-
}
|
|
68
|
-
return context.outgoingResponse
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
return await next(context)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { NATIVE_PLATFORM } from './declarations'
|
|
2
|
-
import { NativeAdapter } from './NativeAdapter'
|
|
3
|
-
import { NativeErrorHandler } from './NativeErrorHandler'
|
|
4
|
-
import { IncomingEventMiddleware, ResponseMiddleware } from './middleware'
|
|
5
|
-
import { AdapterConfig, AppConfig, defaultKernelResolver, IBlueprint, StoneBlueprint } from '@stone-js/core'
|
|
6
|
-
import { OutgoingBrowserResponse, OutgoingBrowserResponseOptions } from '@stone-js/browser-core'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Adapter resolver for the native proof-of-concept adapter.
|
|
10
|
-
*
|
|
11
|
-
* @param blueprint - The `IBlueprint` providing configuration and dependencies.
|
|
12
|
-
* @returns A `NativeAdapter` instance.
|
|
13
|
-
*/
|
|
14
|
-
export const nativeAdapterResolver = (blueprint: IBlueprint): NativeAdapter => {
|
|
15
|
-
return NativeAdapter.create(blueprint)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Blueprint for the native proof-of-concept adapter.
|
|
20
|
-
*
|
|
21
|
-
* Activated the canonical way: handed to `@StoneApp(options, [blueprints])`
|
|
22
|
-
* (declarative) or `defineStoneApp(handler, options, [blueprints])`
|
|
23
|
-
* (imperative). Being the only adapter, it is selected automatically.
|
|
24
|
-
*/
|
|
25
|
-
export const nativeAdapterBlueprint: StoneBlueprint = {
|
|
26
|
-
stone: {
|
|
27
|
-
kernel: {
|
|
28
|
-
responseResolver: (options: OutgoingBrowserResponseOptions) => {
|
|
29
|
-
return OutgoingBrowserResponse.create({ ...options, statusCode: options.statusCode ?? 200 })
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
adapters: [
|
|
33
|
-
{
|
|
34
|
-
current: false,
|
|
35
|
-
default: true,
|
|
36
|
-
variant: 'native',
|
|
37
|
-
platform: NATIVE_PLATFORM,
|
|
38
|
-
middleware: [
|
|
39
|
-
{ module: IncomingEventMiddleware, isClass: true, priority: 0 },
|
|
40
|
-
{ module: ResponseMiddleware, isClass: true, priority: 10 }
|
|
41
|
-
],
|
|
42
|
-
resolver: nativeAdapterResolver,
|
|
43
|
-
eventHandlerResolver: defaultKernelResolver,
|
|
44
|
-
events: [],
|
|
45
|
-
errorHandlers: {
|
|
46
|
-
default: { module: NativeErrorHandler, isClass: true }
|
|
47
|
-
}
|
|
48
|
-
} as unknown as AdapterConfig
|
|
49
|
-
]
|
|
50
|
-
} as Partial<AppConfig> as AppConfig
|
|
51
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { OutgoingBrowserResponse } from '@stone-js/browser-core'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A render listener: receives the kernel's outgoing response for display.
|
|
5
|
-
*/
|
|
6
|
-
export type NativeRenderListener = (response: OutgoingBrowserResponse) => void
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* An error listener: receives adapter-level errors for display.
|
|
10
|
-
*/
|
|
11
|
-
export type NativeErrorListener = (error: Error) => void
|
|
12
|
-
|
|
13
|
-
let renderListener: NativeRenderListener | undefined
|
|
14
|
-
let errorListener: NativeErrorListener | undefined
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Register the render effect target. In this proof of concept the target is
|
|
18
|
-
* the React root component's state; the future `@stone-js/use-react-native`
|
|
19
|
-
* response middleware will push into the native navigation stack instead.
|
|
20
|
-
*
|
|
21
|
-
* @param listener - The render listener.
|
|
22
|
-
*/
|
|
23
|
-
export function onNativeRender (listener: NativeRenderListener): void {
|
|
24
|
-
renderListener = listener
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Register the error display target.
|
|
29
|
-
*
|
|
30
|
-
* @param listener - The error listener.
|
|
31
|
-
*/
|
|
32
|
-
export function onNativeError (listener: NativeErrorListener): void {
|
|
33
|
-
errorListener = listener
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Push an outgoing response to the registered render target.
|
|
38
|
-
*
|
|
39
|
-
* @param response - The kernel's outgoing response.
|
|
40
|
-
*/
|
|
41
|
-
export function emitNativeRender (response: OutgoingBrowserResponse): void {
|
|
42
|
-
renderListener?.(response)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Push an error to the registered error target.
|
|
47
|
-
*
|
|
48
|
-
* @param error - The error to display.
|
|
49
|
-
*/
|
|
50
|
-
export function emitNativeError (error: Error): void {
|
|
51
|
-
errorListener?.(error)
|
|
52
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { Controller, Match } from '@stone-js/router'
|
|
2
|
-
import { IncomingBrowserEvent } from '@stone-js/browser-core'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The payload every route of this starter returns.
|
|
6
|
-
*/
|
|
7
|
-
export interface WelcomeData {
|
|
8
|
-
message: string
|
|
9
|
-
route: string
|
|
10
|
-
framework: {
|
|
11
|
-
name: string
|
|
12
|
-
tagline: string
|
|
13
|
-
docs: string
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* WelcomeController
|
|
19
|
-
*
|
|
20
|
-
* The routes are matched against the URL carried by each navigation event,
|
|
21
|
-
* exactly like they would be in a browser SPA or behind an HTTP adapter:
|
|
22
|
-
* the domain does not know it is running inside a native application.
|
|
23
|
-
*/
|
|
24
|
-
@Controller()
|
|
25
|
-
export class WelcomeController {
|
|
26
|
-
/**
|
|
27
|
-
* The landing route, dispatched once when the application starts.
|
|
28
|
-
*
|
|
29
|
-
* @returns The welcome payload.
|
|
30
|
-
*/
|
|
31
|
-
@Match('/')
|
|
32
|
-
welcome (): WelcomeData {
|
|
33
|
-
return this.present('Welcome to Stone.js on React Native!', '/')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* A parameterized route: the `name` route parameter is read from the event.
|
|
38
|
-
*
|
|
39
|
-
* @param event - The incoming navigation event.
|
|
40
|
-
* @returns The greeting payload.
|
|
41
|
-
*/
|
|
42
|
-
@Match('/hello/:name')
|
|
43
|
-
hello (event: IncomingBrowserEvent): WelcomeData {
|
|
44
|
-
const name = String(event.get<string>('name', 'World'))
|
|
45
|
-
return this.present(`Hello ${name}! Same domain, native screen.`, `/hello/${name}`)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Build the branded payload returned by every route.
|
|
50
|
-
*
|
|
51
|
-
* @param message - The message to display.
|
|
52
|
-
* @param route - The matched route path.
|
|
53
|
-
* @returns The payload.
|
|
54
|
-
*/
|
|
55
|
-
private present (message: string, route: string): WelcomeData {
|
|
56
|
-
return {
|
|
57
|
-
message,
|
|
58
|
-
route,
|
|
59
|
-
framework: {
|
|
60
|
-
name: 'Stone.js',
|
|
61
|
-
tagline: 'The continuum framework',
|
|
62
|
-
docs: 'https://stonejs.dev'
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|