From 565e890973b1d96544bb750fdd700d58f8dad088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Wed, 6 Jul 2022 11:46:04 +0200 Subject: [PATCH] feat: add time package --- .pnp.cjs | 42 ++-- ...s-time-npm-1.7.1-e6859705d5-ccb9c4af73.zip | Bin 9394 -> 0 bytes ...rotime-npm-2.1.0-111ed89518-6c23131fe4.zip | Bin 0 -> 2483 bytes packages/api-gateway/package.json | 2 +- packages/auth/package.json | 2 +- packages/files/package.json | 2 +- packages/scheduler/package.json | 2 +- packages/syncing-server/package.json | 2 +- packages/time/.eslintignore | 1 + packages/time/.eslintrc | 6 + packages/time/CHANGELOG.md | 182 ++++++++++++++++++ packages/time/jest.config.js | 11 ++ packages/time/linter.tsconfig.json | 4 + packages/time/package.json | 39 ++++ packages/time/src/Domain/Time/Time.ts | 4 + packages/time/src/Domain/Time/Timer.spec.ts | 111 +++++++++++ packages/time/src/Domain/Time/Timer.ts | 95 +++++++++ .../time/src/Domain/Time/TimerInterface.ts | 22 +++ packages/time/src/Domain/index.ts | 3 + packages/time/src/index.ts | 1 + packages/time/tsconfig.json | 11 ++ tsconfig.json | 3 + yarn.lock | 34 ++-- 23 files changed, 552 insertions(+), 27 deletions(-) delete mode 100644 .yarn/cache/@standardnotes-time-npm-1.7.1-e6859705d5-ccb9c4af73.zip create mode 100644 .yarn/cache/@types-microtime-npm-2.1.0-111ed89518-6c23131fe4.zip create mode 100644 packages/time/.eslintignore create mode 100644 packages/time/.eslintrc create mode 100644 packages/time/CHANGELOG.md create mode 100644 packages/time/jest.config.js create mode 100644 packages/time/linter.tsconfig.json create mode 100644 packages/time/package.json create mode 100644 packages/time/src/Domain/Time/Time.ts create mode 100644 packages/time/src/Domain/Time/Timer.spec.ts create mode 100644 packages/time/src/Domain/Time/Timer.ts create mode 100644 packages/time/src/Domain/Time/TimerInterface.ts create mode 100644 packages/time/src/Domain/index.ts create mode 100644 packages/time/src/index.ts create mode 100644 packages/time/tsconfig.json diff --git a/.pnp.cjs b/.pnp.cjs index d66258a1b..faa7910ef 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -59,6 +59,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { {\ "name": "@standardnotes/syncing-server",\ "reference": "workspace:packages/syncing-server"\ + },\ + {\ + "name": "@standardnotes/time",\ + "reference": "workspace:packages/time"\ }\ ],\ "enableTopLevelFallback": true,\ @@ -74,7 +78,8 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@standardnotes/scheduler-server", ["workspace:packages/scheduler"]],\ ["@standardnotes/security", ["workspace:packages/security"]],\ ["@standardnotes/server-monorepo", ["workspace:."]],\ - ["@standardnotes/syncing-server", ["workspace:packages/syncing-server"]]\ + ["@standardnotes/syncing-server", ["workspace:packages/syncing-server"]],\ + ["@standardnotes/time", ["workspace:packages/time"]]\ ],\ "fallbackPool": [\ ],\ @@ -2682,7 +2687,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@standardnotes/domain-events", "workspace:packages/domain-events"],\ ["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\ ["@standardnotes/security", "workspace:packages/security"],\ - ["@standardnotes/time", "npm:1.7.1"],\ + ["@standardnotes/time", "workspace:packages/time"],\ ["@types/cors", "npm:2.8.12"],\ ["@types/express", "npm:4.17.13"],\ ["@types/ioredis", "npm:4.28.10"],\ @@ -2745,7 +2750,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@standardnotes/settings", "npm:1.15.0"],\ ["@standardnotes/sncrypto-common", "npm:1.9.0"],\ ["@standardnotes/sncrypto-node", "npm:1.8.3"],\ - ["@standardnotes/time", "npm:1.7.1"],\ + ["@standardnotes/time", "workspace:packages/time"],\ ["@types/bcryptjs", "npm:2.4.2"],\ ["@types/cors", "npm:2.8.12"],\ ["@types/express", "npm:4.17.13"],\ @@ -2893,7 +2898,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@standardnotes/security", "workspace:packages/security"],\ ["@standardnotes/sncrypto-common", "npm:1.9.0"],\ ["@standardnotes/sncrypto-node", "npm:1.8.3"],\ - ["@standardnotes/time", "npm:1.7.1"],\ + ["@standardnotes/time", "workspace:packages/time"],\ ["@types/connect-busboy", "npm:1.0.0"],\ ["@types/cors", "npm:2.8.12"],\ ["@types/express", "npm:4.17.13"],\ @@ -2998,7 +3003,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@standardnotes/domain-events", "workspace:packages/domain-events"],\ ["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\ ["@standardnotes/predicates", "workspace:packages/predicates"],\ - ["@standardnotes/time", "npm:1.7.1"],\ + ["@standardnotes/time", "workspace:packages/time"],\ ["@types/ioredis", "npm:4.28.10"],\ ["@types/jest", "npm:28.1.4"],\ ["@types/newrelic", "npm:7.0.3"],\ @@ -3125,7 +3130,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@standardnotes/responses", "npm:1.6.39"],\ ["@standardnotes/security", "workspace:packages/security"],\ ["@standardnotes/settings", "npm:1.15.0"],\ - ["@standardnotes/time", "npm:1.7.1"],\ + ["@standardnotes/time", "workspace:packages/time"],\ ["@types/cors", "npm:2.8.12"],\ ["@types/dotenv", "npm:8.2.0"],\ ["@types/express", "npm:4.17.13"],\ @@ -3167,15 +3172,21 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["@standardnotes/time", [\ - ["npm:1.7.1", {\ - "packageLocation": "./.yarn/cache/@standardnotes-time-npm-1.7.1-e6859705d5-ccb9c4af73.zip/node_modules/@standardnotes/time/",\ + ["workspace:packages/time", {\ + "packageLocation": "./packages/time/",\ "packageDependencies": [\ - ["@standardnotes/time", "npm:1.7.1"],\ + ["@standardnotes/time", "workspace:packages/time"],\ + ["@types/jest", "npm:27.5.2"],\ + ["@types/microtime", "npm:2.1.0"],\ + ["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.30.5"],\ ["dayjs", "npm:1.11.3"],\ + ["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\ + ["jest", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:27.5.1"],\ ["microtime", "npm:3.1.0"],\ - ["reflect-metadata", "npm:0.1.13"]\ + ["reflect-metadata", "npm:0.1.13"],\ + ["ts-jest", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:27.1.5"]\ ],\ - "linkType": "HARD"\ + "linkType": "SOFT"\ }]\ ]],\ ["@standardnotes/utils", [\ @@ -3510,6 +3521,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/microtime", [\ + ["npm:2.1.0", {\ + "packageLocation": "./.yarn/cache/@types-microtime-npm-2.1.0-111ed89518-6c23131fe4.zip/node_modules/@types/microtime/",\ + "packageDependencies": [\ + ["@types/microtime", "npm:2.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/mime", [\ ["npm:1.3.2", {\ "packageLocation": "./.yarn/cache/@types-mime-npm-1.3.2-ea71878ab3-0493368244.zip/node_modules/@types/mime/",\ diff --git a/.yarn/cache/@standardnotes-time-npm-1.7.1-e6859705d5-ccb9c4af73.zip b/.yarn/cache/@standardnotes-time-npm-1.7.1-e6859705d5-ccb9c4af73.zip deleted file mode 100644 index 675bbb6c0851152de93bcd30becc28c7881d2f57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9394 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.0.0 <17.0.0" + }, + "description": "Utilities for time processing and calculation", + "main": "dist/src/index.js", + "types": "dist/src/index.d.ts", + "files": [ + "dist/src/**/*.js", + "dist/src/**/*.d.ts" + ], + "publishConfig": { + "access": "public" + }, + "author": "Standard Notes", + "license": "AGPL-3.0-or-later", + "scripts": { + "clean": "rm -fr dist", + "prebuild": "yarn clean", + "build": "tsc -p tsconfig.json", + "lint": "eslint . --ext .ts", + "test:unit": "jest spec --coverage" + }, + "dependencies": { + "dayjs": "^1.10.8", + "microtime": "^3.1.0", + "reflect-metadata": "^0.1.13" + }, + "devDependencies": { + "@types/jest": "^27.4.1", + "@types/microtime": "^2.1.0", + "@typescript-eslint/eslint-plugin": "^5.30.0", + "eslint-plugin-prettier": "^4.2.1", + "jest": "^27.5.1", + "ts-jest": "^27.1.3" + } +} diff --git a/packages/time/src/Domain/Time/Time.ts b/packages/time/src/Domain/Time/Time.ts new file mode 100644 index 000000000..3a55c1016 --- /dev/null +++ b/packages/time/src/Domain/Time/Time.ts @@ -0,0 +1,4 @@ +export enum Time { + MicrosecondsInASecond = 1_000_000, + MicrosecondsInAMillisecond = 1_000, +} diff --git a/packages/time/src/Domain/Time/Timer.spec.ts b/packages/time/src/Domain/Time/Timer.spec.ts new file mode 100644 index 000000000..813d66c1c --- /dev/null +++ b/packages/time/src/Domain/Time/Timer.spec.ts @@ -0,0 +1,111 @@ +import 'reflect-metadata' + +import { Timer } from './Timer' + +describe('Timer', () => { + const createTimer = () => new Timer() + + it('should return a timestamp in microseconds', () => { + const timestamp = createTimer().getTimestampInMicroseconds() + expect(`${timestamp}`.length).toEqual(16) + }) + + it('should return a timestamp in seconds', () => { + const timestamp = createTimer().getTimestampInSeconds() + expect(`${timestamp}`.length).toEqual(10) + }) + + it('should return a utc date', () => { + const date = createTimer().getUTCDate() + expect(date).toBeInstanceOf(Date) + }) + + it('should return a utc date n days ago', () => { + const date = createTimer().getUTCDate() + const dateNDaysAgo = createTimer().getUTCDateNDaysAgo(4) + + expect(+date - +dateNDaysAgo >= 4 * 24 * 3600).toBeTruthy() + }) + + it('should return a utc date n days ahead', () => { + const date = createTimer().getUTCDate() + const dateNDaysAhead = createTimer().getUTCDateNDaysAhead(4) + + expect(+dateNDaysAhead - +date >= 4 * 24 * 3600).toBeTruthy() + }) + + it('should calculate days difference between now and a given date', () => { + const dateNDaysAgo = createTimer().getUTCDateNDaysAgo(4) + + expect(createTimer().dateWasNDaysAgo(dateNDaysAgo)).toEqual(4) + }) + + it('should return a utc date n hours ago', () => { + const date = createTimer().getUTCDate() + const dateNHoursAgo = createTimer().getUTCDateNHoursAgo(4) + + expect(+date - +dateNHoursAgo >= 4 * 3600).toBeTruthy() + }) + + it('should return a utc date n hours ahead', () => { + const date = createTimer().getUTCDate() + const dateNHoursAhead = createTimer().getUTCDateNHoursAhead(4) + + expect(+dateNHoursAhead - +date >= 4 * 3600).toBeTruthy() + }) + + it('should convert a date to milliseconds', () => { + const timestamp = createTimer().convertDateToMilliseconds(new Date(Date.UTC(2021, 2, 29, 12, 13, 45))) + expect(timestamp).toEqual(1617020025000) + }) + + it('should convert a date to microseconds', () => { + const timestamp = createTimer().convertDateToMicroseconds(new Date(Date.UTC(2021, 2, 29, 8, 0, 5, 233))) + expect(timestamp).toEqual(1617004805000000) + }) + + it('should convert a date to iso string', () => { + const isoString = createTimer().convertDateToISOString(new Date(Date.UTC(2021, 2, 29, 8, 0, 5))) + expect(isoString).toEqual('2021-03-29T08:00:05.000Z') + }) + + it('should convert a string date to microseconds', () => { + const timestamp = createTimer().convertStringDateToMicroseconds('2021-03-29 08:00:05.233Z') + expect(timestamp).toEqual(1617004805233000) + }) + + it('should convert a string date to seconds', () => { + const timestamp = createTimer().convertStringDateToSeconds('2021-03-29 08:00:05.233Z') + expect(timestamp).toEqual(1617004805) + }) + + it('should convert microseconds to string date', () => { + expect(createTimer().convertMicrosecondsToStringDate(1617004805233123)).toEqual('2021-03-29T08:00:05.233123Z') + }) + + it('should convert a string date to milliseconds', () => { + const timestamp = createTimer().convertStringDateToMilliseconds('Mon Mar 29 2021 12:13:45 GMT+0200') + expect(timestamp).toEqual(1617012825000) + }) + + it('should convert a string date to date', () => { + const date = createTimer().convertStringDateToDate('Mon Mar 29 2021 12:13:45 GMT+0200') + expect(date).toEqual(new Date(1617012825000)) + }) + + it('should convert microseconds to date', () => { + expect(createTimer().convertMicrosecondsToDate(1617004805233123)).toEqual(new Date('2021-03-29T08:00:05.233123Z')) + }) + + it('should convert microseconds to milliseconds', () => { + expect(createTimer().convertMicrosecondsToMilliseconds(1616164633241312)).toEqual(1616164633241) + }) + + it('should convert microseconds to seconds', () => { + expect(createTimer().convertMicrosecondsToSeconds(1616164633241312)).toEqual(1616164633) + }) + + it('should format date', () => { + expect(createTimer().formatDate(new Date('2021-03-29T08:00:05.233123Z'), 'YYYY-MM-DD')).toEqual('2021-03-29') + }) +}) diff --git a/packages/time/src/Domain/Time/Timer.ts b/packages/time/src/Domain/Time/Timer.ts new file mode 100644 index 000000000..078bda4a9 --- /dev/null +++ b/packages/time/src/Domain/Time/Timer.ts @@ -0,0 +1,95 @@ +import * as dayjs from 'dayjs' +import * as utc from 'dayjs/plugin/utc' +import * as microtime from 'microtime' +import { Time } from './Time' +import { TimerInterface } from './TimerInterface' + +export class Timer implements TimerInterface { + constructor() { + dayjs.extend(utc) + } + + formatDate(date: Date, format: string): string { + return dayjs.utc(date).format(format) + } + + convertDateToMilliseconds(date: Date): number { + return this.convertStringDateToMilliseconds(date.toString()) + } + + convertDateToMicroseconds(date: Date): number { + return this.convertStringDateToMicroseconds(date.toString()) + } + + convertMicrosecondsToSeconds(microseconds: number): number { + return Math.floor(microseconds / Time.MicrosecondsInASecond) + } + + getTimestampInMicroseconds(): number { + return microtime.now() + } + + getTimestampInSeconds(): number { + return this.convertMicrosecondsToSeconds(this.getTimestampInMicroseconds()) + } + + getUTCDate(): Date { + return dayjs.utc().toDate() + } + + getUTCDateNDaysAgo(n: number): Date { + return dayjs.utc().subtract(n, 'days').toDate() + } + + getUTCDateNDaysAhead(n: number): Date { + return dayjs.utc().add(n, 'days').toDate() + } + + getUTCDateNHoursAgo(n: number): Date { + return dayjs.utc().subtract(n, 'hours').toDate() + } + + getUTCDateNHoursAhead(n: number): Date { + return dayjs.utc().add(n, 'hours').toDate() + } + + convertStringDateToDate(date: string): Date { + return dayjs.utc(date).toDate() + } + + convertDateToISOString(date: Date): string { + return dayjs.utc(date).toISOString() + } + + dateWasNDaysAgo(date: Date): number { + return dayjs.utc().diff(date, 'days') + } + + convertStringDateToMicroseconds(date: string): number { + return this.convertStringDateToMilliseconds(date) * Time.MicrosecondsInAMillisecond + } + + convertStringDateToMilliseconds(date: string): number { + return dayjs.utc(date).valueOf() + } + + convertStringDateToSeconds(date: string): number { + return this.convertMicrosecondsToSeconds(this.convertStringDateToMicroseconds(date)) + } + + convertMicrosecondsToMilliseconds(microseconds: number): number { + return Math.floor(microseconds / Time.MicrosecondsInAMillisecond) + } + + convertMicrosecondsToStringDate(microseconds: number): string { + const milliseconds = this.convertMicrosecondsToMilliseconds(microseconds) + + const microsecondsString = microseconds.toString().substring(13) + + return dayjs.utc(milliseconds).format(`YYYY-MM-DDTHH:mm:ss.SSS${microsecondsString}[Z]`) + } + + convertMicrosecondsToDate(microseconds: number): Date { + return this.convertStringDateToDate(this.convertMicrosecondsToStringDate(microseconds)) + } +} diff --git a/packages/time/src/Domain/Time/TimerInterface.ts b/packages/time/src/Domain/Time/TimerInterface.ts new file mode 100644 index 000000000..d570bcfc5 --- /dev/null +++ b/packages/time/src/Domain/Time/TimerInterface.ts @@ -0,0 +1,22 @@ +export interface TimerInterface { + getTimestampInMicroseconds(): number + getTimestampInSeconds(): number + getUTCDate(): Date + getUTCDateNDaysAgo(n: number): Date + getUTCDateNDaysAhead(n: number): Date + getUTCDateNHoursAgo(n: number): Date + getUTCDateNHoursAhead(n: number): Date + convertDateToMilliseconds(date: Date): number + convertDateToMicroseconds(date: Date): number + convertDateToISOString(date: Date): string + convertStringDateToDate(date: string): Date + convertStringDateToMicroseconds(date: string): number + convertStringDateToMilliseconds(date: string): number + convertStringDateToSeconds(date: string): number + convertMicrosecondsToMilliseconds(microseconds: number): number + convertMicrosecondsToSeconds(microseconds: number): number + convertMicrosecondsToStringDate(microseconds: number): string + convertMicrosecondsToDate(microseconds: number): Date + formatDate(date: Date, format: string): string + dateWasNDaysAgo(date: Date): number +} diff --git a/packages/time/src/Domain/index.ts b/packages/time/src/Domain/index.ts new file mode 100644 index 000000000..acc1c966b --- /dev/null +++ b/packages/time/src/Domain/index.ts @@ -0,0 +1,3 @@ +export * from './Time/Time' +export * from './Time/Timer' +export * from './Time/TimerInterface' diff --git a/packages/time/src/index.ts b/packages/time/src/index.ts new file mode 100644 index 000000000..920deacdb --- /dev/null +++ b/packages/time/src/index.ts @@ -0,0 +1 @@ +export * from './Domain' diff --git a/packages/time/tsconfig.json b/packages/time/tsconfig.json new file mode 100644 index 000000000..8d2588d39 --- /dev/null +++ b/packages/time/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true, + "outDir": "./dist", + }, + "include": [ + "src/**/*" + ], + "references": [] +} diff --git a/tsconfig.json b/tsconfig.json index fe8f9e745..3f2452d83 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -51,6 +51,9 @@ }, { "path": "./packages/syncing-server" + }, + { + "path": "./packages/time" } ] } diff --git a/yarn.lock b/yarn.lock index 37909f5bb..bab691acf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1964,7 +1964,7 @@ __metadata: "@standardnotes/domain-events": "workspace:*" "@standardnotes/domain-events-infra": "workspace:*" "@standardnotes/security": "workspace:*" - "@standardnotes/time": ^1.7.1 + "@standardnotes/time": "workspace:*" "@types/cors": ^2.8.9 "@types/express": ^4.17.11 "@types/ioredis": ^4.28.10 @@ -2028,7 +2028,7 @@ __metadata: "@standardnotes/settings": ^1.15.0 "@standardnotes/sncrypto-common": ^1.9.0 "@standardnotes/sncrypto-node": ^1.8.3 - "@standardnotes/time": ^1.7.1 + "@standardnotes/time": "workspace:*" "@types/bcryptjs": ^2.4.2 "@types/cors": ^2.8.9 "@types/express": ^4.17.11 @@ -2175,7 +2175,7 @@ __metadata: "@standardnotes/security": "workspace:*" "@standardnotes/sncrypto-common": ^1.9.0 "@standardnotes/sncrypto-node": ^1.8.3 - "@standardnotes/time": ^1.7.1 + "@standardnotes/time": "workspace:*" "@types/connect-busboy": ^1.0.0 "@types/cors": ^2.8.9 "@types/express": ^4.17.11 @@ -2273,7 +2273,7 @@ __metadata: "@standardnotes/domain-events": "workspace:*" "@standardnotes/domain-events-infra": "workspace:*" "@standardnotes/predicates": "workspace:*" - "@standardnotes/time": ^1.7.1 + "@standardnotes/time": "workspace:*" "@types/ioredis": ^4.28.10 "@types/jest": ^28.1.2 "@types/newrelic": ^7.0.3 @@ -2388,7 +2388,7 @@ __metadata: "@standardnotes/responses": ^1.6.39 "@standardnotes/security": "workspace:*" "@standardnotes/settings": 1.15.0 - "@standardnotes/time": ^1.7.1 + "@standardnotes/time": "workspace:*" "@types/cors": ^2.8.9 "@types/dotenv": ^8.2.0 "@types/express": ^4.17.9 @@ -2428,16 +2428,21 @@ __metadata: languageName: unknown linkType: soft -"@standardnotes/time@npm:^1.7.1": - version: 1.7.1 - resolution: "@standardnotes/time@npm:1.7.1" +"@standardnotes/time@workspace:*, @standardnotes/time@workspace:packages/time": + version: 0.0.0-use.local + resolution: "@standardnotes/time@workspace:packages/time" dependencies: + "@types/jest": ^27.4.1 + "@types/microtime": ^2.1.0 + "@typescript-eslint/eslint-plugin": ^5.30.0 dayjs: ^1.10.8 + eslint-plugin-prettier: ^4.2.1 + jest: ^27.5.1 microtime: ^3.1.0 reflect-metadata: ^0.1.13 - checksum: ccb9c4af73d2c77d5b1cfea480930e3a30e87fb426eee3c60eb0ce0f259fa5c1f9b1b29fdc52c72d321821791e3bdc141e4af0bfc668662863012743332c5407 - languageName: node - linkType: hard + ts-jest: ^27.1.3 + languageName: unknown + linkType: soft "@standardnotes/utils@npm:^1.4.6, @standardnotes/utils@npm:^1.6.12": version: 1.6.12 @@ -2731,6 +2736,13 @@ __metadata: languageName: node linkType: hard +"@types/microtime@npm:^2.1.0": + version: 2.1.0 + resolution: "@types/microtime@npm:2.1.0" + checksum: 6c23131fe46fd1b059c8d7e474a5ab60e703cf0f4a6ab0e3dbe36f1d394359fb4712dca696ff891b15482855465e6febc16acc56eaaf500864283d758b0c8dca + languageName: node + linkType: hard + "@types/mime@npm:^1": version: 1.3.2 resolution: "@types/mime@npm:1.3.2"