@sudobility/auth_lib 0.0.101 → 0.0.102
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/build/firebase-service-config.cjs +184 -0
- package/package.json +12 -6
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase's web config, read at BUILD time from the app's native services
|
|
3
|
+
* files and written into the bundle — so a React Native app on Firebase's JS
|
|
4
|
+
* SDK is configured from `GoogleService-Info.plist` / `google-services.json`,
|
|
5
|
+
* the same files native Firebase (analytics, crashlytics, messaging, remote
|
|
6
|
+
* config, performance) already reads, rather than from a second copy of the
|
|
7
|
+
* same values in `.env`.
|
|
8
|
+
*
|
|
9
|
+
* Used from an app's `babel.config.js`:
|
|
10
|
+
*
|
|
11
|
+
* const { firebaseServiceConfigPlugin } =
|
|
12
|
+
* require('@sudobility/auth_lib/build/firebase-service-config');
|
|
13
|
+
* ...
|
|
14
|
+
* plugins: [
|
|
15
|
+
* firebaseServiceConfigPlugin(api, {
|
|
16
|
+
* ios: 'ios/MyApp/GoogleService-Info.plist',
|
|
17
|
+
* android: 'android/app/google-services.json',
|
|
18
|
+
* androidPackage: 'com.example.myapp',
|
|
19
|
+
* }),
|
|
20
|
+
* ...
|
|
21
|
+
* ]
|
|
22
|
+
*
|
|
23
|
+
* The plugin replaces these `process.env` references with literals for the
|
|
24
|
+
* platform Metro is bundling (Babel's `caller.platform`):
|
|
25
|
+
*
|
|
26
|
+
* FIREBASE_API_KEY, FIREBASE_AUTH_DOMAIN, FIREBASE_PROJECT_ID,
|
|
27
|
+
* FIREBASE_STORAGE_BUCKET, FIREBASE_MESSAGING_SENDER_ID, FIREBASE_APP_ID,
|
|
28
|
+
* GOOGLE_OAUTH_CLIENT_ID (the iOS-type client), GOOGLE_WEB_CLIENT_ID
|
|
29
|
+
*
|
|
30
|
+
* Each platform gets its OWN app's values — the iOS app's API key and app id
|
|
31
|
+
* on iOS, the Android app's on Android — which the Auth API accepts from the
|
|
32
|
+
* JS SDK (checked for every app in the family). macOS and Windows read the
|
|
33
|
+
* iOS file — always, even where a macOS plist exists: a desktop signs in with
|
|
34
|
+
* the iOS-type Google client, and one file for the Apple-and-desktop family
|
|
35
|
+
* means one set of values to keep right. With no platform
|
|
36
|
+
* (jest) every name becomes `undefined`, so the code's defaults apply.
|
|
37
|
+
*
|
|
38
|
+
* The library reads only the files the app names; it reads no environment.
|
|
39
|
+
*/
|
|
40
|
+
'use strict';
|
|
41
|
+
|
|
42
|
+
const fs = require('fs');
|
|
43
|
+
const path = require('path');
|
|
44
|
+
|
|
45
|
+
const NAMES = [
|
|
46
|
+
'FIREBASE_API_KEY',
|
|
47
|
+
'FIREBASE_AUTH_DOMAIN',
|
|
48
|
+
'FIREBASE_PROJECT_ID',
|
|
49
|
+
'FIREBASE_STORAGE_BUCKET',
|
|
50
|
+
'FIREBASE_MESSAGING_SENDER_ID',
|
|
51
|
+
'FIREBASE_APP_ID',
|
|
52
|
+
'GOOGLE_OAUTH_CLIENT_ID',
|
|
53
|
+
'GOOGLE_WEB_CLIENT_ID',
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
/** `<key>K</key><string>V</string>` pairs — all a GoogleService-Info.plist holds. */
|
|
57
|
+
function parsePlist(text) {
|
|
58
|
+
const out = {};
|
|
59
|
+
const re = /<key>([^<]+)<\/key>\s*<string>([^<]*)<\/string>/g;
|
|
60
|
+
let m;
|
|
61
|
+
while ((m = re.exec(text)) !== null) out[m[1]] = m[2];
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The values a GoogleService-Info.plist gives. */
|
|
66
|
+
function fromPlist(file) {
|
|
67
|
+
const p = parsePlist(fs.readFileSync(file, 'utf8'));
|
|
68
|
+
const projectId = p.PROJECT_ID || '';
|
|
69
|
+
return {
|
|
70
|
+
FIREBASE_API_KEY: p.API_KEY || '',
|
|
71
|
+
FIREBASE_AUTH_DOMAIN: projectId ? `${projectId}.firebaseapp.com` : '',
|
|
72
|
+
FIREBASE_PROJECT_ID: projectId,
|
|
73
|
+
FIREBASE_STORAGE_BUCKET: p.STORAGE_BUCKET || '',
|
|
74
|
+
FIREBASE_MESSAGING_SENDER_ID: p.GCM_SENDER_ID || '',
|
|
75
|
+
FIREBASE_APP_ID: p.GOOGLE_APP_ID || '',
|
|
76
|
+
GOOGLE_OAUTH_CLIENT_ID: p.CLIENT_ID || '',
|
|
77
|
+
GOOGLE_WEB_CLIENT_ID: '',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The values a google-services.json gives, for the client registered to
|
|
83
|
+
* `androidPackage` (a file may list several apps of one project).
|
|
84
|
+
*/
|
|
85
|
+
function fromServicesJson(file, androidPackage) {
|
|
86
|
+
const j = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
87
|
+
const clients = j.client || [];
|
|
88
|
+
const client =
|
|
89
|
+
clients.find(
|
|
90
|
+
c =>
|
|
91
|
+
c.client_info &&
|
|
92
|
+
c.client_info.android_client_info &&
|
|
93
|
+
c.client_info.android_client_info.package_name === androidPackage
|
|
94
|
+
) || (androidPackage ? null : clients[0]);
|
|
95
|
+
if (!client) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`google-services.json (${file}) has no client for package "${androidPackage}"`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
const projectId = (j.project_info && j.project_info.project_id) || '';
|
|
101
|
+
const oauth = client.oauth_client || [];
|
|
102
|
+
const other =
|
|
103
|
+
(client.services &&
|
|
104
|
+
client.services.appinvite_service &&
|
|
105
|
+
client.services.appinvite_service.other_platform_oauth_client) ||
|
|
106
|
+
[];
|
|
107
|
+
const web = [...oauth, ...other].find(c => c.client_type === 3);
|
|
108
|
+
const ios = [...oauth, ...other].find(c => c.client_type === 2);
|
|
109
|
+
return {
|
|
110
|
+
FIREBASE_API_KEY: (client.api_key && client.api_key[0] && client.api_key[0].current_key) || '',
|
|
111
|
+
FIREBASE_AUTH_DOMAIN: projectId ? `${projectId}.firebaseapp.com` : '',
|
|
112
|
+
FIREBASE_PROJECT_ID: projectId,
|
|
113
|
+
FIREBASE_STORAGE_BUCKET: (j.project_info && j.project_info.storage_bucket) || '',
|
|
114
|
+
FIREBASE_MESSAGING_SENDER_ID: (j.project_info && j.project_info.project_number) || '',
|
|
115
|
+
FIREBASE_APP_ID: (client.client_info && client.client_info.mobilesdk_app_id) || '',
|
|
116
|
+
GOOGLE_OAUTH_CLIENT_ID: (ios && ios.client_id) || '',
|
|
117
|
+
GOOGLE_WEB_CLIENT_ID: (web && web.client_id) || '',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The values for one platform, or null when the platform is unknown.
|
|
123
|
+
* `files` paths are relative to `root` (the app; default: cwd).
|
|
124
|
+
*/
|
|
125
|
+
function firebaseServiceConfig(platform, files, root) {
|
|
126
|
+
const base = root || process.cwd();
|
|
127
|
+
const at = p => path.resolve(base, p);
|
|
128
|
+
switch (platform) {
|
|
129
|
+
case 'ios':
|
|
130
|
+
return fromPlist(at(files.ios));
|
|
131
|
+
case 'android':
|
|
132
|
+
return fromServicesJson(at(files.android), files.androidPackage);
|
|
133
|
+
case 'macos':
|
|
134
|
+
case 'windows':
|
|
135
|
+
return fromPlist(at(files.ios));
|
|
136
|
+
default:
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const cache = new Map();
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* A Babel plugin entry that inlines the platform's values. Reads the files
|
|
145
|
+
* once per platform per process.
|
|
146
|
+
*/
|
|
147
|
+
function firebaseServiceConfigPlugin(api, files) {
|
|
148
|
+
const platform = api.caller(caller => (caller && caller.platform) || null);
|
|
149
|
+
const root = files.root || process.cwd();
|
|
150
|
+
const key = `${root}|${platform}`;
|
|
151
|
+
if (!cache.has(key)) cache.set(key, firebaseServiceConfig(platform, files, root));
|
|
152
|
+
const values = cache.get(key);
|
|
153
|
+
|
|
154
|
+
return function inlineFirebaseServiceConfig({ types: t }) {
|
|
155
|
+
return {
|
|
156
|
+
name: 'inline-firebase-service-config',
|
|
157
|
+
visitor: {
|
|
158
|
+
MemberExpression(p) {
|
|
159
|
+
const node = p.node;
|
|
160
|
+
if (
|
|
161
|
+
!t.isMemberExpression(node.object) ||
|
|
162
|
+
!t.isIdentifier(node.object.object, { name: 'process' }) ||
|
|
163
|
+
!t.isIdentifier(node.object.property, { name: 'env' })
|
|
164
|
+
) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const name = node.computed
|
|
168
|
+
? t.isStringLiteral(node.property) && node.property.value
|
|
169
|
+
: t.isIdentifier(node.property) && node.property.name;
|
|
170
|
+
if (!name || !NAMES.includes(name)) return;
|
|
171
|
+
const value = values && values[name];
|
|
172
|
+
p.replaceWith(value ? t.stringLiteral(value) : t.identifier('undefined'));
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
module.exports = {
|
|
180
|
+
FIREBASE_SERVICE_CONFIG_NAMES: NAMES,
|
|
181
|
+
firebaseServiceConfig,
|
|
182
|
+
firebaseServiceConfigPlugin,
|
|
183
|
+
parsePlist,
|
|
184
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudobility/auth_lib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.102",
|
|
4
4
|
"description": "Firebase authentication utilities with token refresh handling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
"import": "./dist/signin/index.js",
|
|
24
24
|
"types": "./dist/signin/index.d.ts"
|
|
25
25
|
},
|
|
26
|
+
"./build/firebase-service-config": {
|
|
27
|
+
"require": "./build/firebase-service-config.cjs",
|
|
28
|
+
"default": "./build/firebase-service-config.cjs"
|
|
29
|
+
},
|
|
26
30
|
"./account": {
|
|
27
31
|
"import": "./dist/account/index.js",
|
|
28
32
|
"types": "./dist/account/index.d.ts"
|
|
@@ -38,6 +42,7 @@
|
|
|
38
42
|
},
|
|
39
43
|
"files": [
|
|
40
44
|
"dist",
|
|
45
|
+
"build/firebase-service-config.cjs",
|
|
41
46
|
"README.md"
|
|
42
47
|
],
|
|
43
48
|
"scripts": {
|
|
@@ -73,22 +78,23 @@
|
|
|
73
78
|
}
|
|
74
79
|
},
|
|
75
80
|
"devDependencies": {
|
|
76
|
-
"
|
|
81
|
+
"@babel/core": "^7",
|
|
82
|
+
"@eslint/js": "^9.0.0",
|
|
77
83
|
"@sudobility/di": "^1.5.67",
|
|
78
84
|
"@sudobility/types": "^1.9.68",
|
|
79
85
|
"@tanstack/react-query": "^5.80.7",
|
|
80
|
-
"@types/node": "^22.0.0",
|
|
81
|
-
"vitest": "^4.0.4",
|
|
82
|
-
"@eslint/js": "^9.0.0",
|
|
83
86
|
"@types/bun": "^1.2.8",
|
|
87
|
+
"@types/node": "^22.0.0",
|
|
84
88
|
"@types/react": "^19.2.5",
|
|
85
89
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
86
90
|
"@typescript-eslint/parser": "^8.0.0",
|
|
87
91
|
"eslint": "^9.0.0",
|
|
88
92
|
"eslint-config-prettier": "^10.0.0",
|
|
89
93
|
"eslint-plugin-prettier": "^5.0.0",
|
|
94
|
+
"firebase": "^12.7.0",
|
|
90
95
|
"prettier": "^3.0.0",
|
|
91
|
-
"typescript": "~5.9.3"
|
|
96
|
+
"typescript": "~5.9.3",
|
|
97
|
+
"vitest": "^4.0.4"
|
|
92
98
|
},
|
|
93
99
|
"publishConfig": {
|
|
94
100
|
"access": "public"
|