Make shared generators work when called from .NET Blazor interop (#896)

This commit is contained in:
Leendert de Borst
2025-06-06 13:19:52 +02:00
committed by Leendert de Borst
parent 4c7bef2a5a
commit cbe8b2c471
16 changed files with 354 additions and 188 deletions

View File

@@ -16,39 +16,6 @@ type Identity = {
nickName: string;
};
/**
* Generate a username or email prefix.
*/
declare class UsernameEmailGenerator {
private static readonly MIN_LENGTH;
private static readonly MAX_LENGTH;
private readonly symbols;
/**
* Generate a username based on an identity.
*/
generateUsername(identity: Identity): string;
/**
* Generate an email prefix based on an identity.
*/
generateEmailPrefix(identity: Identity): string;
/**
* Sanitize an email prefix.
*/
private sanitizeEmailPrefix;
/**
* Get a random symbol.
*/
private getRandomSymbol;
/**
* Generate a random string.
*/
private generateRandomString;
/**
* Generate a secure random integer between 0 (inclusive) and max (exclusive)
*/
private getSecureRandom;
}
interface IIdentityGenerator {
generateRandomIdentity(): Identity;
}
@@ -132,6 +99,39 @@ declare class IdentityHelperUtils {
static isValidBirthDate(input: string | undefined): boolean;
}
/**
* Generate a username or email prefix.
*/
declare class UsernameEmailGenerator {
private static readonly MIN_LENGTH;
private static readonly MAX_LENGTH;
private readonly symbols;
/**
* Generate a username based on an identity.
*/
generateUsername(identity: Identity): string;
/**
* Generate an email prefix based on an identity.
*/
generateEmailPrefix(identity: Identity): string;
/**
* Sanitize an email prefix.
*/
private sanitizeEmailPrefix;
/**
* Get a random symbol.
*/
private getRandomSymbol;
/**
* Generate a random string.
*/
private generateRandomString;
/**
* Generate a secure random integer between 0 (inclusive) and max (exclusive)
*/
private getSecureRandom;
}
/**
* Creates a new identity generator based on the language.
* @param language - The language to use for generating the identity (e.g. "en", "nl").
@@ -139,4 +139,11 @@ declare class IdentityHelperUtils {
*/
declare const CreateIdentityGenerator: (language: string) => IIdentityGenerator;
export { CreateIdentityGenerator, Gender, type Identity, IdentityGenerator, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator };
/**
* Creates a new username email generator. This is used by the .NET Blazor WASM JSinterop
* as it cannot create instances of classes directly, it has to use a factory method.
* @returns A new username email generator instance.
*/
declare const CreateUsernameEmailGenerator: () => UsernameEmailGenerator;
export { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, type Identity, IdentityGenerator, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator };

View File

@@ -24,6 +24,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
var index_exports = {};
__export(index_exports, {
CreateIdentityGenerator: () => CreateIdentityGenerator,
CreateUsernameEmailGenerator: () => CreateUsernameEmailGenerator,
Gender: () => Gender,
IdentityGenerator: () => IdentityGenerator,
IdentityGeneratorEn: () => IdentityGeneratorEn,
@@ -33,6 +34,14 @@ __export(index_exports, {
});
module.exports = __toCommonJS(index_exports);
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/utils/UsernameEmailGenerator.ts
var _UsernameEmailGenerator = class _UsernameEmailGenerator {
constructor() {
@@ -56,6 +65,9 @@ var _UsernameEmailGenerator = class _UsernameEmailGenerator {
*/
generateEmailPrefix(identity) {
const parts = [];
if (typeof identity.birthDate === "string") {
identity.birthDate = new Date(identity.birthDate);
}
switch (this.getSecureRandom(4)) {
case 0:
parts.push(identity.firstName.substring(0, 1).toLowerCase() + identity.lastName.toLowerCase());
@@ -131,14 +143,6 @@ _UsernameEmailGenerator.MIN_LENGTH = 6;
_UsernameEmailGenerator.MAX_LENGTH = 20;
var UsernameEmailGenerator = _UsernameEmailGenerator;
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/implementations/base/IdentityGenerator.ts
var IdentityGenerator = class {
/**
@@ -1727,9 +1731,15 @@ var CreateIdentityGenerator = (language) => {
}
throw new Error(`Unsupported language: ${language}`);
};
// src/factories/UsernameEmailGeneratorFactory.ts
var CreateUsernameEmailGenerator = () => {
return new UsernameEmailGenerator();
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
CreateIdentityGenerator,
CreateUsernameEmailGenerator,
Gender,
IdentityGenerator,
IdentityGeneratorEn,

View File

@@ -2,6 +2,14 @@
// This file was automatically generated. Do not edit manually.
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/utils/UsernameEmailGenerator.ts
var _UsernameEmailGenerator = class _UsernameEmailGenerator {
constructor() {
@@ -25,6 +33,9 @@ var _UsernameEmailGenerator = class _UsernameEmailGenerator {
*/
generateEmailPrefix(identity) {
const parts = [];
if (typeof identity.birthDate === "string") {
identity.birthDate = new Date(identity.birthDate);
}
switch (this.getSecureRandom(4)) {
case 0:
parts.push(identity.firstName.substring(0, 1).toLowerCase() + identity.lastName.toLowerCase());
@@ -100,14 +111,6 @@ _UsernameEmailGenerator.MIN_LENGTH = 6;
_UsernameEmailGenerator.MAX_LENGTH = 20;
var UsernameEmailGenerator = _UsernameEmailGenerator;
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/implementations/base/IdentityGenerator.ts
var IdentityGenerator = class {
/**
@@ -1696,8 +1699,14 @@ var CreateIdentityGenerator = (language) => {
}
throw new Error(`Unsupported language: ${language}`);
};
// src/factories/UsernameEmailGeneratorFactory.ts
var CreateUsernameEmailGenerator = () => {
return new UsernameEmailGenerator();
};
export {
CreateIdentityGenerator,
CreateUsernameEmailGenerator,
Gender,
IdentityGenerator,
IdentityGeneratorEn,

View File

@@ -16,39 +16,6 @@ type Identity = {
nickName: string;
};
/**
* Generate a username or email prefix.
*/
declare class UsernameEmailGenerator {
private static readonly MIN_LENGTH;
private static readonly MAX_LENGTH;
private readonly symbols;
/**
* Generate a username based on an identity.
*/
generateUsername(identity: Identity): string;
/**
* Generate an email prefix based on an identity.
*/
generateEmailPrefix(identity: Identity): string;
/**
* Sanitize an email prefix.
*/
private sanitizeEmailPrefix;
/**
* Get a random symbol.
*/
private getRandomSymbol;
/**
* Generate a random string.
*/
private generateRandomString;
/**
* Generate a secure random integer between 0 (inclusive) and max (exclusive)
*/
private getSecureRandom;
}
interface IIdentityGenerator {
generateRandomIdentity(): Identity;
}
@@ -132,6 +99,39 @@ declare class IdentityHelperUtils {
static isValidBirthDate(input: string | undefined): boolean;
}
/**
* Generate a username or email prefix.
*/
declare class UsernameEmailGenerator {
private static readonly MIN_LENGTH;
private static readonly MAX_LENGTH;
private readonly symbols;
/**
* Generate a username based on an identity.
*/
generateUsername(identity: Identity): string;
/**
* Generate an email prefix based on an identity.
*/
generateEmailPrefix(identity: Identity): string;
/**
* Sanitize an email prefix.
*/
private sanitizeEmailPrefix;
/**
* Get a random symbol.
*/
private getRandomSymbol;
/**
* Generate a random string.
*/
private generateRandomString;
/**
* Generate a secure random integer between 0 (inclusive) and max (exclusive)
*/
private getSecureRandom;
}
/**
* Creates a new identity generator based on the language.
* @param language - The language to use for generating the identity (e.g. "en", "nl").
@@ -139,4 +139,11 @@ declare class IdentityHelperUtils {
*/
declare const CreateIdentityGenerator: (language: string) => IIdentityGenerator;
export { CreateIdentityGenerator, Gender, type Identity, IdentityGenerator, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator };
/**
* Creates a new username email generator. This is used by the .NET Blazor WASM JSinterop
* as it cannot create instances of classes directly, it has to use a factory method.
* @returns A new username email generator instance.
*/
declare const CreateUsernameEmailGenerator: () => UsernameEmailGenerator;
export { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, type Identity, IdentityGenerator, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator };

View File

@@ -24,6 +24,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
var index_exports = {};
__export(index_exports, {
CreateIdentityGenerator: () => CreateIdentityGenerator,
CreateUsernameEmailGenerator: () => CreateUsernameEmailGenerator,
Gender: () => Gender,
IdentityGenerator: () => IdentityGenerator,
IdentityGeneratorEn: () => IdentityGeneratorEn,
@@ -33,6 +34,14 @@ __export(index_exports, {
});
module.exports = __toCommonJS(index_exports);
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/utils/UsernameEmailGenerator.ts
var _UsernameEmailGenerator = class _UsernameEmailGenerator {
constructor() {
@@ -56,6 +65,9 @@ var _UsernameEmailGenerator = class _UsernameEmailGenerator {
*/
generateEmailPrefix(identity) {
const parts = [];
if (typeof identity.birthDate === "string") {
identity.birthDate = new Date(identity.birthDate);
}
switch (this.getSecureRandom(4)) {
case 0:
parts.push(identity.firstName.substring(0, 1).toLowerCase() + identity.lastName.toLowerCase());
@@ -131,14 +143,6 @@ _UsernameEmailGenerator.MIN_LENGTH = 6;
_UsernameEmailGenerator.MAX_LENGTH = 20;
var UsernameEmailGenerator = _UsernameEmailGenerator;
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/implementations/base/IdentityGenerator.ts
var IdentityGenerator = class {
/**
@@ -1727,9 +1731,15 @@ var CreateIdentityGenerator = (language) => {
}
throw new Error(`Unsupported language: ${language}`);
};
// src/factories/UsernameEmailGeneratorFactory.ts
var CreateUsernameEmailGenerator = () => {
return new UsernameEmailGenerator();
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
CreateIdentityGenerator,
CreateUsernameEmailGenerator,
Gender,
IdentityGenerator,
IdentityGeneratorEn,

View File

@@ -2,6 +2,14 @@
// This file was automatically generated. Do not edit manually.
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/utils/UsernameEmailGenerator.ts
var _UsernameEmailGenerator = class _UsernameEmailGenerator {
constructor() {
@@ -25,6 +33,9 @@ var _UsernameEmailGenerator = class _UsernameEmailGenerator {
*/
generateEmailPrefix(identity) {
const parts = [];
if (typeof identity.birthDate === "string") {
identity.birthDate = new Date(identity.birthDate);
}
switch (this.getSecureRandom(4)) {
case 0:
parts.push(identity.firstName.substring(0, 1).toLowerCase() + identity.lastName.toLowerCase());
@@ -100,14 +111,6 @@ _UsernameEmailGenerator.MIN_LENGTH = 6;
_UsernameEmailGenerator.MAX_LENGTH = 20;
var UsernameEmailGenerator = _UsernameEmailGenerator;
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/implementations/base/IdentityGenerator.ts
var IdentityGenerator = class {
/**
@@ -1696,8 +1699,14 @@ var CreateIdentityGenerator = (language) => {
}
throw new Error(`Unsupported language: ${language}`);
};
// src/factories/UsernameEmailGeneratorFactory.ts
var CreateUsernameEmailGenerator = () => {
return new UsernameEmailGenerator();
};
export {
CreateIdentityGenerator,
CreateUsernameEmailGenerator,
Gender,
IdentityGenerator,
IdentityGeneratorEn,

View File

@@ -161,7 +161,7 @@
}
credential.Passwords = new List<Password> { new() };
await CredentialService.GenerateRandomIdentity(credential);
await CredentialService.GenerateRandomIdentityAsync(credential);
var id = await CredentialService.InsertEntryAsync(credential);
if (id == Guid.Empty)

View File

@@ -2,12 +2,7 @@
@page "/credentials/{id:guid}/edit"
@inherits MainBase
@inject CredentialService CredentialService
@using System.Globalization
@using System.Text.Json
@using System.Text.Json.Serialization
@using AliasVault.Generators.Identity
@using AliasVault.Generators.Identity.Implementations.Factories
@using AliasVault.Generators.Identity.Models
@using AliasVault.Client.Services
@inject IJSRuntime JSRuntime
@implements IAsyncDisposable
@@ -192,7 +187,7 @@ else
if (firstRender)
{
Module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./js/modules/newIdentityWidget.js");
if (EditMode)
{
await LoadExistingCredential();
@@ -233,7 +228,7 @@ else
}
Obj = CredentialEdit.FromEntity(alias);
// If BirthDate is MinValue, set AliasBirthDate to empty string
// TODO: after date field in alias data model is made optional and
// all min values have been replaced with null, we can remove this check.
@@ -241,33 +236,39 @@ else
{
Obj.AliasBirthDate = string.Empty;
}
if (Obj.ServiceUrl is null)
{
Obj.ServiceUrl = CredentialService.DefaultServiceUrl;
}
}
/// <summary>
/// Creates a new credential object.
/// </summary>
private Credential CreateNewCredentialObject()
{
var credential = new Credential();
credential.Alias = new Alias();
credential.Alias.Email = "@" + CredentialService.GetDefaultEmailDomain();
credential.Service = new Service();
credential.Passwords = new List<Password> { new Password() };
credential.TotpCodes = new List<TotpCode>();
return credential;
}
/// <summary>
/// Creates a new credential object.
/// </summary>
private void CreateNewCredential()
{
// Create new Obj
var alias = new Credential();
alias.Alias = new Alias();
alias.Alias.Email = "@" + CredentialService.GetDefaultEmailDomain();
alias.Service = new Service();
alias.Passwords = new List<Password> { new Password() };
alias.TotpCodes = new List<TotpCode>();
Obj = CredentialEdit.FromEntity(CreateNewCredentialObject());
Obj = CredentialEdit.FromEntity(alias);
// Always set AliasBirthDate to empty for new credentials
// TODO: after date field in alias data model is made optional and
// all min values have been replaced with null, we can remove this check.
Obj.AliasBirthDate = string.Empty;
Obj.ServiceUrl = CredentialService.DefaultServiceUrl;
}
@@ -321,8 +322,8 @@ else
string currentPassword = Obj.Password.Value ?? string.Empty;
// Generate random identity but preserve username and password
Obj = CredentialEdit.FromEntity(await CredentialService.GenerateRandomIdentity(Obj.ToEntity()));
Obj = CredentialEdit.FromEntity(await CredentialService.GenerateRandomIdentityAsync(Obj.ToEntity()));
// Restore username and password
Obj.Username = currentUsername;
Obj.Password.Value = currentPassword;
@@ -330,7 +331,7 @@ else
else
{
// For new credentials, generate everything
Obj = CredentialEdit.FromEntity(await CredentialService.GenerateRandomIdentity(Obj.ToEntity()));
Obj = CredentialEdit.FromEntity(await CredentialService.GenerateRandomIdentityAsync(Obj.ToEntity()));
IsPasswordVisible = true;
}
@@ -345,26 +346,35 @@ else
private async Task GenerateRandomUsername()
{
// If current object is null, then we create a new random identity.
Identity identity;
JsInteropService.AliasVaultIdentity identity;
if (Obj.Alias.FirstName is null && Obj.Alias.LastName is null && Obj.Alias.BirthDate == DateTime.MinValue)
{
identity = await IdentityGeneratorFactory.CreateIdentityGenerator(DbService.Settings.DefaultIdentityLanguage).GenerateRandomIdentityAsync();
// Create new Credential object to avoid modifying the original object
var randomIdentity = await CredentialService.GenerateRandomIdentityAsync(CreateNewCredentialObject());
identity = new JsInteropService.AliasVaultIdentity
{
FirstName = randomIdentity.Alias.FirstName ?? string.Empty,
LastName = randomIdentity.Alias.LastName ?? string.Empty,
BirthDate = randomIdentity.Alias.BirthDate.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),
Gender = randomIdentity.Alias.Gender,
NickName = randomIdentity.Alias.NickName ?? string.Empty,
};
}
else
{
// Assemble identity model with the current values
identity = new Identity
identity = new JsInteropService.AliasVaultIdentity
{
FirstName = Obj.Alias.FirstName ?? string.Empty,
LastName = Obj.Alias.LastName ?? string.Empty,
BirthDate = Obj.Alias.BirthDate,
Gender = Obj.Alias.Gender == Gender.Female.ToString() ? Gender.Female : Gender.Male,
BirthDate = Obj.Alias.BirthDate.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),
Gender = Obj.Alias.Gender,
NickName = Obj.Alias.NickName ?? string.Empty,
};
}
var generator = new UsernameEmailGenerator();
Obj.Username = generator.GenerateUsername(identity);
Obj.Username = await JsInteropService.GenerateRandomUsernameAsync(identity);
}
/// <summary>

View File

@@ -49,7 +49,7 @@ public sealed class CredentialService(HttpClient httpClient, DbService dbService
/// </summary>
/// <param name="credential">The credential object to update.</param>
/// <returns>Task.</returns>
public async Task<Credential> GenerateRandomIdentity(Credential credential)
public async Task<Credential> GenerateRandomIdentityAsync(Credential credential)
{
const int MaxAttempts = 5;
var attempts = 0;
@@ -60,13 +60,15 @@ public sealed class CredentialService(HttpClient httpClient, DbService dbService
// Generate a random identity using the TypeScript library
var identity = await jsInteropService.GenerateRandomIdentityAsync(dbService.Settings.DefaultIdentityLanguage);
Console.WriteLine($"Generated identity: {identity.FirstName} {identity.LastName} {identity.BirthDate} {identity.Gender} {identity.NickName}");
// Generate random values for the Identity properties
credential.Username = identity.NickName;
credential.Alias.FirstName = identity.FirstName;
credential.Alias.LastName = identity.LastName;
credential.Alias.NickName = identity.NickName;
credential.Alias.Gender = identity.Gender;
credential.Alias.BirthDate = identity.BirthDate;
credential.Alias.BirthDate = string.IsNullOrEmpty(identity.BirthDate) ? DateTime.MinValue : DateTime.Parse(identity.BirthDate);
// Set the email
var emailDomain = GetDefaultEmailDomain();

View File

@@ -291,8 +291,8 @@ public sealed class JsInteropService(IJSRuntime jsRuntime)
/// Generates a random identity using the specified language.
/// </summary>
/// <param name="language">The language to use for generating the identity (e.g. "en", "nl").</param>
/// <returns>A <see cref="IdentityGeneratorResult"/> containing the generated identity information.</returns>
public async Task<IdentityGeneratorResult> GenerateRandomIdentityAsync(string language)
/// <returns>A <see cref="AliasVaultIdentity"/> containing the generated identity information.</returns>
public async Task<AliasVaultIdentity> GenerateRandomIdentityAsync(string language)
{
try
{
@@ -306,7 +306,7 @@ public sealed class JsInteropService(IJSRuntime jsRuntime)
}
var generatorInstance = await _identityGeneratorModule.InvokeAsync<IJSObjectReference>("CreateIdentityGenerator", language);
var result = await generatorInstance.InvokeAsync<IdentityGeneratorResult>("generateRandomIdentity");
var result = await generatorInstance.InvokeAsync<AliasVaultIdentity>("generateRandomIdentity");
return result;
}
@@ -317,6 +317,66 @@ public sealed class JsInteropService(IJSRuntime jsRuntime)
}
}
/// <summary>
/// Generates a random username.
/// </summary>
/// <param name="identity">The identity to use for generating the username.</param>
/// <returns>The generated username.</returns>
public async Task<string> GenerateRandomUsernameAsync(AliasVaultIdentity identity)
{
try
{
if (_identityGeneratorModule == null)
{
await InitializeAsync();
if (_identityGeneratorModule == null)
{
throw new InvalidOperationException("Failed to initialize identity generator module");
}
}
Console.WriteLine($"Generating username for identity: {identity.FirstName} {identity.LastName} {identity.BirthDate} {identity.Gender} {identity.NickName}");
var generatorInstance = await _identityGeneratorModule.InvokeAsync<IJSObjectReference>("CreateUsernameEmailGenerator");
var result = await generatorInstance.InvokeAsync<string>("generateUsername", identity);
return result;
}
catch (JSException ex)
{
await Console.Error.WriteLineAsync($"JavaScript error generating username: {ex.Message}");
throw new InvalidOperationException("Failed to generate random username", ex);
}
}
/// <summary>
/// Generates a random email prefix.
/// </summary>
/// <param name="identity">The identity to use for generating the email prefix.</param>
/// <returns>The generated email prefix.</returns>
public async Task<string> GenerateRandomEmailPrefixAsync(AliasVaultIdentity identity)
{
try
{
if (_identityGeneratorModule == null)
{
await InitializeAsync();
if (_identityGeneratorModule == null)
{
throw new InvalidOperationException("Failed to initialize identity generator module");
}
}
var generatorInstance = await _identityGeneratorModule.InvokeAsync<IJSObjectReference>("CreateUsernameEmailGenerator");
var result = await generatorInstance.InvokeAsync<string>("generateEmailPrefix", identity);
return result;
}
catch (JSException ex)
{
await Console.Error.WriteLineAsync($"JavaScript error generating email prefix: {ex.Message}");
throw new InvalidOperationException("Failed to generate random email prefix", ex);
}
}
/// <summary>
/// Generates a random password using the specified settings.
/// </summary>
@@ -351,7 +411,7 @@ public sealed class JsInteropService(IJSRuntime jsRuntime)
/// <summary>
/// Represents the result of a JavaScript identity generator operation.
/// </summary>
public sealed class IdentityGeneratorResult
public sealed class AliasVaultIdentity
{
/// <summary>
/// Gets the first name.
@@ -366,7 +426,7 @@ public sealed class JsInteropService(IJSRuntime jsRuntime)
/// <summary>
/// Gets the birth date.
/// </summary>
public DateTime BirthDate { get; init; }
public string? BirthDate { get; init; }
/// <summary>
/// Gets the email prefix.

View File

@@ -16,39 +16,6 @@ type Identity = {
nickName: string;
};
/**
* Generate a username or email prefix.
*/
declare class UsernameEmailGenerator {
private static readonly MIN_LENGTH;
private static readonly MAX_LENGTH;
private readonly symbols;
/**
* Generate a username based on an identity.
*/
generateUsername(identity: Identity): string;
/**
* Generate an email prefix based on an identity.
*/
generateEmailPrefix(identity: Identity): string;
/**
* Sanitize an email prefix.
*/
private sanitizeEmailPrefix;
/**
* Get a random symbol.
*/
private getRandomSymbol;
/**
* Generate a random string.
*/
private generateRandomString;
/**
* Generate a secure random integer between 0 (inclusive) and max (exclusive)
*/
private getSecureRandom;
}
interface IIdentityGenerator {
generateRandomIdentity(): Identity;
}
@@ -132,6 +99,39 @@ declare class IdentityHelperUtils {
static isValidBirthDate(input: string | undefined): boolean;
}
/**
* Generate a username or email prefix.
*/
declare class UsernameEmailGenerator {
private static readonly MIN_LENGTH;
private static readonly MAX_LENGTH;
private readonly symbols;
/**
* Generate a username based on an identity.
*/
generateUsername(identity: Identity): string;
/**
* Generate an email prefix based on an identity.
*/
generateEmailPrefix(identity: Identity): string;
/**
* Sanitize an email prefix.
*/
private sanitizeEmailPrefix;
/**
* Get a random symbol.
*/
private getRandomSymbol;
/**
* Generate a random string.
*/
private generateRandomString;
/**
* Generate a secure random integer between 0 (inclusive) and max (exclusive)
*/
private getSecureRandom;
}
/**
* Creates a new identity generator based on the language.
* @param language - The language to use for generating the identity (e.g. "en", "nl").
@@ -139,4 +139,11 @@ declare class IdentityHelperUtils {
*/
declare const CreateIdentityGenerator: (language: string) => IIdentityGenerator;
export { CreateIdentityGenerator, Gender, type Identity, IdentityGenerator, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator };
/**
* Creates a new username email generator. This is used by the .NET Blazor WASM JSinterop
* as it cannot create instances of classes directly, it has to use a factory method.
* @returns A new username email generator instance.
*/
declare const CreateUsernameEmailGenerator: () => UsernameEmailGenerator;
export { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, type Identity, IdentityGenerator, IdentityGeneratorEn, IdentityGeneratorNl, IdentityHelperUtils, UsernameEmailGenerator };

View File

@@ -24,6 +24,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
var index_exports = {};
__export(index_exports, {
CreateIdentityGenerator: () => CreateIdentityGenerator,
CreateUsernameEmailGenerator: () => CreateUsernameEmailGenerator,
Gender: () => Gender,
IdentityGenerator: () => IdentityGenerator,
IdentityGeneratorEn: () => IdentityGeneratorEn,
@@ -33,6 +34,14 @@ __export(index_exports, {
});
module.exports = __toCommonJS(index_exports);
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/utils/UsernameEmailGenerator.ts
var _UsernameEmailGenerator = class _UsernameEmailGenerator {
constructor() {
@@ -56,6 +65,9 @@ var _UsernameEmailGenerator = class _UsernameEmailGenerator {
*/
generateEmailPrefix(identity) {
const parts = [];
if (typeof identity.birthDate === "string") {
identity.birthDate = new Date(identity.birthDate);
}
switch (this.getSecureRandom(4)) {
case 0:
parts.push(identity.firstName.substring(0, 1).toLowerCase() + identity.lastName.toLowerCase());
@@ -131,14 +143,6 @@ _UsernameEmailGenerator.MIN_LENGTH = 6;
_UsernameEmailGenerator.MAX_LENGTH = 20;
var UsernameEmailGenerator = _UsernameEmailGenerator;
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/implementations/base/IdentityGenerator.ts
var IdentityGenerator = class {
/**
@@ -1727,9 +1731,15 @@ var CreateIdentityGenerator = (language) => {
}
throw new Error(`Unsupported language: ${language}`);
};
// src/factories/UsernameEmailGeneratorFactory.ts
var CreateUsernameEmailGenerator = () => {
return new UsernameEmailGenerator();
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
CreateIdentityGenerator,
CreateUsernameEmailGenerator,
Gender,
IdentityGenerator,
IdentityGeneratorEn,

View File

@@ -2,6 +2,14 @@
// This file was automatically generated. Do not edit manually.
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/utils/UsernameEmailGenerator.ts
var _UsernameEmailGenerator = class _UsernameEmailGenerator {
constructor() {
@@ -25,6 +33,9 @@ var _UsernameEmailGenerator = class _UsernameEmailGenerator {
*/
generateEmailPrefix(identity) {
const parts = [];
if (typeof identity.birthDate === "string") {
identity.birthDate = new Date(identity.birthDate);
}
switch (this.getSecureRandom(4)) {
case 0:
parts.push(identity.firstName.substring(0, 1).toLowerCase() + identity.lastName.toLowerCase());
@@ -100,14 +111,6 @@ _UsernameEmailGenerator.MIN_LENGTH = 6;
_UsernameEmailGenerator.MAX_LENGTH = 20;
var UsernameEmailGenerator = _UsernameEmailGenerator;
// src/types/Gender.ts
var Gender = /* @__PURE__ */ ((Gender2) => {
Gender2["Male"] = "Male";
Gender2["Female"] = "Female";
Gender2["Other"] = "Other";
return Gender2;
})(Gender || {});
// src/implementations/base/IdentityGenerator.ts
var IdentityGenerator = class {
/**
@@ -1696,8 +1699,14 @@ var CreateIdentityGenerator = (language) => {
}
throw new Error(`Unsupported language: ${language}`);
};
// src/factories/UsernameEmailGeneratorFactory.ts
var CreateUsernameEmailGenerator = () => {
return new UsernameEmailGenerator();
};
export {
CreateIdentityGenerator,
CreateUsernameEmailGenerator,
Gender,
IdentityGenerator,
IdentityGeneratorEn,

View File

@@ -0,0 +1,10 @@
import { UsernameEmailGenerator } from "src/utils/UsernameEmailGenerator";
/**
* Creates a new username email generator. This is used by the .NET Blazor WASM JSinterop
* as it cannot create instances of classes directly, it has to use a factory method.
* @returns A new username email generator instance.
*/
export const CreateUsernameEmailGenerator = (): UsernameEmailGenerator => {
return new UsernameEmailGenerator();
};

View File

@@ -1,8 +1,9 @@
export * from './utils/UsernameEmailGenerator';
export * from './types/Identity';
export * from './types/Gender';
export * from './implementations/IdentityGeneratorEn';
export * from './implementations/IdentityGeneratorNl';
export * from './implementations/base/IdentityGenerator';
export * from './utils/IdentityHelperUtils';
export * from './utils/UsernameEmailGenerator';
export * from './factories/IdentityGeneratorFactory';
export * from './factories/UsernameEmailGeneratorFactory';

View File

@@ -32,6 +32,11 @@ export class UsernameEmailGenerator {
public generateEmailPrefix(identity: Identity): string {
const parts: string[] = [];
// Make sure the birth date is not a string which can happen when using the .NET Blazor WASM JSInterop.
if (typeof identity.birthDate === 'string') {
identity.birthDate = new Date(identity.birthDate);
}
switch (this.getSecureRandom(4)) {
case 0:
// First initial + last name