airbridge-react-native-sdk-restricted 2.8.9 → 4.1.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.
Files changed (268) hide show
  1. package/.github/workflows/build.yml +249 -159
  2. package/.github/workflows/documentation.yml +76 -0
  3. package/.github/workflows/qa.yml +187 -0
  4. package/.github/workflows/release.yml +26 -0
  5. package/airbridge-react-native-sdk-restricted.podspec +10 -7
  6. package/airbridge_sdk.json +4 -0
  7. package/android/build.gradle +22 -5
  8. package/android/{copy-config.gradle → copy-airbridge-json.gradle} +2 -2
  9. package/android/src/main/java/co/ab180/airbridge/reactnative/AirbridgeReactNative.kt +141 -0
  10. package/android/src/main/java/co/ab180/airbridge/reactnative/common/AirbridgeLifecycleIntegration.kt +7 -0
  11. package/android/src/main/java/co/ab180/airbridge/reactnative/extension/AirbridgeOptionBuilderApply.kt +79 -0
  12. package/android/src/main/java/co/ab180/airbridge/reactnative/extension/JSONConvert.kt +33 -0
  13. package/android/src/main/java/co/ab180/airbridge/reactnative/module/AttributionInteractor.kt +54 -0
  14. package/android/src/main/java/co/ab180/airbridge/reactnative/module/DeeplinkInteractor.kt +45 -0
  15. package/android/src/main/java/co/ab180/airbridge/reactnative/module/EventInteractor.kt +22 -0
  16. package/android/src/main/java/co/ab180/airbridge/reactnative/module/FetchInteractor.kt +51 -0
  17. package/android/src/main/java/co/ab180/airbridge/reactnative/module/PlacementInteractor.kt +56 -0
  18. package/android/src/main/java/co/ab180/airbridge/reactnative/module/RegisterInteractor.kt +108 -0
  19. package/android/src/main/java/co/ab180/airbridge/reactnative/module/SwitchInteractor.kt +43 -0
  20. package/android/src/main/java/co/ab180/airbridge/reactnative/module/WebInterfaceInteractor.kt +24 -0
  21. package/build/document/.nojekyll +1 -0
  22. package/build/document/assets/highlight.css +22 -0
  23. package/build/document/assets/icons.js +18 -0
  24. package/build/document/assets/icons.svg +1 -0
  25. package/build/document/assets/main.js +60 -0
  26. package/build/document/assets/navigation.js +1 -0
  27. package/build/document/assets/search.js +1 -0
  28. package/build/document/assets/style.css +1448 -0
  29. package/build/document/classes/Airbridge.html +113 -0
  30. package/build/document/classes/AirbridgeAttribute.html +49 -0
  31. package/build/document/classes/AirbridgeCategory.html +28 -0
  32. package/build/document/index.html +8 -0
  33. package/build/document/modules.html +4 -0
  34. package/build/source/Airbridge.d.ts +230 -0
  35. package/build/source/Airbridge.js +277 -0
  36. package/build/source/Airbridge.js.map +1 -0
  37. package/build/source/architecture/Interactor.d.ts +2 -0
  38. package/build/source/architecture/Interactor.js +7 -0
  39. package/build/source/architecture/Interactor.js.map +1 -0
  40. package/build/source/architecture/module.d.ts +1 -0
  41. package/build/source/architecture/module.js +2 -0
  42. package/build/source/architecture/module.js.map +1 -0
  43. package/build/source/constant/AirbridgeAttribute.d.ts +51 -0
  44. package/build/source/constant/AirbridgeAttribute.js +144 -0
  45. package/build/source/constant/AirbridgeAttribute.js.map +1 -0
  46. package/build/source/constant/AirbridgeCategory.d.ts +30 -0
  47. package/build/source/constant/AirbridgeCategory.js +81 -0
  48. package/build/source/constant/AirbridgeCategory.js.map +1 -0
  49. package/build/source/module/Attribution.d.ts +16 -0
  50. package/build/source/module/Attribution.js +39 -0
  51. package/build/source/module/Attribution.js.map +1 -0
  52. package/build/source/module/Deeplink.d.ts +17 -0
  53. package/build/source/module/Deeplink.js +40 -0
  54. package/build/source/module/Deeplink.js.map +1 -0
  55. package/build/source/module/Event.d.ts +14 -0
  56. package/build/source/module/Event.js +50 -0
  57. package/build/source/module/Event.js.map +1 -0
  58. package/build/source/module/Fetch.d.ts +19 -0
  59. package/build/source/module/Fetch.js +100 -0
  60. package/build/source/module/Fetch.js.map +1 -0
  61. package/build/source/module/Placement.d.ts +18 -0
  62. package/build/source/module/Placement.js +95 -0
  63. package/build/source/module/Placement.js.map +1 -0
  64. package/build/source/module/Register.d.ts +49 -0
  65. package/build/source/module/Register.js +138 -0
  66. package/build/source/module/Register.js.map +1 -0
  67. package/build/source/module/Switch.d.ts +24 -0
  68. package/build/source/module/Switch.js +39 -0
  69. package/build/source/module/Switch.js.map +1 -0
  70. package/build/source/module/WebInterface.d.ts +16 -0
  71. package/build/source/module/WebInterface.js +46 -0
  72. package/build/source/module/WebInterface.js.map +1 -0
  73. package/build/source/module.d.ts +3 -0
  74. package/build/source/module.js +4 -0
  75. package/build/source/module.js.map +1 -0
  76. package/build/source/utility/check.d.ts +13 -0
  77. package/build/source/utility/check.js +15 -0
  78. package/build/source/utility/check.js.map +1 -0
  79. package/build/source/utility/compute.d.ts +3 -0
  80. package/build/source/utility/compute.js +5 -0
  81. package/build/source/utility/compute.js.map +1 -0
  82. package/build/source/utility/create.d.ts +5 -0
  83. package/build/source/utility/create.js +12 -0
  84. package/build/source/utility/create.js.map +1 -0
  85. package/build/source/utility/extract.d.ts +3 -0
  86. package/build/source/utility/extract.js +4 -0
  87. package/build/source/utility/extract.js.map +1 -0
  88. package/build/source/utility/json.d.ts +11 -0
  89. package/build/source/utility/json.js +137 -0
  90. package/build/source/utility/json.js.map +1 -0
  91. package/build/source/utility/log.d.ts +4 -0
  92. package/build/source/utility/log.js +9 -0
  93. package/build/source/utility/log.js.map +1 -0
  94. package/changelog.md +5 -3
  95. package/ios/AirbridgeReactNative/AirbridgeReactNative.h +23 -0
  96. package/ios/AirbridgeReactNative/AirbridgeReactNative.m +36 -0
  97. package/ios/AirbridgeReactNative/AirbridgeReactNative.swift +95 -0
  98. package/ios/AirbridgeReactNative/Extension/AirbridgeOptionBuilderApply.swift +86 -0
  99. package/ios/AirbridgeReactNative/Extension/DataFromHex.swift +21 -0
  100. package/ios/AirbridgeReactNative/Extension/Logger.swift +62 -0
  101. package/ios/AirbridgeReactNative/Module/AirbridgeModuleExtern.m +133 -0
  102. package/ios/AirbridgeReactNative/Module/AttributionInteractor.swift +43 -0
  103. package/ios/AirbridgeReactNative/Module/DeeplinkInteractor.swift +49 -0
  104. package/ios/AirbridgeReactNative/Module/EventInteractor.swift +26 -0
  105. package/ios/AirbridgeReactNative/Module/FetchInteractor.swift +66 -0
  106. package/ios/AirbridgeReactNative/Module/PlacementInteractor.swift +72 -0
  107. package/ios/AirbridgeReactNative/Module/RegisterInteractor.swift +104 -0
  108. package/ios/AirbridgeReactNative/Module/SwitchInteractor.swift +48 -0
  109. package/ios/AirbridgeReactNative/Module/WebInterfaceInteractor.swift +30 -0
  110. package/ios/{copy-config.rb → copy-airbridge-json.rb} +1 -1
  111. package/package.json +18 -27
  112. package/qa/Gemfile +3 -4
  113. package/qa/Gemfile.lock +28 -17
  114. package/qa/airbridge_qa.json +6 -0
  115. package/qa/android/app/build.gradle +30 -26
  116. package/qa/android/app/src/main/AndroidManifest.xml +159 -7
  117. package/qa/android/app/src/main/java/co/ab180/airbridge/qa/application/ConfigurationLoader.kt +5 -5
  118. package/qa/android/app/src/main/java/co/ab180/airbridge/qa/application/MainActivity.kt +2 -2
  119. package/qa/android/app/src/main/java/co/ab180/airbridge/qa/application/module/IdentifiersInteractor.kt +8 -17
  120. package/qa/android/app/src/main/java/co/ab180/airbridge/qa/application/module/InstallReferrerInteractor.kt +13 -22
  121. package/qa/android/app/src/main/java/co/ab180/airbridge/qa/application/module/ModuleInjector.kt +1 -2
  122. package/qa/android/app/src/main/res/values/airbridge.xml +16 -0
  123. package/qa/android/build.gradle +4 -2
  124. package/qa/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  125. package/qa/android/gradle.properties +0 -2
  126. package/qa/android/gradlew +1 -1
  127. package/qa/android/settings.gradle +3 -1
  128. package/qa/ios/AirbridgeQA/AirbridgeQA.entitlements +11 -0
  129. package/qa/ios/AirbridgeQA/AppDelegate.mm +40 -30
  130. package/qa/ios/AirbridgeQA/DeviceInfoInteractor.swift +0 -1
  131. package/qa/ios/AirbridgeQA/IdentifiersInteractor.swift +4 -8
  132. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-20@2x.png +0 -0
  133. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png +0 -0
  134. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-20@3x.png +0 -0
  135. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png +0 -0
  136. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-29.png +0 -0
  137. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-29@2x.png +0 -0
  138. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png +0 -0
  139. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-29@3x.png +0 -0
  140. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png +0 -0
  141. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-40@2x.png +0 -0
  142. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png +0 -0
  143. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-40@3x.png +0 -0
  144. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png +0 -0
  145. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png +0 -0
  146. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png +0 -0
  147. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png +0 -0
  148. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon@2x.png +0 -0
  149. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png +0 -0
  150. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon@3x.png +0 -0
  151. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png +0 -0
  152. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/AppIcon~ipad.png +0 -0
  153. package/qa/ios/AirbridgeQA/Images.xcassets/AppIcon.appiconset/Contents.json +113 -32
  154. package/qa/ios/AirbridgeQA.xcodeproj/project.pbxproj +47 -29
  155. package/qa/ios/InternalLibrary/airbridge-ios-sdk-qa-library.podspec +32 -0
  156. package/qa/ios/InternalLibrary/airbridge-ios-sdk-restricted.podspec +32 -0
  157. package/qa/ios/Library/airbridge-ios-sdk-qa-library.podspec +6 -1
  158. package/qa/ios/Podfile +13 -1
  159. package/qa/ios/Podfile.lock +678 -313
  160. package/qa/ios/Script/prepare-build-parameter.rb +23 -0
  161. package/qa/metro.config.js +5 -2
  162. package/qa/package-lock.json +3360 -1435
  163. package/qa/package.json +29 -30
  164. package/qa/source/App.js +11 -5
  165. package/qa/source/common/FCMService.js +39 -15
  166. package/qa/source/navigations/Stack.js +8 -1
  167. package/qa/source/pages/AppInfo.js +40 -0
  168. package/qa/source/pages/Browse.js +16 -19
  169. package/qa/source/pages/DeviceInfo.js +10 -4
  170. package/qa/source/pages/Event.js +70 -60
  171. package/qa/source/pages/Home.js +77 -17
  172. package/qa/source/pages/Identifiers.js +10 -6
  173. package/qa/source/pages/Placement.js +3 -3
  174. package/qa/source/pages/Skad.js +76 -0
  175. package/qa/source/pages/UserInfo.js +47 -28
  176. package/readme.md +6 -6
  177. package/script/BuildDocument.sh +10 -0
  178. package/{scripts/build-qa.sh → script/BuildQA.sh} +5 -4
  179. package/script/BuildSource.sh +14 -0
  180. package/script/ChangeInternalSDK.sh +22 -0
  181. package/script/ChangeProductionSDK.sh +37 -0
  182. package/script/ChangeRestricted.sh +34 -0
  183. package/script/PrepareBuildParameter.sh +28 -0
  184. package/source/Airbridge.ts +340 -0
  185. package/source/architecture/Interactor.ts +10 -0
  186. package/source/architecture/module.ts +1 -0
  187. package/source/constant/AirbridgeAttribute.ts +188 -0
  188. package/source/constant/AirbridgeCategory.ts +104 -0
  189. package/source/module/Attribution.ts +4 -8
  190. package/source/module/Deeplink.ts +59 -0
  191. package/source/module/Event.ts +71 -0
  192. package/source/module/Fetch.ts +137 -0
  193. package/source/module/Placement.ts +134 -0
  194. package/source/module/Register.ts +203 -0
  195. package/source/module/Switch.ts +61 -0
  196. package/source/module/WebInterface.ts +55 -0
  197. package/source/module.ts +3 -0
  198. package/source/tsconfig.json +14 -0
  199. package/source/utility/check.ts +46 -0
  200. package/source/utility/compute.ts +9 -0
  201. package/source/utility/create.ts +12 -0
  202. package/source/utility/extract.ts +5 -0
  203. package/source/utility/json.ts +180 -0
  204. package/source/utility/log.ts +14 -0
  205. package/test/jest.json +13 -0
  206. package/test/mock.ts +112 -0
  207. package/test/module/Deeplink.test.ts +29 -0
  208. package/test/tsconfig.json +8 -0
  209. package/.eslintrc.json +0 -44
  210. package/.gitattributes +0 -1
  211. package/.github/actions/add-github-check/action.yml +0 -78
  212. package/.github/actions/add-github-comment/action.yml +0 -48
  213. package/.github/actions/add-slack-message/action.yml +0 -32
  214. package/.github/actions/edit-github-check/action.yml +0 -59
  215. package/.github/actions/edit-github-comment/action.yml +0 -41
  216. package/.github/workflows/release-restricted.yml +0 -35
  217. package/android/src/main/java/co/ab180/airbridge/reactnative/AirbridgeAttribution.java +0 -78
  218. package/android/src/main/java/co/ab180/airbridge/reactnative/AirbridgeDeeplink.java +0 -97
  219. package/android/src/main/java/co/ab180/airbridge/reactnative/AirbridgeEvent.java +0 -76
  220. package/android/src/main/java/co/ab180/airbridge/reactnative/AirbridgeLifecycle.java +0 -31
  221. package/android/src/main/java/co/ab180/airbridge/reactnative/AirbridgeLifecycleIntegration.java +0 -8
  222. package/android/src/main/java/co/ab180/airbridge/reactnative/AirbridgePlacement.java +0 -42
  223. package/android/src/main/java/co/ab180/airbridge/reactnative/AirbridgeRN.java +0 -112
  224. package/android/src/main/java/co/ab180/airbridge/reactnative/AirbridgeState.java +0 -174
  225. package/android/src/main/java/co/ab180/airbridge/reactnative/ConfigReader.java +0 -154
  226. package/android/src/main/java/co/ab180/airbridge/reactnative/Get.java +0 -84
  227. package/index.d.ts +0 -338
  228. package/index.js +0 -8
  229. package/ios/AirbridgeRN/ARNConfigReader.h +0 -19
  230. package/ios/AirbridgeRN/ARNConfigReader.m +0 -80
  231. package/ios/AirbridgeRN/ARNGet.h +0 -20
  232. package/ios/AirbridgeRN/ARNGet.m +0 -40
  233. package/ios/AirbridgeRN/ARNHex.h +0 -16
  234. package/ios/AirbridgeRN/ARNHex.m +0 -44
  235. package/ios/AirbridgeRN/AirbridgeAttribution.h +0 -19
  236. package/ios/AirbridgeRN/AirbridgeAttribution.m +0 -47
  237. package/ios/AirbridgeRN/AirbridgeDeeplink.h +0 -20
  238. package/ios/AirbridgeRN/AirbridgeDeeplink.m +0 -59
  239. package/ios/AirbridgeRN/AirbridgeEvent.h +0 -17
  240. package/ios/AirbridgeRN/AirbridgeEvent.m +0 -63
  241. package/ios/AirbridgeRN/AirbridgePlacement.h +0 -17
  242. package/ios/AirbridgeRN/AirbridgePlacement.m +0 -38
  243. package/ios/AirbridgeRN/AirbridgeRN.h +0 -71
  244. package/ios/AirbridgeRN/AirbridgeRN.m +0 -83
  245. package/ios/AirbridgeRN/AirbridgeState.h +0 -17
  246. package/ios/AirbridgeRN/AirbridgeState.m +0 -94
  247. package/ios/AirbridgeRN.xcodeproj/project.pbxproj +0 -417
  248. package/qa/android/app/src/main/java/co/ab180/airbridge/qa/application/module/UserInfoInteractor.kt +0 -74
  249. package/qa/ios/AirbridgeQA/UserInfoInteractor.m +0 -57
  250. package/qa/ios/AirbridgeQA/UserInfoInteractor.swift +0 -49
  251. package/qa/source/pages/appInfo.js +0 -22
  252. package/scripts/addiOSFramework.js +0 -48
  253. package/scripts/change_restricted.sh +0 -21
  254. package/scripts/update_native_version.sh +0 -104
  255. package/src/Airbridge.js +0 -82
  256. package/src/Deeplink.js +0 -75
  257. package/src/Event.js +0 -38
  258. package/src/Placement.js +0 -56
  259. package/src/State.js +0 -175
  260. package/src/WebInterface.js +0 -135
  261. package/src/tool/Log.js +0 -40
  262. package/src/tool/_.js +0 -56
  263. package/src/type/AirbridgeAttributes.js +0 -40
  264. package/src/type/AirbridgeCategory.js +0 -35
  265. package/src/type/AirbridgeProduct.js +0 -18
  266. package/src/typedef/EventOption.js +0 -9
  267. package/src/typedef/Product.js +0 -10
  268. package/src/typedef/User.js +0 -9
@@ -0,0 +1,55 @@
1
+ import { NativeModules } from 'react-native'
2
+
3
+ import { createInteractor } from '../architecture/Interactor'
4
+ import { check } from '../utility/check'
5
+ import { log } from '../utility/log'
6
+
7
+ export const createDependency = () => {}
8
+
9
+ type WebInterfaceInteractor = {
10
+ createWebInterfaceScript(webToken: string, postMessageScript: string): Promise<string>
11
+ handleWebInterfaceCommand(command: string): void
12
+ }
13
+
14
+ createDependency.WebInterfaceModule = () => ({
15
+ interactor: createInteractor<WebInterfaceInteractor>(NativeModules.WebInterfaceInteractor),
16
+ })
17
+
18
+ export type WebInterfaceModule = ReturnType<typeof createWebInterfaceModule>
19
+
20
+ export const createWebInterfaceModule= () => {
21
+ // create dependency
22
+ const { interactor } = createDependency.WebInterfaceModule()
23
+
24
+ // define method
25
+ const createWebInterfaceScript = async (
26
+ webToken: string,
27
+ postMessageScript: string,
28
+ ) => {
29
+ if (!check.string(webToken)) {
30
+ log.unmatchedType('webToken', 'string')
31
+ return undefined
32
+ }
33
+ if (!check.string(postMessageScript)) {
34
+ log.unmatchedType('postMessageScript', 'string')
35
+ return undefined
36
+ }
37
+
38
+ return await interactor.createWebInterfaceScript(webToken, postMessageScript)
39
+ }
40
+
41
+ const handleWebInterfaceCommand = (command: string) => {
42
+ if (!check.string(command)) {
43
+ log.unmatchedType('command', 'string')
44
+ return undefined
45
+ }
46
+
47
+ interactor.handleWebInterfaceCommand(command)
48
+ }
49
+
50
+ // create object
51
+ return {
52
+ createWebInterfaceScript,
53
+ handleWebInterfaceCommand,
54
+ }
55
+ }
@@ -0,0 +1,3 @@
1
+ export { Airbridge } from './Airbridge'
2
+ export * from './constant/AirbridgeAttribute'
3
+ export * from './constant/AirbridgeCategory'
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2015",
4
+ "lib": ["ES2015"],
5
+ "types": ["react-native"],
6
+ "outDir": "../build/source",
7
+ "declaration": true,
8
+ "sourceMap": true,
9
+ "strict": true,
10
+ "noUncheckedIndexedAccess": true,
11
+ "moduleResolution": "node",
12
+ "esModuleInterop": true
13
+ }
14
+ }
@@ -0,0 +1,46 @@
1
+ export const check = {
2
+ defined: <Value> (value: Value): value is Exclude<Value, undefined> => (
3
+ value !== undefined
4
+ ),
5
+
6
+ undefined: (value: unknown): value is undefined => (
7
+ value === undefined
8
+ ),
9
+
10
+ null: (value: unknown): value is null => (
11
+ value === null
12
+ ),
13
+
14
+ object: (value: unknown): value is Record<string, unknown> => (
15
+ value !== null
16
+ && (typeof value === 'object' || value instanceof Object)
17
+ ),
18
+
19
+ array: (value: unknown): value is Array<unknown> => (
20
+ Array.isArray(value)
21
+ ),
22
+
23
+ string: (value: unknown): value is string => (
24
+ typeof value === 'string' || value instanceof String
25
+ ),
26
+
27
+ number: (value: unknown): value is number => (
28
+ typeof value === 'number' || value instanceof Number
29
+ ),
30
+
31
+ function: (value: unknown): value is Function => (
32
+ typeof value === 'function' || value instanceof Function
33
+ ),
34
+
35
+ promise: (value: unknown): value is Promise<unknown> => (
36
+ value instanceof Promise
37
+ ),
38
+
39
+ actual: <Actual> (value: unknown, actual: Actual): value is Actual => (
40
+ value === actual
41
+ ),
42
+
43
+ boolean: (value: unknown): value is boolean => (
44
+ typeof value === 'boolean' || value instanceof Boolean
45
+ ),
46
+ }
@@ -0,0 +1,9 @@
1
+ import { check } from './check'
2
+
3
+ export const compute = {
4
+ defined: <Value, Result> (
5
+ value: Value, block: (value: Exclude<Value, undefined>) => Result
6
+ ): Result | undefined => (
7
+ check.defined(value) ? block(value) : undefined
8
+ )
9
+ }
@@ -0,0 +1,12 @@
1
+ export const create = {
2
+ object: {
3
+ fromEntries: <Value> (array: [string, Value][]): Record<string, Value> => {
4
+ const object: Record<string, Value> = {}
5
+ array.forEach(([key, value]) => {
6
+ object[key] = value
7
+ })
8
+
9
+ return object
10
+ },
11
+ },
12
+ }
@@ -0,0 +1,5 @@
1
+ export const extract = {
2
+ entries: <Value> (object: Record<string, Value> | Value[]): [string, Value][] => (
3
+ Object.keys(object).map(key => [key, (object as Record<string, Value>)[key]!])
4
+ ),
5
+ }
@@ -0,0 +1,180 @@
1
+ import { check } from './check'
2
+ import { compute } from './compute'
3
+ import { create } from './create'
4
+ import { extract } from './extract'
5
+
6
+ export type JSONObject = {
7
+ [key: string]: JSONElement
8
+ }
9
+
10
+ export type JSONArray = JSONElement[]
11
+
12
+ export type JSONElement = JSONObject | JSONArray | string | number | boolean | null
13
+
14
+ export const createJSONObject = (object: unknown): JSONObject | undefined => {
15
+ if (!check.object(object)) {
16
+ return undefined
17
+ }
18
+
19
+ return create.object.fromEntries(extract.entries(object).map(([key, value]): [string, JSONElement] | undefined => {
20
+ if (!check.string(key)) {
21
+ return undefined
22
+ }
23
+
24
+ if (
25
+ !check.string(value)
26
+ && !check.number(value)
27
+ && !check.boolean(value)
28
+ && !check.array(value)
29
+ && !check.object(value)
30
+ && !check.null(value)
31
+ ) {
32
+ return undefined
33
+ }
34
+
35
+ if (check.array(value)) {
36
+ return compute.defined(createJSONArray(value), array => {
37
+ return [key, array]
38
+ })
39
+ }
40
+ if (check.object(value)) {
41
+ return compute.defined(createJSONObject(value), object => {
42
+ return [key, object]
43
+ })
44
+ }
45
+
46
+ return [key, value]
47
+ }).filter(value => check.defined(value)))
48
+ }
49
+
50
+ export const createJSONArray = (array: unknown): JSONArray | undefined => {
51
+ if (!check.array(array)) {
52
+ return undefined
53
+ }
54
+
55
+ return array.map((value): JSONElement | undefined => {
56
+ if (
57
+ !check.string(value)
58
+ && !check.number(value)
59
+ && !check.boolean(value)
60
+ && !check.array(value)
61
+ && !check.object(value)
62
+ && !check.null(value)
63
+ ) {
64
+ return undefined
65
+ }
66
+
67
+ if (check.array(value)) {
68
+ return createJSONArray(value)
69
+ }
70
+ if (check.object(value)) {
71
+ return createJSONObject(value)
72
+ }
73
+
74
+ return value
75
+ }).filter(value => check.defined(value))
76
+ }
77
+
78
+ export const createJSONElement = (element: unknown): JSONElement | undefined => {
79
+ if (
80
+ !check.string(element)
81
+ && !check.number(element)
82
+ && !check.boolean(element)
83
+ && !check.array(element)
84
+ && !check.object(element)
85
+ && !check.null(element)
86
+ ) {
87
+ return undefined
88
+ }
89
+
90
+ if (check.array(element)) {
91
+ return createJSONArray(element)
92
+ }
93
+ if (check.object(element)) {
94
+ return createJSONObject(element)
95
+ }
96
+
97
+ return element
98
+ }
99
+
100
+ export const checkJSONObject = (object: unknown): object is JSONObject => {
101
+ if (!check.object(object)) {
102
+ return false
103
+ }
104
+
105
+ for (const [key, value] of extract.entries(object)) {
106
+ if (!check.string(key)) {
107
+ return false
108
+ }
109
+
110
+ if (
111
+ !check.string(value)
112
+ && !check.number(value)
113
+ && !check.boolean(value)
114
+ && !check.array(value)
115
+ && !check.object(value)
116
+ && !check.null(value)
117
+ ) {
118
+ return false
119
+ }
120
+
121
+ if (check.array(value) && !checkJSONArray(value)) {
122
+ return false
123
+ }
124
+ if (check.object(value) && !checkJSONObject(value)) {
125
+ return false
126
+ }
127
+ }
128
+
129
+ return true
130
+ }
131
+
132
+ export const checkJSONArray = (array: unknown): array is JSONArray => {
133
+ if (!check.array(array)) {
134
+ return false
135
+ }
136
+
137
+ for (const value of array) {
138
+ if (
139
+ !check.string(value)
140
+ && !check.number(value)
141
+ && !check.boolean(value)
142
+ && !check.array(value)
143
+ && !check.object(value)
144
+ && !check.null(value)
145
+ ) {
146
+ return false
147
+ }
148
+
149
+ if (check.array(value) && !checkJSONArray(value)) {
150
+ return false
151
+ }
152
+ if (check.object(value) && !checkJSONObject(value)) {
153
+ return false
154
+ }
155
+ }
156
+
157
+ return true
158
+ }
159
+
160
+ export const checkJSONElement = (element: unknown): element is JSONElement => {
161
+ if (
162
+ !check.string(element)
163
+ && !check.number(element)
164
+ && !check.boolean(element)
165
+ && !check.array(element)
166
+ && !check.object(element)
167
+ && !check.null(element)
168
+ ) {
169
+ return false
170
+ }
171
+
172
+ if (check.array(element) && !checkJSONArray(element)) {
173
+ return false
174
+ }
175
+ if (check.object(element) && !checkJSONObject(element)) {
176
+ return false
177
+ }
178
+
179
+ return true
180
+ }
@@ -0,0 +1,14 @@
1
+ export const log = {
2
+ unmatchedType: (
3
+ name: string,
4
+ type: 'string' | 'object' | 'object?' | 'function' | 'function?',
5
+ ) => {
6
+ console.warn(`Unmatched type: ${name} is not ${type}.`)
7
+ },
8
+
9
+ nonJSONValue: (
10
+ name: string,
11
+ ) => {
12
+ console.warn(`Non-json value: ${name} includes non-json value which is ignored by Airbridge.`)
13
+ },
14
+ }
package/test/jest.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "rootDir": "..",
3
+ "preset": "react-native",
4
+ "transform": {
5
+ "\\.(ts|js)$": ["babel-jest", {
6
+ "presets": ["module:@react-native/babel-preset"]
7
+ }]
8
+ },
9
+ "testEnvironment": "node",
10
+ "testMatch": [
11
+ "<rootDir>/test/**/*.test.ts"
12
+ ]
13
+ }
package/test/mock.ts ADDED
@@ -0,0 +1,112 @@
1
+ type ArrowFunction<Return = any, Parameters extends any[] = any[]> = (...args: Parameters) => Return
2
+
3
+ type And<Condition0 extends boolean, Condition1 extends boolean> = Condition0 extends true ? (Condition1 extends true ? true : false) : false
4
+ type Not<Condition extends boolean> = Condition extends true ? false : true
5
+
6
+ type IsAny<Type> = (any extends Type ? true : false) extends true ? true : false
7
+ type Is<Type, Expect> = Not<IsAny<Type>> extends true ? (Type extends Expect ? true : false) : false
8
+
9
+ type Opt<Type, Condition extends boolean> = Condition extends true ? Type : never
10
+ type Cast<Type, Condition> = Type extends Condition ? Type : never
11
+
12
+ type PropertyValue<Type> = {
13
+ [Key in keyof Type as Opt<Key, Not<Is<Type[Key], object | ArrowFunction>>>]: Type[Key]
14
+ }
15
+ type PropertyObject<Type> = {
16
+ [Key in keyof Type as Opt<Key, And<Is<Type[Key], object>, Not<Is<Type[Key], ArrowFunction>>>>]: Type[Key]
17
+ }
18
+ type Interface<Type> = {
19
+ [Key in keyof Type as Opt<Key, Is<Type[Key], ArrowFunction>>]: Cast<Type[Key], ArrowFunction>
20
+ }
21
+
22
+ type MockPropertyValue<Type> = PropertyValue<Type> & {
23
+ readonly [Key in 'getMock' as Opt<Key, Is<keyof PropertyValue<Type>, string>>]: {
24
+ readonly [Key in keyof PropertyValue<Type>]: jest.Mock<PropertyValue<Type>[Key], []>
25
+ }
26
+ } & {
27
+ readonly [Key in 'setMock' as Opt<Key, Is<keyof PropertyValue<Type>, string>>]: {
28
+ readonly [Key in keyof PropertyValue<Type>]: jest.Mock<void, [PropertyValue<Type>[Key]]>
29
+ }
30
+ }
31
+ type MockPropertyObject<Type> = {
32
+ readonly [Key in keyof PropertyObject<Type>]: Mock<PropertyObject<Type>[Key]>
33
+ }
34
+ type MockInterface<Type> = {
35
+ readonly [Key in keyof Interface<Type>]: jest.Mock<ReturnType<Interface<Type>[Key]>, Parameters<Interface<Type>[Key]>>
36
+ }
37
+
38
+ export type Mock<Type> = MockPropertyValue<Type> & MockPropertyObject<Type> & MockInterface<Type>
39
+
40
+ export const createMock = <Type>(): Mock<Type> => {
41
+ const values: Record<string, any> = {}
42
+ const mocks: Record<string, any> = {}
43
+
44
+ const prepareValue = (name: string) => {
45
+ if (!(name in values)) {
46
+ values[name] = {
47
+ value: undefined,
48
+ getMock: jest.fn(() => {
49
+ return values[name].value
50
+ }),
51
+ setMock: jest.fn((value) => {
52
+ values[name].value = value
53
+ }),
54
+ }
55
+ }
56
+ }
57
+
58
+ const getMock = new Proxy({}, {
59
+ get: (_, name: string) => {
60
+ prepareValue(name)
61
+ return values[name].getMock
62
+ },
63
+ set: () => {
64
+ return false
65
+ },
66
+ })
67
+
68
+ const setMock = new Proxy({}, {
69
+ get: (_, name: string) => {
70
+ prepareValue(name)
71
+ return values[name].setMock
72
+ },
73
+ set: () => {
74
+ return false
75
+ },
76
+ })
77
+
78
+ return new Proxy(jest.fn(), {
79
+ apply: (call: any, _, argument) => {
80
+ return call(...argument)
81
+ },
82
+ get: (call: any, name: string) => {
83
+ if (name in call || name === 'calls') {
84
+ return call[name]
85
+ }
86
+
87
+ if (name in values) {
88
+ return values[name].getMock()
89
+ }
90
+
91
+ if (name === 'getMock') {
92
+ return getMock
93
+ }
94
+
95
+ if (name === 'setMock') {
96
+ return setMock
97
+ }
98
+
99
+ if (!(name in mocks)) {
100
+ mocks[name] = createMock()
101
+ }
102
+
103
+ return mocks[name]
104
+ },
105
+ set: (_, name: string, value: any) => {
106
+ prepareValue(name)
107
+ values[name].setMock(value)
108
+
109
+ return true
110
+ },
111
+ }) as any as Mock<Type>
112
+ }
@@ -0,0 +1,29 @@
1
+ import { DeeplinkModule, DeeplinkModuleDependency, createDeeplinkModule, createDependency } from '../../source/module/Deeplink'
2
+ import { createMock, Mock } from '../mock'
3
+
4
+ describe('Deeplink', () => {
5
+ test('offer last deeplink received before javascript initialization', async () => {
6
+ deeplink = createDeeplinkModule()
7
+
8
+ const emit = dependency.emitter.addListener.mock.calls[0][1]
9
+ emit('1')
10
+ emit('2')
11
+ emit('3')
12
+
13
+ const first = await new Promise((resolve) => {
14
+ deeplink.setOnDeeplinkReceived((deeplink) => {
15
+ resolve(deeplink)
16
+ })
17
+ })
18
+
19
+ expect(first).toBe('3')
20
+ })
21
+
22
+ let deeplink: DeeplinkModule
23
+ let dependency: Mock<DeeplinkModuleDependency>
24
+
25
+ beforeEach(() => {
26
+ dependency = createMock()
27
+ createDependency.DeeplinkModule = () => dependency
28
+ })
29
+ })
@@ -0,0 +1,8 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "types": ["react-native", "jest"],
5
+ "moduleResolution": "node",
6
+ "esModuleInterop": true
7
+ }
8
+ }
package/.eslintrc.json DELETED
@@ -1,44 +0,0 @@
1
- {
2
- "env": {
3
- "browser": true,
4
- "es6": true
5
- },
6
- "extends": "airbnb",
7
- "parser": "babel-eslint",
8
- "globals": {
9
- "Atomics": "readonly",
10
- "SharedArrayBuffer": "readonly"
11
- },
12
- "parserOptions": {
13
- "ecmaFeatures": {
14
- "jsx": true
15
- },
16
- "ecmaVersion": 2018,
17
- "sourceType": "module"
18
- },
19
- "plugins": [
20
- "react"
21
- ],
22
- "rules": {
23
- "indent": [
24
- "off"
25
- // ,
26
- // "error",
27
- // "tab",
28
- ],
29
- "no-console": "off",
30
- "no-tabs": "off",
31
- "class-methods-use-this": "off",
32
- "import/no-extraneous-dependencies": [
33
- "error",
34
- {
35
- "devDependencies": true
36
- }
37
- ],
38
- "no-underscore-dangle": "off",
39
- "no-param-reassign": "off",
40
- "no-useless-constructor": "off",
41
- "no-empty-function": "off",
42
- "padded-blocks": "off"
43
- }
44
- }
package/.gitattributes DELETED
@@ -1 +0,0 @@
1
- *.pbxproj -text
@@ -1,78 +0,0 @@
1
- name: 'Add GitHub check'
2
- description: Add GitHub check
3
-
4
- inputs:
5
- owner:
6
- description: Owner of repository
7
- type: string
8
- default: ${context.repo.owner}
9
- required: false
10
- repository:
11
- description: Repository of release
12
- type: string
13
- default: ${context.repo.repo}
14
- required: false
15
- name:
16
- description: Name of check
17
- type: string
18
- default: ${{ github.workflow }}
19
- required: false
20
- pull-request-number:
21
- description: Pull request of check
22
- type: string
23
- default: ${context.issue.number}
24
- required: false
25
- detail-url:
26
- description: Detail URL of check
27
- type: string
28
- default: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
29
- required: false
30
- conclusion:
31
- description: Conclusion of check if status is completed (success, failure)
32
- type: string
33
- default: 'success'
34
- required: false
35
- token:
36
- description: GitHub Token
37
- type: string
38
- required: false
39
- status:
40
- description: Status of check (queued, in_progress, completed)
41
- type: string
42
- required: true
43
-
44
- outputs:
45
- check-id:
46
- description: ID of added check
47
- value: ${{ steps.add-check.outputs.result }}
48
- runs:
49
- using: 'composite'
50
- steps:
51
- - name: Add check
52
- id: add-check
53
- uses: actions/github-script@v7
54
- with:
55
- script: |
56
- const { data: { id: id } } = await github.rest.checks.create({
57
- owner: `${{ inputs.owner }}`,
58
- repo: `${{ inputs.repository }}`,
59
- name: `${{ inputs.name }}`,
60
- head_sha: await (async () => {
61
- const { data: { head: { sha: sha } } } = await github.rest.pulls.get({
62
- owner: `${{ inputs.owner }}`,
63
- repo: `${{ inputs.repository }}`,
64
- pull_number: `${{ inputs.pull-request-number }}`,
65
- })
66
- return sha
67
- })(),
68
- details_url: `${{ inputs.detail-url }}`,
69
- status: `${{ inputs.status }}`,
70
- conclusion: (() => {
71
- if (`${{ inputs.status }}` !== 'completed') {
72
- return undefined
73
- }
74
- return `${{ inputs.conclusion }}`
75
- })(),
76
- })
77
- return id
78
- github-token: ${{ inputs.token || env.GITHUB_TOKEN || github.token }}
@@ -1,48 +0,0 @@
1
- name: 'Add GitHub comment'
2
- description: Add GitHub comment
3
-
4
- inputs:
5
- issue-number:
6
- description: Issue to comment
7
- type: string
8
- default: ${context.issue.number}
9
- required: false
10
- owner:
11
- description: Owner of repository
12
- type: string
13
- default: ${context.repo.owner}
14
- required: false
15
- repository:
16
- description: Repository of release
17
- type: string
18
- default: ${context.repo.repo}
19
- required: false
20
- token:
21
- description: GitHub Token
22
- type: string
23
- required: false
24
- comment:
25
- description: Comment
26
- type: string
27
- required: true
28
-
29
- outputs:
30
- comment-id:
31
- description: ID of added comment
32
- value: ${{ steps.add-comment.outputs.result }}
33
- runs:
34
- using: 'composite'
35
- steps:
36
- - name: Add comment
37
- id: add-comment
38
- uses: actions/github-script@v7
39
- with:
40
- script: |
41
- const { data: { id: id } } = await github.rest.issues.createComment({
42
- issue_number: `${{ inputs.issue-number }}`,
43
- owner: `${{ inputs.owner }}`,
44
- repo: `${{ inputs.repository }}`,
45
- body: `${{ inputs.comment }}`,
46
- })
47
- return id
48
- github-token: ${{ inputs.token || env.GITHUB_TOKEN || github.token }}