@symbiote-native/apple-authentication 0.0.0-stage → 0.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.
- package/LICENSE +21 -0
- package/README.md +264 -2
- package/build/angular/apple-authentication-button/index.d.ts +12 -0
- package/build/angular/apple-authentication-button/index.js +98 -0
- package/build/angular/index.d.ts +2 -0
- package/build/angular/index.js +3 -0
- package/build/core/apple-authentication-button.d.ts +20 -0
- package/build/core/apple-authentication-button.js +28 -0
- package/build/core/apple-authentication.d.ts +34 -0
- package/build/core/apple-authentication.js +85 -0
- package/build/core/constants.d.ts +2 -0
- package/build/core/constants.js +3 -0
- package/build/core/index.d.ts +5 -0
- package/build/core/index.js +4 -0
- package/build/core/native-module.d.ts +10 -0
- package/build/core/native-module.js +8 -0
- package/build/core/types.d.ts +104 -0
- package/build/core/types.js +56 -0
- package/build/react/apple-authentication-button.d.ts +6 -0
- package/build/react/apple-authentication-button.js +7 -0
- package/build/react/index.d.ts +3 -0
- package/build/react/index.js +3 -0
- package/build/solid/apple-authentication-button.d.ts +3 -0
- package/build/solid/apple-authentication-button.js +4 -0
- package/build/solid/index.d.ts +3 -0
- package/build/solid/index.js +3 -0
- package/build/svelte/apple-authentication-button.svelte +17 -0
- package/build/svelte/apple-authentication-button.svelte.d.ts +4 -0
- package/build/svelte/index.d.ts +2 -0
- package/build/svelte/index.js +3 -0
- package/build/vue/apple-authentication-button.d.ts +3 -0
- package/build/vue/apple-authentication-button.js +15 -0
- package/build/vue/index.d.ts +3 -0
- package/build/vue/index.js +3 -0
- package/build-ngc/angular/apple-authentication-button/index.d.ts +15 -0
- package/build-ngc/angular/apple-authentication-button/index.js +48 -0
- package/build-ngc/angular/apple-authentication-button/index.js.map +1 -0
- package/build-ngc/angular/index.d.ts +2 -0
- package/build-ngc/angular/index.js +4 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/core/apple-authentication-button.d.ts +20 -0
- package/build-ngc/core/apple-authentication-button.js +29 -0
- package/build-ngc/core/apple-authentication-button.js.map +1 -0
- package/build-ngc/core/apple-authentication.d.ts +34 -0
- package/build-ngc/core/apple-authentication.js +86 -0
- package/build-ngc/core/apple-authentication.js.map +1 -0
- package/build-ngc/core/constants.d.ts +2 -0
- package/build-ngc/core/constants.js +4 -0
- package/build-ngc/core/constants.js.map +1 -0
- package/build-ngc/core/index.d.ts +5 -0
- package/build-ngc/core/index.js +5 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/native-module.d.ts +10 -0
- package/build-ngc/core/native-module.js +9 -0
- package/build-ngc/core/native-module.js.map +1 -0
- package/build-ngc/core/types.d.ts +104 -0
- package/build-ngc/core/types.js +57 -0
- package/build-ngc/core/types.js.map +1 -0
- package/native-link.json +11 -0
- package/package.json +145 -3
- package/src/angular/apple-authentication-button/index.ts +36 -0
- package/src/angular/index.ts +28 -0
- package/src/core/apple-authentication-button.ts +69 -0
- package/src/core/apple-authentication.ts +130 -0
- package/src/core/constants.ts +5 -0
- package/src/core/index.ts +31 -0
- package/src/core/native-module.ts +38 -0
- package/src/core/types.ts +121 -0
- package/src/react/apple-authentication-button.ts +12 -0
- package/src/react/index.ts +28 -0
- package/src/solid/apple-authentication-button.ts +9 -0
- package/src/solid/index.ts +28 -0
- package/src/svelte/apple-authentication-button.svelte +17 -0
- package/src/svelte/index.ts +4 -0
- package/src/svelte/svelte-ambient.d.ts +3 -0
- package/src/svelte/svelte-compile.test-helper.ts +6 -0
- package/src/vue/apple-authentication-button.ts +18 -0
- package/src/vue/index.ts +28 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/** Scopes for `signInAsync`, the user may deny any of them, so handle `null` fields */
|
|
2
|
+
export declare enum AppleAuthenticationScope {
|
|
3
|
+
FULL_NAME = 0,
|
|
4
|
+
EMAIL = 1
|
|
5
|
+
}
|
|
6
|
+
export declare enum AppleAuthenticationOperation {
|
|
7
|
+
/** An operation that depends on the particular kind of credential provider */
|
|
8
|
+
IMPLICIT = 0,
|
|
9
|
+
LOGIN = 1,
|
|
10
|
+
REFRESH = 2,
|
|
11
|
+
LOGOUT = 3
|
|
12
|
+
}
|
|
13
|
+
/** The state of a credential checked with `getCredentialStateAsync` */
|
|
14
|
+
export declare enum AppleAuthenticationCredentialState {
|
|
15
|
+
REVOKED = 0,
|
|
16
|
+
AUTHORIZED = 1,
|
|
17
|
+
NOT_FOUND = 2,
|
|
18
|
+
TRANSFERRED = 3
|
|
19
|
+
}
|
|
20
|
+
/** The system's guess of how likely the user is a real person */
|
|
21
|
+
export declare enum AppleAuthenticationUserDetectionStatus {
|
|
22
|
+
/** The system does not support this determination and there is no data */
|
|
23
|
+
UNSUPPORTED = 0,
|
|
24
|
+
/** The system has not determined whether the user might be a real person */
|
|
25
|
+
UNKNOWN = 1,
|
|
26
|
+
/** The user appears to be a real person */
|
|
27
|
+
LIKELY_REAL = 2
|
|
28
|
+
}
|
|
29
|
+
/** Which pre-defined text the button shows */
|
|
30
|
+
export declare enum AppleAuthenticationButtonType {
|
|
31
|
+
/** "Sign in with Apple" */
|
|
32
|
+
SIGN_IN = 0,
|
|
33
|
+
/** "Continue with Apple" */
|
|
34
|
+
CONTINUE = 1,
|
|
35
|
+
/**
|
|
36
|
+
* "Sign up with Apple"
|
|
37
|
+
* @platform ios 13.2+
|
|
38
|
+
*/
|
|
39
|
+
SIGN_UP = 2
|
|
40
|
+
}
|
|
41
|
+
/** Which pre-defined color scheme the button uses */
|
|
42
|
+
export declare enum AppleAuthenticationButtonStyle {
|
|
43
|
+
/** White button with black text */
|
|
44
|
+
WHITE = 0,
|
|
45
|
+
/** White button with a black outline and black text */
|
|
46
|
+
WHITE_OUTLINE = 1,
|
|
47
|
+
/** Black button with white text */
|
|
48
|
+
BLACK = 2
|
|
49
|
+
}
|
|
50
|
+
/** The style a name is formatted in, see `formatFullName` */
|
|
51
|
+
export type IAppleAuthenticationFullNameFormatStyle = 'default' | 'short' | 'medium' | 'long' | 'abbreviated';
|
|
52
|
+
/** The tokenized portions of the user's name, only what the user allowed is not `null` */
|
|
53
|
+
export type IAppleAuthenticationFullName = {
|
|
54
|
+
namePrefix: string | null;
|
|
55
|
+
givenName: string | null;
|
|
56
|
+
middleName: string | null;
|
|
57
|
+
familyName: string | null;
|
|
58
|
+
nameSuffix: string | null;
|
|
59
|
+
nickname: string | null;
|
|
60
|
+
};
|
|
61
|
+
type IRequestOptions = {
|
|
62
|
+
/**
|
|
63
|
+
* Scopes the app asks for, they come only the first time a user signs in
|
|
64
|
+
* @default []
|
|
65
|
+
*/
|
|
66
|
+
requestedScopes?: AppleAuthenticationScope[];
|
|
67
|
+
/** An arbitrary string returned unmodified in the credential, it guards against replay attacks */
|
|
68
|
+
state?: string;
|
|
69
|
+
};
|
|
70
|
+
/** Options for `signInAsync`, none is required */
|
|
71
|
+
export type IAppleAuthenticationSignInOptions = IRequestOptions & {
|
|
72
|
+
/** An arbitrary string that prevents replay attacks */
|
|
73
|
+
nonce?: string;
|
|
74
|
+
};
|
|
75
|
+
/** Options for `refreshAsync`, `user` is the id of the user whose credentials refresh */
|
|
76
|
+
export type IAppleAuthenticationRefreshOptions = IRequestOptions & {
|
|
77
|
+
user: string;
|
|
78
|
+
};
|
|
79
|
+
/** Options for `signOutAsync`, `user` is the id of the user to sign out */
|
|
80
|
+
export type IAppleAuthenticationSignOutOptions = {
|
|
81
|
+
user: string;
|
|
82
|
+
state?: string;
|
|
83
|
+
};
|
|
84
|
+
/** What a successful `signInAsync`, `refreshAsync` or `signOutAsync` resolves with */
|
|
85
|
+
export type IAppleAuthenticationCredential = {
|
|
86
|
+
/** Stable across apps of one development team, use it to check the user later */
|
|
87
|
+
user: string;
|
|
88
|
+
/** The `state` the request carried, `null` when none was given */
|
|
89
|
+
state: string | null;
|
|
90
|
+
/** `null` without the `FULL_NAME` scope, on a denial, or after the first sign-in */
|
|
91
|
+
fullName: IAppleAuthenticationFullName | null;
|
|
92
|
+
/** Obscured with an Apple domain when the user withholds the address */
|
|
93
|
+
email: string | null;
|
|
94
|
+
realUserStatus: AppleAuthenticationUserDetectionStatus;
|
|
95
|
+
/** A JSON Web Token with information about the user */
|
|
96
|
+
identityToken: string | null;
|
|
97
|
+
/** A short-lived session token for the app's server, it changes every session */
|
|
98
|
+
authorizationCode: string | null;
|
|
99
|
+
};
|
|
100
|
+
/** What the native module accepts: the options of a call plus the operation it performs */
|
|
101
|
+
export type IAppleAuthenticationRequest = (IAppleAuthenticationSignInOptions | IAppleAuthenticationRefreshOptions | IAppleAuthenticationSignOutOptions) & {
|
|
102
|
+
requestedOperation: AppleAuthenticationOperation;
|
|
103
|
+
};
|
|
104
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Типы и enum-ы `expo-apple-authentication`, порт `AppleAuthentication.types.ts`
|
|
2
|
+
/** Scopes for `signInAsync`, the user may deny any of them, so handle `null` fields */
|
|
3
|
+
export var AppleAuthenticationScope;
|
|
4
|
+
(function (AppleAuthenticationScope) {
|
|
5
|
+
AppleAuthenticationScope[AppleAuthenticationScope["FULL_NAME"] = 0] = "FULL_NAME";
|
|
6
|
+
AppleAuthenticationScope[AppleAuthenticationScope["EMAIL"] = 1] = "EMAIL";
|
|
7
|
+
})(AppleAuthenticationScope || (AppleAuthenticationScope = {}));
|
|
8
|
+
export var AppleAuthenticationOperation;
|
|
9
|
+
(function (AppleAuthenticationOperation) {
|
|
10
|
+
/** An operation that depends on the particular kind of credential provider */
|
|
11
|
+
AppleAuthenticationOperation[AppleAuthenticationOperation["IMPLICIT"] = 0] = "IMPLICIT";
|
|
12
|
+
AppleAuthenticationOperation[AppleAuthenticationOperation["LOGIN"] = 1] = "LOGIN";
|
|
13
|
+
AppleAuthenticationOperation[AppleAuthenticationOperation["REFRESH"] = 2] = "REFRESH";
|
|
14
|
+
AppleAuthenticationOperation[AppleAuthenticationOperation["LOGOUT"] = 3] = "LOGOUT";
|
|
15
|
+
})(AppleAuthenticationOperation || (AppleAuthenticationOperation = {}));
|
|
16
|
+
/** The state of a credential checked with `getCredentialStateAsync` */
|
|
17
|
+
export var AppleAuthenticationCredentialState;
|
|
18
|
+
(function (AppleAuthenticationCredentialState) {
|
|
19
|
+
AppleAuthenticationCredentialState[AppleAuthenticationCredentialState["REVOKED"] = 0] = "REVOKED";
|
|
20
|
+
AppleAuthenticationCredentialState[AppleAuthenticationCredentialState["AUTHORIZED"] = 1] = "AUTHORIZED";
|
|
21
|
+
AppleAuthenticationCredentialState[AppleAuthenticationCredentialState["NOT_FOUND"] = 2] = "NOT_FOUND";
|
|
22
|
+
AppleAuthenticationCredentialState[AppleAuthenticationCredentialState["TRANSFERRED"] = 3] = "TRANSFERRED";
|
|
23
|
+
})(AppleAuthenticationCredentialState || (AppleAuthenticationCredentialState = {}));
|
|
24
|
+
/** The system's guess of how likely the user is a real person */
|
|
25
|
+
export var AppleAuthenticationUserDetectionStatus;
|
|
26
|
+
(function (AppleAuthenticationUserDetectionStatus) {
|
|
27
|
+
/** The system does not support this determination and there is no data */
|
|
28
|
+
AppleAuthenticationUserDetectionStatus[AppleAuthenticationUserDetectionStatus["UNSUPPORTED"] = 0] = "UNSUPPORTED";
|
|
29
|
+
/** The system has not determined whether the user might be a real person */
|
|
30
|
+
AppleAuthenticationUserDetectionStatus[AppleAuthenticationUserDetectionStatus["UNKNOWN"] = 1] = "UNKNOWN";
|
|
31
|
+
/** The user appears to be a real person */
|
|
32
|
+
AppleAuthenticationUserDetectionStatus[AppleAuthenticationUserDetectionStatus["LIKELY_REAL"] = 2] = "LIKELY_REAL";
|
|
33
|
+
})(AppleAuthenticationUserDetectionStatus || (AppleAuthenticationUserDetectionStatus = {}));
|
|
34
|
+
/** Which pre-defined text the button shows */
|
|
35
|
+
export var AppleAuthenticationButtonType;
|
|
36
|
+
(function (AppleAuthenticationButtonType) {
|
|
37
|
+
/** "Sign in with Apple" */
|
|
38
|
+
AppleAuthenticationButtonType[AppleAuthenticationButtonType["SIGN_IN"] = 0] = "SIGN_IN";
|
|
39
|
+
/** "Continue with Apple" */
|
|
40
|
+
AppleAuthenticationButtonType[AppleAuthenticationButtonType["CONTINUE"] = 1] = "CONTINUE";
|
|
41
|
+
/**
|
|
42
|
+
* "Sign up with Apple"
|
|
43
|
+
* @platform ios 13.2+
|
|
44
|
+
*/
|
|
45
|
+
AppleAuthenticationButtonType[AppleAuthenticationButtonType["SIGN_UP"] = 2] = "SIGN_UP";
|
|
46
|
+
})(AppleAuthenticationButtonType || (AppleAuthenticationButtonType = {}));
|
|
47
|
+
/** Which pre-defined color scheme the button uses */
|
|
48
|
+
export var AppleAuthenticationButtonStyle;
|
|
49
|
+
(function (AppleAuthenticationButtonStyle) {
|
|
50
|
+
/** White button with black text */
|
|
51
|
+
AppleAuthenticationButtonStyle[AppleAuthenticationButtonStyle["WHITE"] = 0] = "WHITE";
|
|
52
|
+
/** White button with a black outline and black text */
|
|
53
|
+
AppleAuthenticationButtonStyle[AppleAuthenticationButtonStyle["WHITE_OUTLINE"] = 1] = "WHITE_OUTLINE";
|
|
54
|
+
/** Black button with white text */
|
|
55
|
+
AppleAuthenticationButtonStyle[AppleAuthenticationButtonStyle["BLACK"] = 2] = "BLACK";
|
|
56
|
+
})(AppleAuthenticationButtonStyle || (AppleAuthenticationButtonStyle = {}));
|
|
57
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,iFAAiF;AAEjF,uFAAuF;AACvF,MAAM,CAAN,IAAY,wBAGX;AAHD,WAAY,wBAAwB;IAClC,iFAAa,CAAA;IACb,yEAAS,CAAA;AACX,CAAC,EAHW,wBAAwB,KAAxB,wBAAwB,QAGnC;AAED,MAAM,CAAN,IAAY,4BAMX;AAND,WAAY,4BAA4B;IACtC,8EAA8E;IAC9E,uFAAY,CAAA;IACZ,iFAAS,CAAA;IACT,qFAAW,CAAA;IACX,mFAAU,CAAA;AACZ,CAAC,EANW,4BAA4B,KAA5B,4BAA4B,QAMvC;AAED,uEAAuE;AACvE,MAAM,CAAN,IAAY,kCAKX;AALD,WAAY,kCAAkC;IAC5C,iGAAO,CAAA;IACP,uGAAU,CAAA;IACV,qGAAS,CAAA;IACT,yGAAW,CAAA;AACb,CAAC,EALW,kCAAkC,KAAlC,kCAAkC,QAK7C;AAED,iEAAiE;AACjE,MAAM,CAAN,IAAY,sCAOX;AAPD,WAAY,sCAAsC;IAChD,0EAA0E;IAC1E,iHAAW,CAAA;IACX,4EAA4E;IAC5E,yGAAO,CAAA;IACP,2CAA2C;IAC3C,iHAAW,CAAA;AACb,CAAC,EAPW,sCAAsC,KAAtC,sCAAsC,QAOjD;AAED,8CAA8C;AAC9C,MAAM,CAAN,IAAY,6BAUX;AAVD,WAAY,6BAA6B;IACvC,2BAA2B;IAC3B,uFAAO,CAAA;IACP,4BAA4B;IAC5B,yFAAQ,CAAA;IACR;;;OAGG;IACH,uFAAO,CAAA;AACT,CAAC,EAVW,6BAA6B,KAA7B,6BAA6B,QAUxC;AAED,qDAAqD;AACrD,MAAM,CAAN,IAAY,8BAOX;AAPD,WAAY,8BAA8B;IACxC,mCAAmC;IACnC,qFAAK,CAAA;IACL,uDAAuD;IACvD,qGAAa,CAAA;IACb,mCAAmC;IACnC,qFAAK,CAAA;AACP,CAAC,EAPW,8BAA8B,KAA9B,8BAA8B,QAOzC"}
|
package/native-link.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,148 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/apple-authentication",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "expo-apple-authentication wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Sign in with Apple: the credential flow and the native button, iOS only.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/OneEyed1366/symbiote-native.git",
|
|
9
|
+
"directory": "packages/apple-authentication"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/OneEyed1366/symbiote-native/tree/master/packages/apple-authentication#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/OneEyed1366/symbiote-native/issues"
|
|
14
|
+
},
|
|
15
|
+
"author": "Andrey Prokopenko <psevdoproger@gmail.com>",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"react-native",
|
|
18
|
+
"symbiote-native",
|
|
19
|
+
"expo-apple-authentication",
|
|
20
|
+
"react",
|
|
21
|
+
"vue",
|
|
22
|
+
"svelte",
|
|
23
|
+
"solid",
|
|
24
|
+
"angular",
|
|
25
|
+
"sign-in-with-apple",
|
|
26
|
+
"apple-authentication"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "./build/core/index.js",
|
|
30
|
+
"module": "./build/core/index.js",
|
|
31
|
+
"types": "./build/core/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./build/core/index.d.ts",
|
|
35
|
+
"default": "./build/core/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./vue": {
|
|
38
|
+
"types": "./build/vue/index.d.ts",
|
|
39
|
+
"default": "./build/vue/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./react": {
|
|
42
|
+
"types": "./build/react/index.d.ts",
|
|
43
|
+
"default": "./build/react/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./svelte": "./src/svelte/index.ts",
|
|
46
|
+
"./solid": {
|
|
47
|
+
"types": "./build/solid/index.d.ts",
|
|
48
|
+
"default": "./build/solid/index.js"
|
|
49
|
+
},
|
|
50
|
+
"./angular": {
|
|
51
|
+
"types": "./build-ngc/angular/index.d.ts",
|
|
52
|
+
"react-native": "./build-ngc/angular/index.js",
|
|
53
|
+
"default": "./src/angular/index.ts"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"files": [
|
|
57
|
+
"src",
|
|
58
|
+
"build",
|
|
59
|
+
"build-ngc",
|
|
60
|
+
"native-link.json",
|
|
61
|
+
"!src/**/*.test.*",
|
|
62
|
+
"!src/**/*.spec.*",
|
|
63
|
+
"!src/**/*.detox.*"
|
|
64
|
+
],
|
|
65
|
+
"publishConfig": {
|
|
66
|
+
"access": "public"
|
|
67
|
+
},
|
|
68
|
+
"dependencies": {
|
|
69
|
+
"expo-apple-authentication": "57.0.2",
|
|
70
|
+
"expo-modules-core": "57.0.20",
|
|
71
|
+
"@symbiote-native/components": "3.2.0"
|
|
72
|
+
},
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"@angular/core": ">=20",
|
|
75
|
+
"@vue/runtime-core": "^3.5.13",
|
|
76
|
+
"react": ">=19.0.0",
|
|
77
|
+
"react-native": ">=0.86",
|
|
78
|
+
"solid-js": ">=1.9.0",
|
|
79
|
+
"svelte": ">=5.56.0",
|
|
80
|
+
"vue": ">=3.5.0",
|
|
81
|
+
"@symbiote-native/angular": "^3.3.0",
|
|
82
|
+
"@symbiote-native/engine": "^1.6.0",
|
|
83
|
+
"@symbiote-native/react": "^3.3.0",
|
|
84
|
+
"@symbiote-native/solid": "^3.2.0",
|
|
85
|
+
"@symbiote-native/svelte": "^3.2.0",
|
|
86
|
+
"@symbiote-native/vue": "^3.3.0"
|
|
87
|
+
},
|
|
88
|
+
"peerDependenciesMeta": {
|
|
89
|
+
"@symbiote-native/angular": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"@symbiote-native/react": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"@symbiote-native/solid": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"@symbiote-native/svelte": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"@symbiote-native/vue": {
|
|
102
|
+
"optional": true
|
|
103
|
+
},
|
|
104
|
+
"@angular/core": {
|
|
105
|
+
"optional": true
|
|
106
|
+
},
|
|
107
|
+
"@vue/runtime-core": {
|
|
108
|
+
"optional": true
|
|
109
|
+
},
|
|
110
|
+
"react": {
|
|
111
|
+
"optional": true
|
|
112
|
+
},
|
|
113
|
+
"solid-js": {
|
|
114
|
+
"optional": true
|
|
115
|
+
},
|
|
116
|
+
"svelte": {
|
|
117
|
+
"optional": true
|
|
118
|
+
},
|
|
119
|
+
"vue": {
|
|
120
|
+
"optional": true
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"devDependencies": {
|
|
124
|
+
"@angular/compiler": "~22.0.8",
|
|
125
|
+
"@angular/compiler-cli": "~22.0.8",
|
|
126
|
+
"@angular/core": "~22.0.8",
|
|
127
|
+
"@types/node": "^26.0.0",
|
|
128
|
+
"@types/react": "^19.2.0",
|
|
129
|
+
"@vue/runtime-core": "^3.5.13",
|
|
130
|
+
"react": "19.2.3",
|
|
131
|
+
"solid-js": "^1.9.14",
|
|
132
|
+
"svelte": "^5.56.0",
|
|
133
|
+
"typescript": "~6.0.0",
|
|
134
|
+
"@symbiote-native/angular": "3.3.0",
|
|
135
|
+
"@symbiote-native/engine": "1.6.0",
|
|
136
|
+
"@symbiote-native/react": "3.3.0",
|
|
137
|
+
"@symbiote-native/solid": "3.2.0",
|
|
138
|
+
"@symbiote-native/svelte": "3.2.0",
|
|
139
|
+
"@symbiote-native/test-utils": "0.4.7",
|
|
140
|
+
"@symbiote-native/vue": "3.3.0"
|
|
141
|
+
},
|
|
142
|
+
"scripts": {
|
|
143
|
+
"typecheck": "tsc --build",
|
|
144
|
+
"clean": "rm -rf build-ngc",
|
|
145
|
+
"ng:build": "pnpm run clean && ngc -p tsconfig.angular.json",
|
|
146
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
147
|
+
}
|
|
6
148
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
|
2
|
+
import { DescriptorOutlet, NativeViewBase } from '@symbiote-native/angular';
|
|
3
|
+
import type { IDescriptor } from '@symbiote-native/components';
|
|
4
|
+
import { renderAppleAuthenticationButton } from '../../core/apple-authentication-button';
|
|
5
|
+
import type { IAppleAuthenticationButtonProps } from '../../core/apple-authentication-button';
|
|
6
|
+
|
|
7
|
+
/** Angular twin of `expo-apple-authentication`'s `AppleAuthenticationButton`, iOS only */
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'AppleAuthenticationButton',
|
|
10
|
+
standalone: true,
|
|
11
|
+
imports: [DescriptorOutlet],
|
|
12
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13
|
+
template: `@if (descriptor; as node) {
|
|
14
|
+
<symbiote-descriptor-outlet [node]="node" />
|
|
15
|
+
}`,
|
|
16
|
+
})
|
|
17
|
+
export class AppleAuthenticationButton extends NativeViewBase {
|
|
18
|
+
@Input({ required: true })
|
|
19
|
+
onPress!: IAppleAuthenticationButtonProps['onPress'];
|
|
20
|
+
@Input({ required: true })
|
|
21
|
+
buttonType!: IAppleAuthenticationButtonProps['buttonType'];
|
|
22
|
+
@Input({ required: true })
|
|
23
|
+
buttonStyle!: IAppleAuthenticationButtonProps['buttonStyle'];
|
|
24
|
+
@Input() cornerRadius?: IAppleAuthenticationButtonProps['cornerRadius'];
|
|
25
|
+
|
|
26
|
+
protected override readonly propNames = [
|
|
27
|
+
'onPress',
|
|
28
|
+
'buttonType',
|
|
29
|
+
'buttonStyle',
|
|
30
|
+
'cornerRadius',
|
|
31
|
+
] as const satisfies readonly (keyof AppleAuthenticationButton)[];
|
|
32
|
+
|
|
33
|
+
protected override renderView(props: object): IDescriptor | null {
|
|
34
|
+
return renderAppleAuthenticationButton(props);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @symbiote-native/apple-authentication/angular: кнопка и поток входа на общем ядре
|
|
2
|
+
|
|
3
|
+
export { AppleAuthenticationButton } from './apple-authentication-button';
|
|
4
|
+
export {
|
|
5
|
+
APPLE_AUTHENTICATION_MODULE_NAME,
|
|
6
|
+
AppleAuthenticationButtonStyle,
|
|
7
|
+
AppleAuthenticationButtonType,
|
|
8
|
+
AppleAuthenticationCredentialState,
|
|
9
|
+
AppleAuthenticationOperation,
|
|
10
|
+
AppleAuthenticationScope,
|
|
11
|
+
AppleAuthenticationUserDetectionStatus,
|
|
12
|
+
addRevokeListener,
|
|
13
|
+
appleAuthenticationButtonViewName,
|
|
14
|
+
formatFullName,
|
|
15
|
+
getCredentialStateAsync,
|
|
16
|
+
isAvailableAsync,
|
|
17
|
+
refreshAsync,
|
|
18
|
+
signInAsync,
|
|
19
|
+
signOutAsync,
|
|
20
|
+
type EventSubscription,
|
|
21
|
+
type IAppleAuthenticationButtonProps,
|
|
22
|
+
type IAppleAuthenticationCredential,
|
|
23
|
+
type IAppleAuthenticationFullName,
|
|
24
|
+
type IAppleAuthenticationFullNameFormatStyle,
|
|
25
|
+
type IAppleAuthenticationRefreshOptions,
|
|
26
|
+
type IAppleAuthenticationSignInOptions,
|
|
27
|
+
type IAppleAuthenticationSignOutOptions,
|
|
28
|
+
} from '../core';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Ядро `AppleAuthenticationButton`: нативный view системной кнопки Sign in with Apple, только iOS
|
|
2
|
+
import { Platform, requireNativeViewManager } from 'expo-modules-core';
|
|
3
|
+
import { el } from '@symbiote-native/components';
|
|
4
|
+
import type {
|
|
5
|
+
IAccessibilityProps,
|
|
6
|
+
IAriaProps,
|
|
7
|
+
IDescriptor,
|
|
8
|
+
IResponderProps,
|
|
9
|
+
} from '@symbiote-native/components';
|
|
10
|
+
import { defineExpoNativeView, isDevBuild } from '@symbiote-native/engine';
|
|
11
|
+
import type {
|
|
12
|
+
IStyleProp,
|
|
13
|
+
ISymbioteEvent,
|
|
14
|
+
IViewStyle,
|
|
15
|
+
} from '@symbiote-native/engine';
|
|
16
|
+
import { APPLE_AUTHENTICATION_MODULE_NAME } from './constants';
|
|
17
|
+
import type {
|
|
18
|
+
AppleAuthenticationButtonStyle,
|
|
19
|
+
AppleAuthenticationButtonType,
|
|
20
|
+
} from './types';
|
|
21
|
+
|
|
22
|
+
const PRESS_EVENT_PROP = 'onButtonPress';
|
|
23
|
+
|
|
24
|
+
// Фон и скругление задают `buttonStyle` и `cornerRadius`, а не `style`, это правило App Store
|
|
25
|
+
export type IAppleAuthenticationButtonProps = IAccessibilityProps &
|
|
26
|
+
IAriaProps &
|
|
27
|
+
IResponderProps & {
|
|
28
|
+
/** Call `signInAsync` in here */
|
|
29
|
+
onPress: () => void;
|
|
30
|
+
buttonType: AppleAuthenticationButtonType;
|
|
31
|
+
buttonStyle: AppleAuthenticationButtonStyle;
|
|
32
|
+
/** Works like `style.borderRadius` of a View */
|
|
33
|
+
cornerRadius?: number;
|
|
34
|
+
/** Needs a width and a height, or the button does not appear */
|
|
35
|
+
style?: IStyleProp<Omit<IViewStyle, 'backgroundColor' | 'borderRadius'>>;
|
|
36
|
+
testID?: string;
|
|
37
|
+
nativeID?: string;
|
|
38
|
+
onLayout?: (event: ISymbioteEvent) => void;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Регистрация идёт при рендере: побочный эффект барреля теряется в release
|
|
42
|
+
const buttonView = defineExpoNativeView(
|
|
43
|
+
requireNativeViewManager,
|
|
44
|
+
APPLE_AUTHENTICATION_MODULE_NAME,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export const appleAuthenticationButtonViewName = buttonView.name;
|
|
48
|
+
|
|
49
|
+
export function ensureAppleAuthenticationButtonRegistered(): boolean {
|
|
50
|
+
if (!Platform.select({ ios: true, default: false })) return false;
|
|
51
|
+
return buttonView.ensureRegistered();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** `null` means the caller renders nothing, the system button exists only on iOS */
|
|
55
|
+
export function renderAppleAuthenticationButton(
|
|
56
|
+
props: object,
|
|
57
|
+
): IDescriptor | null {
|
|
58
|
+
if (!ensureAppleAuthenticationButtonRegistered()) {
|
|
59
|
+
if (isDevBuild()) {
|
|
60
|
+
console.warn("'AppleAuthenticationButton' is not available.");
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const { onPress, ...viewProps } = Object.fromEntries(Object.entries(props));
|
|
65
|
+
return el(appleAuthenticationButtonViewName(), {
|
|
66
|
+
...viewProps,
|
|
67
|
+
[PRESS_EVENT_PROP]: onPress,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { CodedError, UnavailabilityError } from 'expo-modules-core';
|
|
2
|
+
import type { EventSubscription } from 'expo-modules-core';
|
|
3
|
+
import { REVOKE_EVENT_NAME } from './constants';
|
|
4
|
+
import { expoAppleAuthentication } from './native-module';
|
|
5
|
+
import { AppleAuthenticationOperation } from './types';
|
|
6
|
+
import type {
|
|
7
|
+
AppleAuthenticationCredentialState,
|
|
8
|
+
IAppleAuthenticationCredential,
|
|
9
|
+
IAppleAuthenticationFullName,
|
|
10
|
+
IAppleAuthenticationFullNameFormatStyle,
|
|
11
|
+
IAppleAuthenticationRefreshOptions,
|
|
12
|
+
IAppleAuthenticationRequest,
|
|
13
|
+
IAppleAuthenticationSignInOptions,
|
|
14
|
+
IAppleAuthenticationSignOutOptions,
|
|
15
|
+
} from './types';
|
|
16
|
+
|
|
17
|
+
const NATIVE_MODULE_NAME = 'expo-apple-authentication';
|
|
18
|
+
|
|
19
|
+
// Сообщение ссылается на имя вызванной функции, поэтому оно приходит параметром
|
|
20
|
+
async function requestCredential(
|
|
21
|
+
functionName: string,
|
|
22
|
+
request: IAppleAuthenticationRequest,
|
|
23
|
+
): Promise<IAppleAuthenticationCredential> {
|
|
24
|
+
if (!expoAppleAuthentication.requestAsync) {
|
|
25
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, functionName);
|
|
26
|
+
}
|
|
27
|
+
return expoAppleAuthentication.requestAsync(request);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Вход и обновление возвращают токены, без них учётные данные бесполезны
|
|
31
|
+
async function requestCompleteCredential(
|
|
32
|
+
functionName: string,
|
|
33
|
+
request: IAppleAuthenticationRequest,
|
|
34
|
+
): Promise<IAppleAuthenticationCredential> {
|
|
35
|
+
const credential = await requestCredential(functionName, request);
|
|
36
|
+
if (
|
|
37
|
+
!credential.authorizationCode ||
|
|
38
|
+
!credential.identityToken ||
|
|
39
|
+
!credential.user
|
|
40
|
+
) {
|
|
41
|
+
throw new CodedError(
|
|
42
|
+
'ERR_REQUEST_FAILED',
|
|
43
|
+
`The credential returned by \`${functionName}\` is missing one or more required fields.`,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return credential;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Whether the device's operating system supports Apple authentication
|
|
51
|
+
* @returns `true` when the system supports it, `false` otherwise
|
|
52
|
+
*/
|
|
53
|
+
export async function isAvailableAsync(): Promise<boolean> {
|
|
54
|
+
if (!expoAppleAuthentication.isAvailableAsync) return false;
|
|
55
|
+
return expoAppleAuthentication.isAvailableAsync();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Starts the Apple authentication flow, which presents a modal over the app
|
|
60
|
+
* The credential carries the name and email only the first time a user signs in, store it
|
|
61
|
+
* @returns The credential, rejects with `ERR_REQUEST_CANCELED` when the user cancels
|
|
62
|
+
*/
|
|
63
|
+
export async function signInAsync(
|
|
64
|
+
options?: IAppleAuthenticationSignInOptions,
|
|
65
|
+
): Promise<IAppleAuthenticationCredential> {
|
|
66
|
+
return requestCompleteCredential('signInAsync', {
|
|
67
|
+
...options,
|
|
68
|
+
requestedOperation: AppleAuthenticationOperation.LOGIN,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Refreshes the credentials of the logged-in user, the sign in modal shows first
|
|
74
|
+
* @returns The credential, rejects with `ERR_REQUEST_CANCELED` when the user cancels
|
|
75
|
+
*/
|
|
76
|
+
export async function refreshAsync(
|
|
77
|
+
options: IAppleAuthenticationRefreshOptions,
|
|
78
|
+
): Promise<IAppleAuthenticationCredential> {
|
|
79
|
+
return requestCompleteCredential('refreshAsync', {
|
|
80
|
+
...options,
|
|
81
|
+
requestedOperation: AppleAuthenticationOperation.REFRESH,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Ends the authenticated session, the sign in modal shows first
|
|
87
|
+
* Clearing the stored user data after `signInAsync` is the recommended way to sign out
|
|
88
|
+
* @returns The credential, rejects with `ERR_REQUEST_CANCELED` when the user cancels
|
|
89
|
+
*/
|
|
90
|
+
export async function signOutAsync(
|
|
91
|
+
options: IAppleAuthenticationSignOutOptions,
|
|
92
|
+
): Promise<IAppleAuthenticationCredential> {
|
|
93
|
+
return requestCredential('signOutAsync', {
|
|
94
|
+
...options,
|
|
95
|
+
requestedOperation: AppleAuthenticationOperation.LOGOUT,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Whether the credential of a user is still valid or was revoked
|
|
101
|
+
* On the iOS simulator it always throws, test on a real device
|
|
102
|
+
* @param user The `user` field of an `IAppleAuthenticationCredential`
|
|
103
|
+
*/
|
|
104
|
+
export async function getCredentialStateAsync(
|
|
105
|
+
user: string,
|
|
106
|
+
): Promise<AppleAuthenticationCredentialState> {
|
|
107
|
+
if (!expoAppleAuthentication.getCredentialStateAsync) {
|
|
108
|
+
throw new UnavailabilityError(
|
|
109
|
+
NATIVE_MODULE_NAME,
|
|
110
|
+
'getCredentialStateAsync',
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return expoAppleAuthentication.getCredentialStateAsync(user);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** A locale-aware string of a person's name built from its tokenized portions */
|
|
117
|
+
export function formatFullName(
|
|
118
|
+
fullName: IAppleAuthenticationFullName,
|
|
119
|
+
formatStyle?: IAppleAuthenticationFullNameFormatStyle,
|
|
120
|
+
): string {
|
|
121
|
+
if (!expoAppleAuthentication.formatFullName) {
|
|
122
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'formatFullName');
|
|
123
|
+
}
|
|
124
|
+
return expoAppleAuthentication.formatFullName(fullName, formatStyle);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Calls the listener when the user revokes the credential of the app in the system settings */
|
|
128
|
+
export function addRevokeListener(listener: () => void): EventSubscription {
|
|
129
|
+
return expoAppleAuthentication.addListener(REVOKE_EVENT_NAME, listener);
|
|
130
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export {
|
|
2
|
+
addRevokeListener,
|
|
3
|
+
formatFullName,
|
|
4
|
+
getCredentialStateAsync,
|
|
5
|
+
isAvailableAsync,
|
|
6
|
+
refreshAsync,
|
|
7
|
+
signInAsync,
|
|
8
|
+
signOutAsync,
|
|
9
|
+
} from './apple-authentication';
|
|
10
|
+
export {
|
|
11
|
+
appleAuthenticationButtonViewName,
|
|
12
|
+
ensureAppleAuthenticationButtonRegistered,
|
|
13
|
+
renderAppleAuthenticationButton,
|
|
14
|
+
type IAppleAuthenticationButtonProps,
|
|
15
|
+
} from './apple-authentication-button';
|
|
16
|
+
export { APPLE_AUTHENTICATION_MODULE_NAME } from './constants';
|
|
17
|
+
export {
|
|
18
|
+
AppleAuthenticationButtonStyle,
|
|
19
|
+
AppleAuthenticationButtonType,
|
|
20
|
+
AppleAuthenticationCredentialState,
|
|
21
|
+
AppleAuthenticationOperation,
|
|
22
|
+
AppleAuthenticationScope,
|
|
23
|
+
AppleAuthenticationUserDetectionStatus,
|
|
24
|
+
type IAppleAuthenticationCredential,
|
|
25
|
+
type IAppleAuthenticationFullName,
|
|
26
|
+
type IAppleAuthenticationFullNameFormatStyle,
|
|
27
|
+
type IAppleAuthenticationRefreshOptions,
|
|
28
|
+
type IAppleAuthenticationSignInOptions,
|
|
29
|
+
type IAppleAuthenticationSignOutOptions,
|
|
30
|
+
} from './types';
|
|
31
|
+
export type { EventSubscription } from 'expo-modules-core';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { requireOptionalNativeModule } from 'expo-modules-core';
|
|
2
|
+
import type { EventSubscription } from 'expo-modules-core';
|
|
3
|
+
import { APPLE_AUTHENTICATION_MODULE_NAME } from './constants';
|
|
4
|
+
import type {
|
|
5
|
+
IAppleAuthenticationCredential,
|
|
6
|
+
IAppleAuthenticationFullName,
|
|
7
|
+
IAppleAuthenticationFullNameFormatStyle,
|
|
8
|
+
IAppleAuthenticationRequest,
|
|
9
|
+
AppleAuthenticationCredentialState,
|
|
10
|
+
} from './types';
|
|
11
|
+
|
|
12
|
+
// Каждый метод проверяется в месте вызова и бросает `UnavailabilityError`, как у upstream:
|
|
13
|
+
// без нативного кода (не iOS) остаётся только заглушка ниже
|
|
14
|
+
export type INativeAppleAuthenticationModule = {
|
|
15
|
+
addListener(eventName: string, listener: () => void): EventSubscription;
|
|
16
|
+
isAvailableAsync?(): Promise<boolean>;
|
|
17
|
+
requestAsync?(
|
|
18
|
+
options: IAppleAuthenticationRequest,
|
|
19
|
+
): Promise<IAppleAuthenticationCredential>;
|
|
20
|
+
getCredentialStateAsync?(
|
|
21
|
+
user: string,
|
|
22
|
+
): Promise<AppleAuthenticationCredentialState>;
|
|
23
|
+
formatFullName?(
|
|
24
|
+
fullName: IAppleAuthenticationFullName,
|
|
25
|
+
formatStyle?: IAppleAuthenticationFullNameFormatStyle,
|
|
26
|
+
): string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Вместо `null` на неподдерживаемой платформе, чтобы `isAvailableAsync` отвечал `false`
|
|
30
|
+
const unsupportedModule: INativeAppleAuthenticationModule = {
|
|
31
|
+
isAvailableAsync: () => Promise.resolve(false),
|
|
32
|
+
addListener: () => ({ remove: () => undefined }),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const expoAppleAuthentication: INativeAppleAuthenticationModule =
|
|
36
|
+
requireOptionalNativeModule<INativeAppleAuthenticationModule>(
|
|
37
|
+
APPLE_AUTHENTICATION_MODULE_NAME,
|
|
38
|
+
) ?? unsupportedModule;
|