1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-12 06:23:38 +00:00

refactor: introduce @bitwarden/platform-utils

This commit is contained in:
addisonbeck
2025-08-09 12:21:31 -04:00
parent db5b08bd0f
commit 63446fda81
17 changed files with 204 additions and 57 deletions

1
.github/CODEOWNERS vendored
View File

@@ -104,6 +104,7 @@ libs/state @bitwarden/team-platform-dev
libs/state-test-utils @bitwarden/team-platform-dev
libs/device-type @bitwarden/team-platform-dev
libs/encoding @bitwarden/team-platform-dev
libs/platform-utils @bitwarden/team-platform-dev
# Web utils used across app and connectors
apps/web/src/utils/ @bitwarden/team-platform-dev
# Web core and shared files

View File

@@ -1,57 +1 @@
import { ClientType, DeviceType } from "../../enums";
interface ToastOptions {
timeout?: number;
}
export type ClipboardOptions = {
allowHistory?: boolean;
clearing?: boolean;
clearMs?: number;
window?: Window;
};
export abstract class PlatformUtilsService {
abstract getDevice(): DeviceType;
abstract getDeviceString(): string;
abstract getClientType(): ClientType;
abstract isFirefox(): boolean;
abstract isChrome(): boolean;
abstract isEdge(): boolean;
abstract isOpera(): boolean;
abstract isVivaldi(): boolean;
abstract isSafari(): boolean;
abstract isMacAppStore(): boolean;
abstract isViewOpen(): Promise<boolean>;
abstract launchUri(uri: string, options?: any): void;
abstract getApplicationVersion(): Promise<string>;
abstract getApplicationVersionNumber(): Promise<string>;
abstract supportsWebAuthn(win: Window): boolean;
abstract supportsDuo(): boolean;
/**
* Returns true if the device supports autofill functionality
*/
abstract supportsAutofill(): boolean;
/**
* Returns true if the device supports native file downloads without
* the need for `target="_blank"`
*/
abstract supportsFileDownloads(): boolean;
/**
* @deprecated use `@bitwarden/components/ToastService.showToast` instead
*
* Jira: [CL-213](https://bitwarden.atlassian.net/browse/CL-213)
*/
abstract showToast(
type: "error" | "success" | "warning" | "info",
title: string,
text: string | string[],
options?: ToastOptions,
): void;
abstract isDev(): boolean;
abstract isSelfHost(): boolean;
abstract copyToClipboard(text: string, options?: ClipboardOptions): void | boolean;
abstract readFromClipboard(): Promise<string>;
abstract supportsSecureStorage(): boolean;
abstract getAutofillKeyboardShortcut(): Promise<string>;
}
export { ClipboardOptions, PlatformUtilsService } from "@bitwarden/platform-utils";

View File

@@ -0,0 +1,5 @@
# platform-utils
Owned by: platform
Assorted utils for working with toasts, device type, clipboard, etc. This library needs to be broken up

View File

@@ -0,0 +1,3 @@
import baseConfig from "../../eslint.config.mjs";
export default [...baseConfig];

View File

@@ -0,0 +1,10 @@
module.exports = {
displayName: "platform-utils",
preset: "../../jest.preset.js",
testEnvironment: "node",
transform: {
"^.+\\.[tj]s$": ["ts-jest", { tsconfig: "<rootDir>/tsconfig.spec.json" }],
},
moduleFileExtensions: ["ts", "js", "html"],
coverageDirectory: "../../coverage/libs/platform-utils",
};

View File

@@ -0,0 +1,11 @@
{
"name": "@bitwarden/platform-utils",
"version": "0.0.1",
"description": "Assorted utils for working with toasts, device type, clipboard, etc. This library needs to be broken up",
"private": true,
"type": "commonjs",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "GPL-3.0",
"author": "platform"
}

View File

@@ -0,0 +1,33 @@
{
"name": "platform-utils",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/platform-utils/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/platform-utils",
"main": "libs/platform-utils/src/index.ts",
"tsConfig": "libs/platform-utils/tsconfig.lib.json",
"assets": ["libs/platform-utils/*.md"]
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/platform-utils/**/*.ts"]
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/platform-utils/jest.config.js"
}
}
}
}

View File

@@ -0,0 +1,58 @@
import { ClientType } from "@bitwarden/client-type";
import { DeviceType } from "@bitwarden/device-type";
interface ToastOptions {
timeout?: number;
}
export type ClipboardOptions = {
allowHistory?: boolean;
clearing?: boolean;
clearMs?: number;
window?: Window;
};
export abstract class PlatformUtilsService {
abstract getDevice(): DeviceType;
abstract getDeviceString(): string;
abstract getClientType(): ClientType;
abstract isFirefox(): boolean;
abstract isChrome(): boolean;
abstract isEdge(): boolean;
abstract isOpera(): boolean;
abstract isVivaldi(): boolean;
abstract isSafari(): boolean;
abstract isMacAppStore(): boolean;
abstract isViewOpen(): Promise<boolean>;
abstract launchUri(uri: string, options?: any): void;
abstract getApplicationVersion(): Promise<string>;
abstract getApplicationVersionNumber(): Promise<string>;
abstract supportsWebAuthn(win: Window): boolean;
abstract supportsDuo(): boolean;
/**
* Returns true if the device supports autofill functionality
*/
abstract supportsAutofill(): boolean;
/**
* Returns true if the device supports native file downloads without
* the need for `target="_blank"`
*/
abstract supportsFileDownloads(): boolean;
/**
* @deprecated use `@bitwarden/components/ToastService.showToast` instead
*
* Jira: [CL-213](https://bitwarden.atlassian.net/browse/CL-213)
*/
abstract showToast(
type: "error" | "success" | "warning" | "info",
title: string,
text: string | string[],
options?: ToastOptions,
): void;
abstract isDev(): boolean;
abstract isSelfHost(): boolean;
abstract copyToClipboard(text: string, options?: ClipboardOptions): void | boolean;
abstract readFromClipboard(): Promise<string>;
abstract supportsSecureStorage(): boolean;
abstract getAutofillKeyboardShortcut(): Promise<string>;
}

View File

@@ -0,0 +1,8 @@
import * as lib from "./index";
describe("platform-utils", () => {
// This test will fail until something is exported from index.ts
it("should work", () => {
expect(lib).toBeDefined();
});
});

View File

@@ -0,0 +1,6 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": ["src/**/*.ts", "src/**/*.js"],
"exclude": ["**/build", "**/dist"]
}

View File

@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": ["jest.config.js", "src/**/*.spec.ts"]
}

View File

@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"moduleResolution": "node10",
"types": ["jest", "node"]
},
"include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"]
}

View File

@@ -0,0 +1,25 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Jsonify } from "type-fest";
import { DeviceType } from "@bitwarden/device-type";
import { PlatformUtilsService } from "../../../../platform/abstractions/platform-utils.service";
export class DeviceRequest {
type: DeviceType;
name: string;
identifier: string;
pushToken?: string;
constructor(appId: string, platformUtilsService: PlatformUtilsService) {
this.type = platformUtilsService.getDevice();
this.name = platformUtilsService.getDeviceString();
this.identifier = appId;
this.pushToken = null;
}
static fromJSON(json: Jsonify<DeviceRequest>) {
return Object.assign(Object.create(DeviceRequest.prototype), json);
}
}

9
package-lock.json generated
View File

@@ -402,6 +402,11 @@
"version": "0.0.0",
"license": "GPL-3.0"
},
"libs/platform-utils": {
"name": "@bitwarden/platform-utils",
"version": "0.0.1",
"license": "GPL-3.0"
},
"libs/serialization": {
"name": "@bitwarden/serialization",
"version": "0.0.1",
@@ -4681,6 +4686,10 @@
"resolved": "libs/platform",
"link": true
},
"node_modules/@bitwarden/platform-utils": {
"resolved": "libs/platform-utils",
"link": true
},
"node_modules/@bitwarden/sdk-internal": {
"version": "0.2.0-main.242",
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.242.tgz",

View File

@@ -48,6 +48,7 @@
"@bitwarden/node/*": ["./libs/node/src/*"],
"@bitwarden/nx-plugin": ["libs/nx-plugin/src/index.ts"],
"@bitwarden/platform": ["./libs/platform/src"],
"@bitwarden/platform-utils": ["libs/platform-utils/src/index.ts"],
"@bitwarden/platform/*": ["./libs/platform/src/*"],
"@bitwarden/send-ui": ["./libs/tools/send/send-ui/src"],
"@bitwarden/serialization": ["libs/serialization/src/index.ts"],