@beclab/olaresid 0.1.2 → 0.1.4
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 +3 -0
- package/dist/business/index.d.ts +1 -1
- package/dist/business/index.d.ts.map +1 -1
- package/dist/business/index.js +5 -2
- package/dist/business/index.js.map +1 -1
- package/dist/business/tag-context.d.ts.map +1 -1
- package/dist/business/tag-context.js +23 -0
- package/dist/business/tag-context.js.map +1 -1
- package/dist/cli.js +18 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -4
- package/dist/index.js.map +1 -1
- package/dist/utils/crypto-utils.d.ts +39 -0
- package/dist/utils/crypto-utils.d.ts.map +1 -1
- package/dist/utils/crypto-utils.js +77 -27
- package/dist/utils/crypto-utils.js.map +1 -1
- package/dist/utils/olares-id.d.ts +36 -0
- package/dist/utils/olares-id.d.ts.map +1 -0
- package/dist/utils/olares-id.js +52 -0
- package/dist/utils/olares-id.js.map +1 -0
- package/examples/ed25519-jwk.ts +73 -0
- package/examples/olares-id-format.ts +197 -0
- package/package.json +2 -1
- package/src/business/index.ts +5 -2
- package/src/business/tag-context.ts +35 -1
- package/src/cli.ts +18 -1
- package/src/index.ts +16 -26
- package/src/utils/crypto-utils.ts +90 -33
- package/src/utils/olares-id.ts +49 -0
|
@@ -3,13 +3,17 @@ import { TransactionResult } from './index';
|
|
|
3
3
|
import { parseContractError } from '../utils/error-parser';
|
|
4
4
|
import { TagTypeBuilder } from '../utils/tag-type-builder';
|
|
5
5
|
import { TagAbiCodec } from '../utils/tag-abi-codec';
|
|
6
|
+
import { normalizeToDomain } from '../utils/olares-id';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Tag Operation Context
|
|
9
10
|
* Provides complete Tag management functionality
|
|
10
11
|
*/
|
|
11
12
|
export class TagContext {
|
|
12
|
-
constructor(private console: DIDConsole, private fromDomain: string) {
|
|
13
|
+
constructor(private console: DIDConsole, private fromDomain: string) {
|
|
14
|
+
// Support Olares ID format (user@domain.com)
|
|
15
|
+
this.fromDomain = normalizeToDomain(fromDomain);
|
|
16
|
+
}
|
|
13
17
|
|
|
14
18
|
// ========================================
|
|
15
19
|
// 1. Tag Type Definition Management
|
|
@@ -214,6 +218,9 @@ export class TagContext {
|
|
|
214
218
|
tagName: string,
|
|
215
219
|
value: any
|
|
216
220
|
): Promise<TransactionResult> {
|
|
221
|
+
// Support Olares ID format
|
|
222
|
+
toDomain = normalizeToDomain(toDomain);
|
|
223
|
+
|
|
217
224
|
const contract = this.console.getSignerContractDID();
|
|
218
225
|
|
|
219
226
|
// Get tag type
|
|
@@ -285,6 +292,9 @@ export class TagContext {
|
|
|
285
292
|
* @returns Tag value, or null if not found
|
|
286
293
|
*/
|
|
287
294
|
async getTag(toDomain: string, tagName: string): Promise<any | null> {
|
|
295
|
+
// Support Olares ID format
|
|
296
|
+
toDomain = normalizeToDomain(toDomain);
|
|
297
|
+
|
|
288
298
|
try {
|
|
289
299
|
const contract = this.console.getContractDID();
|
|
290
300
|
|
|
@@ -332,6 +342,9 @@ export class TagContext {
|
|
|
332
342
|
toDomain: string,
|
|
333
343
|
tagName: string
|
|
334
344
|
): Promise<TransactionResult> {
|
|
345
|
+
// Support Olares ID format
|
|
346
|
+
toDomain = normalizeToDomain(toDomain);
|
|
347
|
+
|
|
335
348
|
try {
|
|
336
349
|
const contract = this.console.getSignerContractDID();
|
|
337
350
|
const tx = await contract.removeTag(
|
|
@@ -363,6 +376,9 @@ export class TagContext {
|
|
|
363
376
|
* @returns Whether the tag exists
|
|
364
377
|
*/
|
|
365
378
|
async hasTag(toDomain: string, tagName: string): Promise<boolean> {
|
|
379
|
+
// Support Olares ID format
|
|
380
|
+
toDomain = normalizeToDomain(toDomain);
|
|
381
|
+
|
|
366
382
|
const contract = this.console.getContractDID();
|
|
367
383
|
return await contract.hasTag(this.fromDomain, toDomain, tagName);
|
|
368
384
|
}
|
|
@@ -373,6 +389,9 @@ export class TagContext {
|
|
|
373
389
|
* @returns Array of Tag names
|
|
374
390
|
*/
|
|
375
391
|
async getTagNames(toDomain: string): Promise<string[]> {
|
|
392
|
+
// Support Olares ID format
|
|
393
|
+
toDomain = normalizeToDomain(toDomain);
|
|
394
|
+
|
|
376
395
|
const contract = this.console.getContractDID();
|
|
377
396
|
const count = await contract.getTagCount(this.fromDomain, toDomain);
|
|
378
397
|
const names: string[] = [];
|
|
@@ -433,6 +452,9 @@ export class TagContext {
|
|
|
433
452
|
value: any,
|
|
434
453
|
elemPath: number[] = []
|
|
435
454
|
): Promise<TransactionResult> {
|
|
455
|
+
// Support Olares ID format
|
|
456
|
+
toDomain = normalizeToDomain(toDomain);
|
|
457
|
+
|
|
436
458
|
const contract = this.console.getSignerContractDID();
|
|
437
459
|
|
|
438
460
|
// Get tag type and encode element
|
|
@@ -490,6 +512,9 @@ export class TagContext {
|
|
|
490
512
|
tagName: string,
|
|
491
513
|
elemPath: number[] = []
|
|
492
514
|
): Promise<TransactionResult> {
|
|
515
|
+
// Support Olares ID format
|
|
516
|
+
toDomain = normalizeToDomain(toDomain);
|
|
517
|
+
|
|
493
518
|
try {
|
|
494
519
|
const contract = this.console.getSignerContractDID();
|
|
495
520
|
const tx = await contract.popTagElem(
|
|
@@ -536,6 +561,9 @@ export class TagContext {
|
|
|
536
561
|
elemPath: number[],
|
|
537
562
|
value: any
|
|
538
563
|
): Promise<TransactionResult> {
|
|
564
|
+
// Support Olares ID format
|
|
565
|
+
toDomain = normalizeToDomain(toDomain);
|
|
566
|
+
|
|
539
567
|
const contract = this.console.getSignerContractDID();
|
|
540
568
|
|
|
541
569
|
const tagTypeInfo = await this.getTagType(tagName);
|
|
@@ -592,6 +620,9 @@ export class TagContext {
|
|
|
592
620
|
tagName: string,
|
|
593
621
|
elemPath: number[] = []
|
|
594
622
|
): Promise<number> {
|
|
623
|
+
// Support Olares ID format
|
|
624
|
+
toDomain = normalizeToDomain(toDomain);
|
|
625
|
+
|
|
595
626
|
const contract = this.console.getContractDID();
|
|
596
627
|
const length = await contract.getTagElemLength(
|
|
597
628
|
this.fromDomain,
|
|
@@ -621,6 +652,9 @@ export class TagContext {
|
|
|
621
652
|
tagName: string,
|
|
622
653
|
elemPath: number[]
|
|
623
654
|
): Promise<any | null> {
|
|
655
|
+
// Support Olares ID format
|
|
656
|
+
toDomain = normalizeToDomain(toDomain);
|
|
657
|
+
|
|
624
658
|
try {
|
|
625
659
|
const contract = this.console.getContractDID();
|
|
626
660
|
|
package/src/cli.ts
CHANGED
|
@@ -15,6 +15,7 @@ import OlaresID, {
|
|
|
15
15
|
TagTypeBuilder
|
|
16
16
|
} from './index';
|
|
17
17
|
import { debug } from './debug';
|
|
18
|
+
import { normalizeToDomain } from './utils/olares-id';
|
|
18
19
|
import * as fs from 'fs';
|
|
19
20
|
import * as path from 'path';
|
|
20
21
|
|
|
@@ -155,6 +156,11 @@ DID CLI Tool v${CLI_VERSION}
|
|
|
155
156
|
USAGE:
|
|
156
157
|
did-cli <command> [subcommand] [arguments] [options]
|
|
157
158
|
|
|
159
|
+
NOTE:
|
|
160
|
+
Olares ID Format: You can use @ instead of the first dot in domain names.
|
|
161
|
+
Example: alice@example.com is equivalent to alice.example.com
|
|
162
|
+
Both formats work identically in all commands!
|
|
163
|
+
|
|
158
164
|
COMMANDS:
|
|
159
165
|
Query Commands:
|
|
160
166
|
info <domain> Get domain metadata
|
|
@@ -261,6 +267,14 @@ EXAMPLES:
|
|
|
261
267
|
export PRIVATE_KEY_OR_MNEMONIC=0xYOUR_PRIVATE_KEY
|
|
262
268
|
did-cli is-owner example.olares.com
|
|
263
269
|
|
|
270
|
+
# Olares ID format (use @ instead of first dot - like email addresses!)
|
|
271
|
+
# Both formats work identically: alice.example.com = alice@example.com
|
|
272
|
+
did-cli info alice@example.com
|
|
273
|
+
did-cli owner bob@sub.example.com
|
|
274
|
+
did-cli rsa get user@domain.com
|
|
275
|
+
did-cli ip set alice@example.com 192.168.1.100
|
|
276
|
+
did-cli tag get alice@example.com email
|
|
277
|
+
|
|
264
278
|
# RSA key management
|
|
265
279
|
did-cli rsa generate --output ./my-key.pem --key-length 4096
|
|
266
280
|
did-cli rsa get example.olares.com
|
|
@@ -2266,7 +2280,10 @@ async function tagGetTagger(
|
|
|
2266
2280
|
}
|
|
2267
2281
|
|
|
2268
2282
|
async function main(): Promise<void> {
|
|
2269
|
-
const
|
|
2283
|
+
const parsed = parseArgs();
|
|
2284
|
+
const { command, subCommand, value, options } = parsed;
|
|
2285
|
+
// Support Olares ID format (user@domain.com) by converting to standard domain format
|
|
2286
|
+
const domain = parsed.domain ? normalizeToDomain(parsed.domain) : undefined;
|
|
2270
2287
|
|
|
2271
2288
|
if (options.help || !command || command === 'help') {
|
|
2272
2289
|
showHelp();
|
package/src/index.ts
CHANGED
|
@@ -6,29 +6,9 @@ import RootResolverABI from './abi/RootResolverABI';
|
|
|
6
6
|
import RootResolver2ABI from './abi/RootResolver2ABI';
|
|
7
7
|
import { debug } from './debug';
|
|
8
8
|
import { parseContractError } from './utils/error-parser';
|
|
9
|
+
import { normalizeToDomain } from './utils/olares-id';
|
|
9
10
|
|
|
10
|
-
import {
|
|
11
|
-
DomainContext,
|
|
12
|
-
DomainMetaInfo,
|
|
13
|
-
DomainInfo,
|
|
14
|
-
TagInfo,
|
|
15
|
-
TransactionResult,
|
|
16
|
-
RSAPublicKeyData,
|
|
17
|
-
DIDKeyData,
|
|
18
|
-
UserType,
|
|
19
|
-
createRsaKeyPair,
|
|
20
|
-
pemToDer,
|
|
21
|
-
derToPem,
|
|
22
|
-
ipv4ToBytes4,
|
|
23
|
-
bytes4ToIpv4,
|
|
24
|
-
generateMnemonic,
|
|
25
|
-
getEthereumAddressFromMnemonic,
|
|
26
|
-
getEVMPrivateKeyFromMnemonic,
|
|
27
|
-
getDIDFromMnemonic,
|
|
28
|
-
generateDIDKeyData,
|
|
29
|
-
deriveDIDFromMnemonic
|
|
30
|
-
} from './business';
|
|
31
|
-
import { TagContext } from './business/tag-context';
|
|
11
|
+
import { DomainContext, TransactionResult } from './business';
|
|
32
12
|
|
|
33
13
|
// Import Tag utilities
|
|
34
14
|
import { TagTypeBuilder } from './utils/tag-type-builder';
|
|
@@ -57,7 +37,8 @@ export {
|
|
|
57
37
|
getEVMPrivateKeyFromMnemonic,
|
|
58
38
|
getDIDFromMnemonic,
|
|
59
39
|
generateDIDKeyData,
|
|
60
|
-
deriveDIDFromMnemonic
|
|
40
|
+
deriveDIDFromMnemonic,
|
|
41
|
+
getEd25519JwkFromMnemonic
|
|
61
42
|
} from './business';
|
|
62
43
|
|
|
63
44
|
type Domain = PackageDomain.Domain;
|
|
@@ -289,13 +270,16 @@ export class DIDConsole implements DIDTag.ABITypeProviderHolder {
|
|
|
289
270
|
|
|
290
271
|
fetchDomain = (name: string) =>
|
|
291
272
|
new Promise<Domain | undefined>(async (resolve, reject) => {
|
|
273
|
+
// Support Olares ID format (user@domain.com)
|
|
274
|
+
const normalizedName = normalizeToDomain(name);
|
|
275
|
+
|
|
292
276
|
debug.group('fetchDomain');
|
|
293
277
|
const hasCache = this.allDomainCache.length > 0;
|
|
294
278
|
debug.info('fetchDomain--->hasCache', hasCache);
|
|
295
279
|
|
|
296
280
|
if (hasCache) {
|
|
297
281
|
const domain = PackageDomain.findASubtree(
|
|
298
|
-
|
|
282
|
+
normalizedName,
|
|
299
283
|
this.allDomainCache
|
|
300
284
|
);
|
|
301
285
|
|
|
@@ -303,7 +287,7 @@ export class DIDConsole implements DIDTag.ABITypeProviderHolder {
|
|
|
303
287
|
resolve(domain);
|
|
304
288
|
} else {
|
|
305
289
|
const domain = await PackageDomain.syncByName(
|
|
306
|
-
|
|
290
|
+
normalizedName,
|
|
307
291
|
await this.getContractDID()
|
|
308
292
|
);
|
|
309
293
|
|
|
@@ -314,8 +298,11 @@ export class DIDConsole implements DIDTag.ABITypeProviderHolder {
|
|
|
314
298
|
|
|
315
299
|
updateDomain = (name: string) =>
|
|
316
300
|
new Promise<Domain>(async (resolve, reject) => {
|
|
301
|
+
// Support Olares ID format (user@domain.com)
|
|
302
|
+
const normalizedName = normalizeToDomain(name);
|
|
303
|
+
|
|
317
304
|
const domain = await PackageDomain.syncByName(
|
|
318
|
-
|
|
305
|
+
normalizedName,
|
|
319
306
|
await this.getContractDID()
|
|
320
307
|
);
|
|
321
308
|
|
|
@@ -585,4 +572,7 @@ export { debug } from './debug';
|
|
|
585
572
|
// Export Tag utilities outside namespace
|
|
586
573
|
export { TagTypeBuilder, TagAbiCodec };
|
|
587
574
|
|
|
575
|
+
// Export Olares ID utilities
|
|
576
|
+
export { normalizeToDomain, normalizeToOlaresId } from './utils/olares-id';
|
|
577
|
+
|
|
588
578
|
export default OlaresID;
|
|
@@ -8,43 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
import * as bip39 from 'bip39';
|
|
10
10
|
import * as varint from 'varint';
|
|
11
|
+
import { base58btc } from 'multiformats/bases/base58';
|
|
12
|
+
import { base64url } from 'multiformats/bases/base64';
|
|
11
13
|
|
|
12
14
|
// Browser globals type declaration
|
|
13
15
|
declare const window: any;
|
|
14
16
|
declare const btoa: (input: string) => string;
|
|
15
17
|
|
|
16
|
-
// Base58 Bitcoin alphabet
|
|
17
|
-
const BASE58_ALPHABET =
|
|
18
|
-
'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Encode bytes to base58btc format
|
|
22
|
-
* This is a pure implementation compatible with multiformats/bases/base58
|
|
23
|
-
*/
|
|
24
|
-
function base58Encode(bytes: Uint8Array): string {
|
|
25
|
-
// Convert bytes to bigint
|
|
26
|
-
let num = 0n;
|
|
27
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
28
|
-
num = num * 256n + BigInt(bytes[i]);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Convert to base58
|
|
32
|
-
let encoded = '';
|
|
33
|
-
while (num > 0n) {
|
|
34
|
-
const remainder = Number(num % 58n);
|
|
35
|
-
encoded = BASE58_ALPHABET[remainder] + encoded;
|
|
36
|
-
num = num / 58n;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Add leading '1's for leading zero bytes
|
|
40
|
-
for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
|
|
41
|
-
encoded = '1' + encoded;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Add 'z' prefix for base58btc multibase
|
|
45
|
-
return 'z' + encoded;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
18
|
export interface RSAPublicKeyData {
|
|
49
19
|
rsaPublicKey: string;
|
|
50
20
|
rsaPrivateKey: string;
|
|
@@ -239,7 +209,7 @@ async function getID(mnemonic: string): Promise<string> {
|
|
|
239
209
|
idBytes.set(publicKey.data(), ED25519_CODEC_ID.length);
|
|
240
210
|
|
|
241
211
|
// Encode to base58btc
|
|
242
|
-
const id =
|
|
212
|
+
const id = base58btc.encode(idBytes);
|
|
243
213
|
return id;
|
|
244
214
|
}
|
|
245
215
|
|
|
@@ -268,6 +238,93 @@ export async function getDIDFromMnemonic(mnemonic: string): Promise<string> {
|
|
|
268
238
|
return `did:key:${id}`;
|
|
269
239
|
}
|
|
270
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Generate Ed25519 JWK (JSON Web Key) from BIP39 mnemonic phrase
|
|
243
|
+
* Uses Trust Wallet Core for key derivation, ensuring compatibility with TermiPass
|
|
244
|
+
*
|
|
245
|
+
* @param mnemonic BIP39 mnemonic phrase (12, 15, 18, 21, or 24 words)
|
|
246
|
+
* @returns Object containing publicJwk and privateJwk in RFC 7517 format
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* const { publicJwk, privateJwk } = await getEd25519JwkFromMnemonic(mnemonic);
|
|
251
|
+
*
|
|
252
|
+
* // Public JWK (safe to share)
|
|
253
|
+
* console.log(publicJwk);
|
|
254
|
+
* // {
|
|
255
|
+
* // "kty": "OKP",
|
|
256
|
+
* // "crv": "Ed25519",
|
|
257
|
+
* // "alg": "EdDSA",
|
|
258
|
+
* // "use": "sig",
|
|
259
|
+
* // "kid": "did:key:z6Mk...#z6Mk...",
|
|
260
|
+
* // "x": "base64url-encoded-public-key"
|
|
261
|
+
* // }
|
|
262
|
+
*
|
|
263
|
+
* // Private JWK (keep secure!)
|
|
264
|
+
* console.log(privateJwk);
|
|
265
|
+
* // {
|
|
266
|
+
* // "kty": "OKP",
|
|
267
|
+
* // "crv": "Ed25519",
|
|
268
|
+
* // "alg": "EdDSA",
|
|
269
|
+
* // "use": "sig",
|
|
270
|
+
* // "kid": "did:key:z6Mk...#z6Mk...",
|
|
271
|
+
* // "x": "base64url-encoded-public-key",
|
|
272
|
+
* // "d": "base64url-encoded-private-key"
|
|
273
|
+
* // }
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
export async function getEd25519JwkFromMnemonic(mnemonic: string): Promise<{
|
|
277
|
+
publicJwk: any;
|
|
278
|
+
privateJwk: any;
|
|
279
|
+
}> {
|
|
280
|
+
// Validate mnemonic
|
|
281
|
+
if (!bip39.validateMnemonic(mnemonic)) {
|
|
282
|
+
throw new Error('Invalid mnemonic phrase');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const core = await loadWalletCore();
|
|
286
|
+
const { HDWallet, Curve } = core;
|
|
287
|
+
|
|
288
|
+
const wallet = HDWallet.createWithMnemonic(mnemonic, '');
|
|
289
|
+
const privateKey = wallet.getMasterKey(Curve.ed25519);
|
|
290
|
+
const publicKey = privateKey.getPublicKeyEd25519();
|
|
291
|
+
|
|
292
|
+
// Get key data
|
|
293
|
+
const publicKeyBytes = publicKey.data();
|
|
294
|
+
const privateKeyBytes = privateKey.data();
|
|
295
|
+
|
|
296
|
+
const idBytes = new Uint8Array(
|
|
297
|
+
publicKeyBytes.length + ED25519_CODEC_ID.length
|
|
298
|
+
);
|
|
299
|
+
idBytes.set(ED25519_CODEC_ID, 0);
|
|
300
|
+
idBytes.set(publicKeyBytes, ED25519_CODEC_ID.length);
|
|
301
|
+
const id = base58btc.encode(idBytes);
|
|
302
|
+
const did = `did:key:${id}`;
|
|
303
|
+
const keyId = `${did}#${id}`;
|
|
304
|
+
|
|
305
|
+
// Base64url encode the keys
|
|
306
|
+
const x = base64url.baseEncode(publicKeyBytes);
|
|
307
|
+
const d = base64url.baseEncode(privateKeyBytes);
|
|
308
|
+
|
|
309
|
+
// Public JWK (contains only public key material)
|
|
310
|
+
const publicJwk = {
|
|
311
|
+
kty: 'OKP', // Key Type: Octet Key Pair
|
|
312
|
+
crv: 'Ed25519', // Curve: Ed25519
|
|
313
|
+
alg: 'EdDSA', // Algorithm: EdDSA
|
|
314
|
+
use: 'sig', // Use: signature
|
|
315
|
+
kid: keyId, // Key ID
|
|
316
|
+
x: x // Public key parameter
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// Private JWK (contains both public and private key material)
|
|
320
|
+
const privateJwk = {
|
|
321
|
+
...publicJwk,
|
|
322
|
+
d: d // Private key parameter
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
return { publicJwk, privateJwk };
|
|
326
|
+
}
|
|
327
|
+
|
|
271
328
|
/**
|
|
272
329
|
* Derive both owner (Ethereum address) and DID from existing mnemonic
|
|
273
330
|
*
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Olares ID Utilities
|
|
3
|
+
*
|
|
4
|
+
* Olares ID is a new format that looks like email addresses: user@domain.com
|
|
5
|
+
* It's essentially a domain name where the first dot (.) is replaced with an at sign (@)
|
|
6
|
+
*
|
|
7
|
+
* Examples:
|
|
8
|
+
* - alice.example.com → alice@example.com (Olares ID)
|
|
9
|
+
* - bob.sub.example.com → bob@sub.example.com (Olares ID)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Convert Olares ID format to standard domain format
|
|
14
|
+
* Replaces the first @ with a dot (.)
|
|
15
|
+
*
|
|
16
|
+
* @param input The input string (can be either Olares ID or domain format)
|
|
17
|
+
* @returns The normalized domain format
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* normalizeToDomain('alice@example.com') // returns 'alice.example.com'
|
|
21
|
+
* normalizeToDomain('alice.example.com') // returns 'alice.example.com' (no change)
|
|
22
|
+
* normalizeToDomain('bob@sub.example.com') // returns 'bob.sub.example.com'
|
|
23
|
+
*/
|
|
24
|
+
export function normalizeToDomain(input: string): string {
|
|
25
|
+
if (!input) {
|
|
26
|
+
return input;
|
|
27
|
+
}
|
|
28
|
+
// Replace the first @ with a dot
|
|
29
|
+
return input.replace('@', '.');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Convert standard domain format to Olares ID format
|
|
34
|
+
* Replaces the first dot (.) with an at sign (@)
|
|
35
|
+
*
|
|
36
|
+
* @param domain The domain name
|
|
37
|
+
* @returns The Olares ID format
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* normalizeToOlaresId('alice.example.com') // returns 'alice@example.com'
|
|
41
|
+
* normalizeToOlaresId('bob.sub.example.com') // returns 'bob@sub.example.com'
|
|
42
|
+
*/
|
|
43
|
+
export function normalizeToOlaresId(domain: string): string {
|
|
44
|
+
if (!domain) {
|
|
45
|
+
return domain;
|
|
46
|
+
}
|
|
47
|
+
// Replace the first dot with @
|
|
48
|
+
return domain.replace('.', '@');
|
|
49
|
+
}
|