@sleeperhq/mini-core 1.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 ADDED
@@ -0,0 +1,9 @@
1
+ # Sleeper-Mini Core
2
+
3
+ ![Sleeper](https://user-images.githubusercontent.com/61988202/223927288-c54734de-39f9-40c5-bb24-d1b193c9c374.png)
4
+
5
+ ## Description
6
+
7
+ This package contains built in sleeper UI components and dev server functionality for creating mini apps.
8
+
9
+ Please see the main repo at [sleeper-mini](https://github.com/blitzstudios/sleeper-mini) for more information.
package/app.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "template",
3
+ "displayName": "template",
4
+ "remoteIP": "192.168.86.190",
5
+ "localSocketPort": 8082,
6
+ "remoteSocketPort": 9092,
7
+ "remoteBundlePort": 9091,
8
+ "release": true
9
+ }
package/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ import * as Sleeper from './src/components';
2
+ import DevServer from './src/dev_server';
3
+ import * as Types from './src/types';
4
+ import './src/packages';
5
+
6
+ export {Sleeper, DevServer, Types};
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@sleeperhq/mini-core",
3
+ "version": "1.0.0",
4
+ "description": "Core library frameworks for developing Sleeper Mini Apps.",
5
+ "main": "index.ts",
6
+ "types": "index.d.ts",
7
+ "scripts": {
8
+ "test": "jest",
9
+ "lint": "eslint ."
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/blitzstudios/sleeper-mini-core.git"
14
+ },
15
+ "keywords": [
16
+ "sleeper",
17
+ "mini",
18
+ "apps",
19
+ "fantasy",
20
+ "sports"
21
+ ],
22
+ "author": "Luke Herbold <luke@sleeper.app>",
23
+ "license": "MIT",
24
+ "bugs": {
25
+ "url": "https://github.com/blitzstudios/sleeper-mini-core/issues"
26
+ },
27
+ "homepage": "https://github.com/blitzstudios/sleeper-mini-core#readme",
28
+ "publishConfig": {
29
+ "registry": "https://registry.npmjs.org/",
30
+ "access": "public"
31
+ },
32
+ "peerDependencies": {
33
+ "@callstack/repack": "blitzstudios/repack.git#callstack-repack-v2.5.3-gitpkg",
34
+ "@react-native-community/netinfo": "^9.3.7",
35
+ "axios": "0.15.3",
36
+ "lodash": "4.17.21",
37
+ "react": "17.0.2",
38
+ "react-native": "0.66.5",
39
+ "react-native-linear-gradient": "2.5.6",
40
+ "react-native-svg": "13.7.0",
41
+ "react-native-udp": "^4.1.6"
42
+ },
43
+ "devDependencies": {
44
+ "@babel/core": "^7.12.9",
45
+ "@babel/preset-typescript": "^7.16.7",
46
+ "@babel/runtime": "^7.12.5",
47
+ "@react-native-community/eslint-config": "^2.0.0",
48
+ "@types/lodash": "^4.14.182",
49
+ "@types/react-native": "0.66.5",
50
+ "@typescript-eslint/eslint-plugin": "^5.31.0",
51
+ "@typescript-eslint/parser": "^5.31.0",
52
+ "babel-jest": "^26.6.3",
53
+ "babel-loader": "^8.2.5",
54
+ "eslint": "7.14.0",
55
+ "jest": "^26.6.3",
56
+ "metro-react-native-babel-preset": "^0.66.2",
57
+ "react-test-renderer": "17.0.2",
58
+ "terser-webpack-plugin": "^5.3.3",
59
+ "typescript": "^4.7.2",
60
+ "webpack": "^5.73.0"
61
+ },
62
+ "resolutions": {
63
+ "react-devtools-core": "~4.25.0",
64
+ "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3"
65
+ },
66
+ "jest": {
67
+ "preset": "react-native"
68
+ }
69
+ }
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import {
3
+ ColorValue,
4
+ GestureResponderEvent,
5
+ TextProps,
6
+ View,
7
+ ViewStyle,
8
+ } from 'react-native';
9
+ import {Federated} from '@callstack/repack/client';
10
+ import {Context} from '../types';
11
+
12
+ const _SleeperModule = React.lazy(() =>
13
+ Federated.importModule('sleeper', 'index').catch(() => ({
14
+ default: props => {
15
+ console.log(
16
+ `[Sleeper] Failed to load <${props?.component}>. Check connection to the app.`,
17
+ );
18
+ return <View />;
19
+ },
20
+ })),
21
+ );
22
+
23
+ type ButtonProps = {
24
+ height?: number;
25
+ gradient?: (string | number)[];
26
+ start?: {x: number; y: number};
27
+ end?: {x: number; y: number};
28
+ disable?: boolean;
29
+ onPress?: (event: GestureResponderEvent) => void;
30
+ text?: string;
31
+ };
32
+ const Button = (props: ButtonProps) => {
33
+ return (
34
+ <React.Suspense fallback={<View />}>
35
+ <_SleeperModule component="Button" {...props} />
36
+ </React.Suspense>
37
+ );
38
+ };
39
+
40
+ const Text = (props: TextProps) => {
41
+ return (
42
+ <React.Suspense fallback={<View />}>
43
+ <_SleeperModule component="Text" {...props} />
44
+ </React.Suspense>
45
+ );
46
+ };
47
+
48
+ type JerseyProps = {
49
+ style: ViewStyle;
50
+ sport: 'nfl' | 'nba' | 'cbb' | 'cfb' | 'mlb';
51
+ number: string;
52
+ fill: ColorValue;
53
+ };
54
+ const Jersey = (props: JerseyProps) => {
55
+ return (
56
+ <React.Suspense fallback={<View />}>
57
+ <_SleeperModule component="Jersey" {...props} />
58
+ </React.Suspense>
59
+ );
60
+ };
61
+
62
+ export type {ButtonProps, Context, TextProps, JerseyProps};
63
+ export {Button, Text, Jersey};
@@ -0,0 +1,104 @@
1
+ import React, {useEffect} from 'react';
2
+ import {Platform} from 'react-native';
3
+ import {ScriptManager, Federated} from '@callstack/repack/client';
4
+ import NetInfo from '@react-native-community/netinfo';
5
+ import dgram from 'react-native-udp';
6
+ import {
7
+ localSocketPort,
8
+ remoteSocketPort,
9
+ remoteBundlePort as _remoteBundlePort,
10
+ release,
11
+ remoteIP,
12
+ } from '../../app.json';
13
+ import axios from 'axios';
14
+
15
+ const remoteBundleHost = release ? remoteIP : 'localhost';
16
+ const remoteBundlePort = release ? _remoteBundlePort : 8081;
17
+
18
+ ScriptManager.shared.addResolver(async (scriptId, caller) => {
19
+ const extension =
20
+ scriptId === 'sleeper' ? '.container.bundle' : '.chunk.bundle';
21
+ const resolveURL = Federated.createURLResolver({
22
+ containers: {
23
+ sleeper: `http://${remoteBundleHost}:${remoteBundlePort}/[name]${extension}`,
24
+ },
25
+ });
26
+
27
+ // Try to resolve URL based on scriptId and caller
28
+ const url = resolveURL(scriptId, caller);
29
+ const query = release ? undefined : {platform: Platform.OS};
30
+
31
+ const response = await axios
32
+ .get(url + '?' + new URLSearchParams(query), {method: 'HEAD'})
33
+ .catch(() => ({
34
+ status: 404,
35
+ }));
36
+
37
+ console.log('[Sleeper] load script:', scriptId, caller);
38
+ if (response?.status === 200) {
39
+ return {url, query};
40
+ }
41
+ });
42
+
43
+ const DevServer = props => {
44
+ const onSocket = msg => {
45
+ const json = JSON.parse(msg.toString());
46
+ if (json?._connected) {
47
+ return;
48
+ }
49
+
50
+ props.onContextChanged(json);
51
+ };
52
+
53
+ const onError = err => {
54
+ console.error('[Sleeper] Socket error: ' + err);
55
+ };
56
+
57
+ const bindSocket = async socket => {
58
+ const netInfo = await NetInfo.fetch();
59
+ const netInfoDetails = netInfo?.details;
60
+
61
+ if (!netInfoDetails || !('ipAddress' in netInfoDetails)) {
62
+ console.error('[Sleeper] Failed to determine local IP address.');
63
+ return;
64
+ }
65
+
66
+ socket.bind({port: localSocketPort, address: netInfoDetails.ipAddress});
67
+ };
68
+
69
+ const pingServer = socket => {
70
+ // Continue to ping the sleeper app server until it responds.
71
+ return new Promise(() => {
72
+ NetInfo.fetch().then(netInfo => {
73
+ const netInfoDetails = netInfo?.details;
74
+ if (!netInfoDetails || !('ipAddress' in netInfoDetails)) {
75
+ console.error('[Sleeper] Failed to determine local IP address.');
76
+ return;
77
+ }
78
+
79
+ const json = JSON.stringify({_ip: netInfoDetails.ipAddress});
80
+
81
+ (async function ping() {
82
+ socket.send(json, undefined, undefined, remoteSocketPort, remoteIP);
83
+ setTimeout(ping, 5000);
84
+ })();
85
+ });
86
+ });
87
+ };
88
+
89
+ useEffect(() => {
90
+ const socket = dgram.createSocket({type: 'udp4'});
91
+ bindSocket(socket);
92
+ pingServer(socket);
93
+
94
+ socket.on('message', onSocket);
95
+ socket.on('error', onError);
96
+ return () => {
97
+ socket.removeAllListeners();
98
+ };
99
+ }, []);
100
+
101
+ return <></>;
102
+ };
103
+
104
+ export default DevServer;
@@ -0,0 +1,4 @@
1
+ // preload shared packages that require initialization during startup
2
+ import 'lodash';
3
+ import 'react-native-svg';
4
+ import 'react-native-linear-gradient';
@@ -0,0 +1,116 @@
1
+ export type Maybe<T> = T | null;
2
+ export type Scalars = {
3
+ ID: string;
4
+ String: string;
5
+ Boolean: boolean;
6
+ Int: number;
7
+ Float: number;
8
+ Json: {[key: string]: any};
9
+ List: string[];
10
+ Map: {[key: string]: any};
11
+ MapWithSnowflakeKey: {[key: string]: any};
12
+ Set: string[];
13
+ Snowflake: string;
14
+ SnowflakeList: string[];
15
+ SnowflakeSet: string[];
16
+ };
17
+
18
+ export type User = {
19
+ __typename?: 'User';
20
+ async_bundles?: Maybe<Scalars['List']>;
21
+ avatar?: Maybe<Scalars['String']>;
22
+ cookies?: Maybe<Scalars['Int']>;
23
+ created?: Maybe<Scalars['Int']>;
24
+ currencies?: Maybe<Scalars['Map']>;
25
+ data_updated?: Maybe<Scalars['Map']>;
26
+ deleted?: Maybe<Scalars['Int']>;
27
+ display_name?: Maybe<Scalars['String']>;
28
+ email?: Maybe<Scalars['String']>;
29
+ is_bot?: Maybe<Scalars['Boolean']>;
30
+ metadata?: Maybe<Scalars['Json']>;
31
+ notifications?: Maybe<Scalars['Map']>;
32
+ pending?: Maybe<Scalars['Boolean']>;
33
+ phone?: Maybe<Scalars['String']>;
34
+ real_name?: Maybe<Scalars['String']>;
35
+ solicitable?: Maybe<Scalars['Boolean']>;
36
+ summoner_name?: Maybe<Scalars['String']>;
37
+ summoner_region?: Maybe<Scalars['String']>;
38
+ token?: Maybe<Scalars['String']>;
39
+ user_id?: Maybe<Scalars['Snowflake']>;
40
+ username?: Maybe<Scalars['String']>;
41
+ verification?: Maybe<Scalars['String']>;
42
+ };
43
+
44
+ export type League = {
45
+ __typename?: 'League';
46
+ avatar?: Maybe<Scalars['String']>;
47
+ company_id?: Maybe<Scalars['Snowflake']>;
48
+ display_order?: Maybe<Scalars['Int']>;
49
+ draft_id?: Maybe<Scalars['Snowflake']>;
50
+ group_id?: Maybe<Scalars['Snowflake']>;
51
+ last_author_avatar?: Maybe<Scalars['String']>;
52
+ last_author_display_name?: Maybe<Scalars['String']>;
53
+ last_author_id?: Maybe<Scalars['Snowflake']>;
54
+ last_author_is_bot?: Maybe<Scalars['Boolean']>;
55
+ last_message_attachment?: Maybe<Scalars['Json']>;
56
+ last_message_id?: Maybe<Scalars['Snowflake']>;
57
+ last_message_text?: Maybe<Scalars['String']>;
58
+ last_message_text_map?: Maybe<Scalars['Json']>;
59
+ last_message_time?: Maybe<Scalars['Int']>;
60
+ last_pinned_message_id?: Maybe<Scalars['Snowflake']>;
61
+ last_read_id?: Maybe<Scalars['Snowflake']>;
62
+ last_transaction_id?: Maybe<Scalars['Snowflake']>;
63
+ league_id?: Maybe<Scalars['Snowflake']>;
64
+ matchup_legs?: Maybe<Scalars['List']>;
65
+ metadata?: Maybe<Scalars['Map']>;
66
+ name?: Maybe<Scalars['String']>;
67
+ previous_league_id?: Maybe<Scalars['Snowflake']>;
68
+ roster_positions?: Maybe<Scalars['List']>;
69
+ scoring_settings?: Maybe<Scalars['Map']>;
70
+ season?: Maybe<Scalars['String']>;
71
+ season_type?: Maybe<Scalars['String']>;
72
+ settings?: Maybe<Scalars['Map']>;
73
+ sport?: Maybe<Scalars['String']>;
74
+ status?: Maybe<Scalars['String']>;
75
+ total_rosters?: Maybe<Scalars['Int']>;
76
+ };
77
+
78
+ export type NavigationType =
79
+ | 'DM'
80
+ | 'INBOX'
81
+ | 'MY_FEED'
82
+ | 'FRIENDS'
83
+ | 'LEAGUE'
84
+ | 'ASYNC_SPORT'
85
+ | 'CREATE_LEAGUE'
86
+ | 'LEAGUE_SYNC'
87
+ | 'DRAFTBOARDS'
88
+ | 'SOLO_OVER_UNDER'
89
+ | 'CHANNEL'
90
+ | 'MANAGE_CHANNELS';
91
+
92
+ export type NavigationTypeId =
93
+ | 1 // DRAFTBOARDS
94
+ | 2 // CREATE_DM
95
+ | 3 // DM_SCREEN
96
+ | 4 // CREATE_LEAGUE
97
+ | 5 // MY_FEED
98
+ | 6 // MENTIONS
99
+ | 7; // FRIENDS
100
+
101
+ export type Navigation = {
102
+ selectedNavType: NavigationType;
103
+ selectedNavTypeId: NavigationTypeId;
104
+ selectedNavData: {};
105
+ };
106
+
107
+ export type Actions = {
108
+ navigate: (navType?: NavigationType, navTypeId?: NavigationTypeId) => void;
109
+ };
110
+
111
+ export type Context = {
112
+ user?: User;
113
+ league?: League;
114
+ navigation?: Navigation;
115
+ actions?: Actions;
116
+ };