Restructure files

This commit is contained in:
aet 2021-11-11 23:56:06 -05:00
parent b4b21561ed
commit bdd46a530c
29 changed files with 271 additions and 179 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
drafts
node_modules node_modules
mochawesome-report mochawesome-report
lib lib

View File

@ -39,6 +39,7 @@
"sass": "^1.43.2", "sass": "^1.43.2",
"sinon": "^11.1.2", "sinon": "^11.1.2",
"sinon-chai": "^3.7.0", "sinon-chai": "^3.7.0",
"tslib": "^2.3.1",
"ts-node": "^10.2.1", "ts-node": "^10.2.1",
"tsconfig-paths": "^3.11.0", "tsconfig-paths": "^3.11.0",
"typescript": "^4.4.3" "typescript": "^4.4.3"

View File

@ -0,0 +1,6 @@
{
"name": "opvault-adapters",
"dependencies": {
"opvault.js": "*"
}
}

View File

@ -1,5 +1,5 @@
import { Buffer } from "buffer" import { Buffer } from "buffer"
import type { IAdapter, IFileSystem } from "./index" import type { IAdapter, IFileSystem } from "opvault.js/src/adapter"
function normalize(path: string) { function normalize(path: string) {
return path.replace(/^\//, "") return path.replace(/^\//, "")

View File

@ -1,5 +1,5 @@
import { Buffer } from "buffer" import { Buffer } from "buffer"
import type { IAdapter, IFileSystem } from "./index" import type { IAdapter, IFileSystem } from "opvault.js/src/adapter"
export class FileSystem implements IFileSystem { export class FileSystem implements IFileSystem {
private paths = new Set<string>() private paths = new Set<string>()

View File

@ -4,7 +4,7 @@
"version": "0.0.1", "version": "0.0.1",
"license": "LGPL-3.0-or-later", "license": "LGPL-3.0-or-later",
"scripts": { "scripts": {
"build": "rollup -c; cp src/adapters/index.d.ts lib/adapters/; prettier --write lib >/dev/null", "build": "rollup -c; prettier --write lib >/dev/null",
"build:docs": "typedoc --out docs src/index.ts --excludePrivate" "build:docs": "typedoc --out docs src/index.ts --excludePrivate"
}, },
"dependencies": { "dependencies": {

View File

@ -8,7 +8,6 @@ import { dependencies } from "./package.json"
export default () => ({ export default () => ({
input: { input: {
index: "./src/index.ts", index: "./src/index.ts",
"adapters/node": "./src/adapters/node.ts",
}, },
external: builtinModules.concat(Object.keys(dependencies)), external: builtinModules.concat(Object.keys(dependencies)),
output: { output: {

View File

@ -1,3 +1,6 @@
import { promises as fs, existsSync } from "fs"
import { webcrypto } from "crypto"
/** /**
* An object that implements basic file system functionalities. * An object that implements basic file system functionalities.
*/ */
@ -53,3 +56,19 @@ export interface IAdapter {
*/ */
subtle: SubtleCrypto subtle: SubtleCrypto
} }
/**
* Default Node.js adapter. This can be used while using `opvault.js`
* in a Node.js environment.
*/
export const nodeAdapter: IAdapter = {
fs: {
readFile: path => fs.readFile(path, "utf-8"),
readBuffer: path => fs.readFile(path),
writeFile: fs.writeFile,
readdir: fs.readdir,
isDirectory: async path => fs.stat(path).then(x => x.isDirectory()),
exists: async path => existsSync(path),
},
subtle: (webcrypto as any).subtle,
}

View File

@ -1,20 +0,0 @@
import { promises as fs, existsSync } from "fs"
import { webcrypto } from "crypto"
import type { IAdapter } from "./index"
/**
* Default Node.js adapter. This can be used while using `opvault.js`
* in a Node.js environment.
*/
export const nodeAdapter: IAdapter = {
fs: {
readFile: path => fs.readFile(path, "utf-8"),
readBuffer: path => fs.readFile(path),
writeFile: fs.writeFile,
readdir: fs.readdir,
isDirectory: async path => fs.stat(path).then(x => x.isDirectory()),
exists: async path => existsSync(path),
},
subtle: (webcrypto as any).subtle,
}

View File

@ -1,12 +1,12 @@
import { Buffer } from "buffer" import { Buffer } from "buffer"
import { decryptData } from "../decipher" import { decryptData } from "./decipher"
import type { IAdapter } from "../adapters" import type { IAdapter } from "./adapter"
import { createEventEmitter } from "../ee" import { createEventEmitter } from "./ee"
import { HMACAssertionError } from "../errors" import { HMACAssertionError } from "./errors"
import type { i18n } from "../i18n" import type { i18n } from "./i18n"
import type { ItemDetails, Overview, Profile } from "../types" import type { ItemDetails, Overview, Profile } from "./types"
import { setIfAbsent } from "../util" import { setIfAbsent } from "./util"
import type { EncryptedItem } from "./item" import type { EncryptedItem } from "./models/item"
/** Encryption and MAC */ /** Encryption and MAC */
export interface Cipher { export interface Cipher {

View File

@ -1,6 +1,6 @@
import { resolve, extname, basename } from "path" import { resolve, extname, basename } from "path"
import invariant from "tiny-invariant" import invariant from "tiny-invariant"
import type { IFileSystem } from "./adapters" import type { IFileSystem } from "./adapter"
import { once } from "./util" import { once } from "./util"
export type OnePasswordFileManager = ReturnType<typeof OnePasswordFileManager> export type OnePasswordFileManager = ReturnType<typeof OnePasswordFileManager>

View File

@ -1,6 +1,6 @@
import { resolve } from "path" import { resolve } from "path"
import { Vault } from "./models/vault" import { Vault } from "./models/vault"
import type { IAdapter } from "./adapters" import type { IAdapter } from "./adapter"
import { asyncMap } from "./util" import { asyncMap } from "./util"
export type { Vault } from "./models/vault" export type { Vault } from "./models/vault"
@ -18,7 +18,7 @@ interface IOptions {
/** /**
* Adapter used to interact with the file system and cryptography modules * Adapter used to interact with the file system and cryptography modules
*/ */
adapter?: IAdapter adapter?: IAdapter | Promise<IAdapter>
} }
/** /**
@ -26,11 +26,11 @@ interface IOptions {
*/ */
export class OnePassword { export class OnePassword {
readonly #path: string readonly #path: string
readonly #adapter: IAdapter readonly #adapter: IAdapter | Promise<IAdapter>
constructor({ constructor({
path, path,
adapter = process.browser ? null : require("./adapters/node").nodeAdapter, adapter = process.browser ? null! : import("./adapter").then(x => x.nodeAdapter),
}: IOptions) { }: IOptions) {
this.#adapter = adapter this.#adapter = adapter
this.#path = path this.#path = path
@ -40,11 +40,11 @@ export class OnePassword {
* @returns A list of names of profiles of the current vault. * @returns A list of names of profiles of the current vault.
*/ */
async getProfileNames() { async getProfileNames() {
const [fs, path] = [this.#adapter.fs, this.#path] const { fs } = await this.#adapter
const children = await fs.readdir(path) const children = await fs.readdir(this.#path)
const profiles: string[] = [] const profiles: string[] = []
await asyncMap(children, async child => { await asyncMap(children, async child => {
const fullPath = resolve(path, child) const fullPath = resolve(this.#path, child)
if ( if (
(await fs.isDirectory(fullPath)) && (await fs.isDirectory(fullPath)) &&
(await fs.exists(resolve(fullPath, "profile.js"))) (await fs.exists(resolve(fullPath, "profile.js")))
@ -59,6 +59,6 @@ export class OnePassword {
* @returns A OnePassword Vault instance. * @returns A OnePassword Vault instance.
*/ */
async getProfile(profileName: string) { async getProfile(profileName: string) {
return await Vault.of(this.#path, profileName, this.#adapter) return await Vault.of(this.#path, profileName, await this.#adapter)
} }
} }

View File

@ -1,5 +1,5 @@
import { Buffer } from "buffer" import { Buffer } from "buffer"
import type { Crypto } from "./crypto" import type { Crypto } from "../crypto"
import { invariant } from "../errors" import { invariant } from "../errors"
type integer = number type integer = number

View File

@ -1,5 +1,5 @@
import type { ItemDetails, Overview } from "../types" import type { ItemDetails, Overview } from "../types"
import type { Crypto } from "./crypto" import type { Crypto } from "../crypto"
import { Attachment } from "./attachment" import { Attachment } from "./attachment"
import { NotUnlockedError } from "../errors" import { NotUnlockedError } from "../errors"
import type { Category } from "../models" import type { Category } from "../models"
@ -8,7 +8,7 @@ export interface EncryptedItem {
category: string // "001" category: string // "001"
/** Unix seconds */ /** Unix seconds */
created: integer created: integer
d: string // "b3BkYXRhMbt" d: string // details, bass64
folder: string // 32 chars folder: string // 32 chars
hmac: string // base64 hmac: string // base64
k: string // base64 k: string // base64

View File

@ -1,9 +1,9 @@
import type { IAdapter } from "../adapters" import type { IAdapter } from "../adapter"
import { HMACAssertionError, invariant } from "../errors" import { HMACAssertionError, invariant } from "../errors"
import { OnePasswordFileManager } from "../fs" import { OnePasswordFileManager } from "../fs"
import { i18n } from "../i18n" import { i18n } from "../i18n"
import type { EncryptedItem } from "./item" import type { EncryptedItem } from "./item"
import { Crypto } from "./crypto" import { Crypto } from "../crypto"
import { Item } from "./item" import { Item } from "./item"
import type { Profile } from "../types" import type { Profile } from "../types"
import { WeakValueMap } from "../weakMap" import { WeakValueMap } from "../weakMap"

View File

@ -130,6 +130,9 @@ export interface ItemDetails {
}[] }[]
/** Web form fields */ /** Web form fields */
fields?: ItemField[] fields?: ItemField[]
/** Plain password items */
backupKeys?: string[]
password?: string
} }
export interface Folder { export interface Folder {

View File

@ -12,8 +12,13 @@ fs.writeFileSync(
dtsPath, dtsPath,
`type Translation = Record<string, string>; `type Translation = Record<string, string>;
declare const exportee: { declare const exportee: {
${Object.keys(json) ${Object.entries(json)
.map(x => `${x}: Translation;`) .map(
([category, value]) =>
`${category}: {\n${Object.keys(value)
.map(key => ` ${key}: Translation;`)
.join("\n")}\n };`
)
.join("\n ")} .join("\n ")}
}; };
export default exportee; export default exportee;

View File

@ -1,6 +1,7 @@
import styled from "@emotion/styled" import styled from "@emotion/styled"
import type { Attachment, AttachmentMetadata, Item, ItemField } from "opvault.js" import type { Attachment, AttachmentMetadata, Item, ItemField } from "opvault.js"
import { useEffect, useState } from "react" import type { ItemDetails } from "opvault.js/src/types"
import { memo, useEffect, useState } from "react"
import { useTranslate } from "../i18n" import { useTranslate } from "../i18n"
import { CategoryIcon } from "./CategoryIcon" import { CategoryIcon } from "./CategoryIcon"
import { ItemDates } from "./ItemDates" import { ItemDates } from "./ItemDates"
@ -10,6 +11,7 @@ import {
FieldTitle, FieldTitle,
ItemDetailsFieldView, ItemDetailsFieldView,
} from "./ItemField" } from "./ItemField"
import { PasswordFieldView } from "./ItemFieldValue"
import { ItemWarning } from "./ItemWarning" import { ItemWarning } from "./ItemWarning"
interface ItemViewProps { interface ItemViewProps {
@ -57,6 +59,22 @@ const AttachmentContainer = styled.div`
margin: 5px 0; margin: 5px 0;
` `
const SectionsView: React.FC<{ sections?: ItemDetails["sections"] }> = ({ sections }) =>
sections?.length ? (
<div style={{ marginBottom: 20 }}>
{sections
.filter(s => s.fields?.some(x => x.v != null))
.map((section, i) => (
<div key={i}>
{section.title != null && <SectionTitle>{section.title}</SectionTitle>}
{section.fields?.map((field, j) => (
<ItemFieldView key={j} field={field} />
))}
</div>
))}
</div>
) : null
const FieldsView: React.FC<{ fields?: ItemField[] }> = ({ fields }) => const FieldsView: React.FC<{ fields?: ItemField[] }> = ({ fields }) =>
fields?.length ? ( fields?.length ? (
<div style={{ marginBottom: 20 }}> <div style={{ marginBottom: 20 }}>
@ -71,7 +89,7 @@ const TagsView: React.FC<{ tags?: string[] }> = ({ tags }) => {
if (!tags?.length) return null if (!tags?.length) return null
return ( return (
<ExtraField> <ExtraField>
<FieldTitle>{t.noun_tags}</FieldTitle> <FieldTitle>{t.noun.tags}</FieldTitle>
<div> <div>
{tags.map((tag, i) => ( {tags.map((tag, i) => (
<Tag key={i}>{tag}</Tag> <Tag key={i}>{tag}</Tag>
@ -81,7 +99,18 @@ const TagsView: React.FC<{ tags?: string[] }> = ({ tags }) => {
) )
} }
export const ItemView: React.FC<ItemViewProps> = ({ className, item }) => ( const JSONView = memo<{ item: Item }>(({ item }) => (
<details>
<summary>JSON</summary>
<pre>
{JSON.stringify({ overview: item.overview, details: item.details }, null, 2)}
</pre>
</details>
))
export const ItemView: React.FC<ItemViewProps> = ({ className, item }) => {
const t = useTranslate()
return (
<Container className={className}> <Container className={className}>
<Inner> <Inner>
<ItemWarning item={item} /> <ItemWarning item={item} />
@ -90,26 +119,11 @@ export const ItemView: React.FC<ItemViewProps> = ({ className, item }) => (
<Icon category={item.category} /> <Icon category={item.category} />
<ItemTitle>{item.overview.title}</ItemTitle> <ItemTitle>{item.overview.title}</ItemTitle>
</Header> </Header>
<details>
<summary>JSON</summary>
<pre>
{JSON.stringify({ overview: item.overview, details: item.details }, null, 2)}
</pre>
</details>
<div style={{ marginBottom: 20 }}> <JSONView item={item} />
{item.details.sections <div style={{ height: 10 }}></div>
?.filter(s => s.fields?.some(x => x.v != null))
.map((section, i) => (
<div key={i}>
{section.title != null && <SectionTitle>{section.title}</SectionTitle>}
{section.fields?.map((field, j) => (
<ItemFieldView key={j} field={field} />
))}
</div>
))}
</div>
<SectionsView sections={item.details.sections} />
<FieldsView fields={item.details.fields} /> <FieldsView fields={item.details.fields} />
{item.details.notesPlain != null && ( {item.details.notesPlain != null && (
@ -121,6 +135,13 @@ export const ItemView: React.FC<ItemViewProps> = ({ className, item }) => (
</ExtraField> </ExtraField>
)} )}
{item.details.password != null && (
<ExtraField>
<FieldTitle>{t.label.password}</FieldTitle>
<PasswordFieldView field={{ v: item.details.password }} />
</ExtraField>
)}
<TagsView tags={item.overview.tags} /> <TagsView tags={item.overview.tags} />
{item.attachments.length > 0 && ( {item.attachments.length > 0 && (
@ -140,6 +161,7 @@ export const ItemView: React.FC<ItemViewProps> = ({ className, item }) => (
</Inner> </Inner>
</Container> </Container>
) )
}
function AttachmentView({ file }: { file: Attachment }) { function AttachmentView({ file }: { file: Attachment }) {
const [metadata, setMetadata] = useState<AttachmentMetadata>() const [metadata, setMetadata] = useState<AttachmentMetadata>()

View File

@ -14,10 +14,10 @@ export const ItemDates: React.FC<{ item: Item }> = ({ item }) => {
return ( return (
<Container> <Container>
<div> <div>
{t.label_last_updated}: {new Date(item.updatedAt).toLocaleString()} {t.label.last_updated}: {new Date(item.updatedAt).toLocaleString()}
</div> </div>
<div> <div>
{t.label_created_at}: {new Date(item.createdAt).toLocaleString()} {t.label.created_at}: {new Date(item.createdAt).toLocaleString()}
</div> </div>
</Container> </Container>
) )

View File

@ -7,7 +7,7 @@ const Container = styled.menu`
box-shadow: #0004 0px 1px 4px; box-shadow: #0004 0px 1px 4px;
left: 99%; left: 99%;
margin-block-start: 0; margin-block-start: 0;
min-width: 120px; min-width: 150px;
padding-inline-start: 0; padding-inline-start: 0;
position: absolute; position: absolute;
top: 0; top: 0;
@ -39,6 +39,7 @@ const Item = styled.div`
height: 2.5em; height: 2.5em;
align-items: center; align-items: center;
padding-left: 1em; padding-left: 1em;
padding-right: 5px;
position: relative; position: relative;
&:hover { &:hover {
background-color: #ddd; background-color: #ddd;

View File

@ -9,8 +9,10 @@ import { useItemFieldContextMenu } from "./ItemFieldContextMenu"
const Container = styled.div`` const Container = styled.div``
export { Password as PasswordFieldView }
const Password: React.FC<{ const Password: React.FC<{
field: ItemSection.Concealed field: Pick<ItemSection.Concealed, "v">
}> = ({ field }) => { }> = ({ field }) => {
const [show, setShow] = useState(false) const [show, setShow] = useState(false)
const [bigText, showBigText] = useState(false) const [bigText, showBigText] = useState(false)

View File

@ -1,7 +1,7 @@
import { createContext, memo, useContext, useEffect, useMemo, useState } from "react" import { createContext, memo, useContext, useEffect, useMemo, useState } from "react"
import texts from "./texts.yml" import texts from "./texts.yml"
type Keys = keyof typeof texts const categories = Object.keys(texts)
const ALLOWED = new Set(["en", "fr"]) const ALLOWED = new Set(["en", "fr"])
const LOCALSTORAGE_KEY = "preferred-locale" const LOCALSTORAGE_KEY = "preferred-locale"
@ -40,21 +40,29 @@ export function useTranslate() {
const { locale } = useContext(LocaleContext) const { locale } = useContext(LocaleContext)
const t = useMemo( const t = useMemo(
() => () =>
Object.fromEntries(
categories.map(category => [
category,
new Proxy( new Proxy(
{}, {},
{ {
get(_, p: string) { get(_, p: string) {
const obj = (texts as any)[category]
if ( if (
process.env.NODE_ENV === "development" && process.env.NODE_ENV === "development" &&
!Object.prototype.hasOwnProperty.call(texts, p) !Object.prototype.hasOwnProperty.call(obj, p)
) { ) {
throw new Error(`t.${p} does not exist.`) throw new Error(`t.${p} does not exist.`)
} }
return (texts as any)[p][locale] return obj[p][locale]
}, },
} }
),
])
) as { ) as {
[key in Keys]: string [category in keyof typeof texts]: {
[key in keyof typeof texts[category]]: string
}
}, },
[locale] [locale]
) )

View File

@ -1,40 +1,51 @@
# /* spellchecker: disable */ # /* spellchecker: disable */
label_choose_a_vault: label:
choose_a_vault:
en: Pick a vault en: Pick a vault
fr: Choisir un coffre fr: Choisir un coffre
label_no_vault_selected: no_vault_selected:
en: No vault is selected. en: No vault is selected.
fr: Aucun coffre nest sélectionné. fr: Aucun coffre nest sélectionné.
label_last_updated: last_updated:
en: Last Updated en: Last Updated
fr: Dernière modification fr: Dernière modification
label_created_at: created_at:
en: Created At en: Created At
fr: Créé fr: Créé
label_password_placeholder: password_placeholder:
en: Master Password en: Master Password
fr: Mot de passe principal fr: Mot de passe principal
noun_vault: username:
en: Username
fr: Nom dutilisateur
password:
en: Password
fr: Mot de passe
noun:
vault:
en: vault en: vault
fr: coffre fr: coffre
noun_tags: tags:
en: tags en: tags
fr: mots-clés fr: mots-clés
action_lock: action:
lock:
en: Lock en: Lock
fr: Vérouiller fr: Vérouiller
action_unlock: unlock:
en: Unlock en: Unlock
fr: Déverouiller fr: Déverouiller
action_go_back: go_back:
en: Back en: Back
fr: Revenir fr: Revenir

View File

@ -102,17 +102,17 @@ export const Unlock: React.FC<{
return ( return (
<Container> <Container>
<div style={{ marginBottom: 10 }}> <div style={{ marginBottom: 10 }}>
<BackButton onClick={onReturn} title={t.action_go_back}> <BackButton onClick={onReturn} title={t.action.go_back}>
<IoMdArrowRoundBack /> <IoMdArrowRoundBack />
</BackButton> </BackButton>
<Select <Select
title={t.noun_vault} title={t.noun.vault}
value={profile} value={profile}
onChange={e => setProfile(e.currentTarget.value)} onChange={e => setProfile(e.currentTarget.value)}
> >
{profiles.map(p => ( {profiles.map(p => (
<option key={p} value={p}> <option key={p} value={p}>
{t.noun_vault}: {p} {t.noun.vault}: {p}
</option> </option>
))} ))}
</Select> </Select>
@ -122,14 +122,14 @@ export const Unlock: React.FC<{
type="password" type="password"
value={password} value={password}
onChange={e => setPassword(e.currentTarget.value)} onChange={e => setPassword(e.currentTarget.value)}
placeholder={t.label_password_placeholder} placeholder={t.label.password_placeholder}
onKeyUp={onKeyUp} onKeyUp={onKeyUp}
/> />
<Submit <Submit
type="submit" type="submit"
disabled={!profile || !password} disabled={!profile || !password}
onClick={unlock} onClick={unlock}
title={t.action_unlock} title={t.action.unlock}
> >
<FaUnlock /> <FaUnlock />
</Submit> </Submit>

View File

@ -88,25 +88,36 @@ export const VaultView: React.FC<{ vault: Vault; onLock(): void }> = ({
arrayFrom(vault.values()).then(setItems) arrayFrom(vault.values()).then(setItems)
}, [vault]) }, [vault])
const filtered = useMemo( const filtered = useMemo(() => {
() => const items = sortedItem.filter(x => x.category !== Category.Tombstone)
sortedItem let res: Item[] = items
.filter(x => x.category !== Category.Tombstone) if (search) {
.filter( res = []
search for (const x of items) {
? x => const compare = Math.max(
stringCompare(search, x.overview.title) || stringCompare(search, x.overview.title),
stringCompare(search, x.overview.ainfo) stringCompare(search, x.overview.ainfo)
: () => true ) as CompareResult
), switch (compare) {
[sortedItem, search] case CompareResult.NoMatch:
) continue
case CompareResult.Includes:
res.push(x)
break
case CompareResult.Equals:
res.unshift(x)
break
}
}
}
return res
}, [sortedItem, search])
return ( return (
<Container> <Container>
<ListContainer className={scrollbar}> <ListContainer className={scrollbar}>
<div style={{ margin: "10px 10px", display: "flex" }}> <div style={{ margin: "10px 10px", display: "flex" }}>
<LockButton onClick={onLock} title={t.action_lock}> <LockButton onClick={onLock} title={t.action.lock}>
<FiLock /> <FiLock />
</LockButton> </LockButton>
<SearchContainer> <SearchContainer>
@ -147,8 +158,20 @@ async function arrayFrom<T>(generator: AsyncGenerator<T, void, unknown>) {
return list return list
} }
function stringCompare(search: string, source?: string) { enum CompareResult {
if (!search) return true NoMatch,
if (!source) return false Includes,
return source.toLocaleLowerCase().includes(search.toLocaleLowerCase()) Equals,
}
function stringCompare(search: string, source?: string) {
if (!search) return CompareResult.Includes
if (!source) return CompareResult.NoMatch
source = source.toLocaleLowerCase()
search = search.toLocaleUpperCase()
const includes = source.includes(search.toLocaleLowerCase())
if (includes) {
return source.length === search.length ? CompareResult.Equals : CompareResult.Includes
}
return CompareResult.NoMatch
} }

View File

@ -87,8 +87,8 @@ const PickOPVault: React.FC<{
return ( return (
<PickOPVaultContainer> <PickOPVaultContainer>
<button onClick={onClick}>{t.label_choose_a_vault}</button> <button onClick={onClick}>{t.label.choose_a_vault}</button>
<PickOPVaultInfo>{t.label_no_vault_selected}</PickOPVaultInfo> <PickOPVaultInfo>{t.label.no_vault_selected}</PickOPVaultInfo>
</PickOPVaultContainer> </PickOPVaultContainer>
) )
} }

11
pnpm-lock.yaml generated
View File

@ -35,6 +35,7 @@ importers:
sinon-chai: ^3.7.0 sinon-chai: ^3.7.0
ts-node: ^10.2.1 ts-node: ^10.2.1
tsconfig-paths: ^3.11.0 tsconfig-paths: ^3.11.0
tslib: ^2.3.1
typescript: ^4.4.3 typescript: ^4.4.3
devDependencies: devDependencies:
'@types/chai': 4.2.22 '@types/chai': 4.2.22
@ -68,8 +69,15 @@ importers:
sinon-chai: 3.7.0_chai@4.3.4+sinon@11.1.2 sinon-chai: 3.7.0_chai@4.3.4+sinon@11.1.2
ts-node: 10.2.1_8304ecd715830f7c190b4d1dea90b100 ts-node: 10.2.1_8304ecd715830f7c190b4d1dea90b100
tsconfig-paths: 3.11.0 tsconfig-paths: 3.11.0
tslib: 2.3.1
typescript: 4.4.3 typescript: 4.4.3
packages/adapters:
specifiers:
opvault.js: '*'
dependencies:
opvault.js: link:../opvault.js
packages/opvault.js: packages/opvault.js:
specifiers: specifiers:
'@rollup/plugin-json': ^4.1.0 '@rollup/plugin-json': ^4.1.0
@ -137,6 +145,9 @@ importers:
typescript: 4.4.3 typescript: 4.4.3
vite: 2.6.13_sass@1.43.4 vite: 2.6.13_sass@1.43.4
packages/web/dist:
specifiers: {}
packages: packages:
/7zip-bin/5.1.1: /7zip-bin/5.1.1:

View File

@ -2,8 +2,8 @@ import { resolve } from "path";
import { describe, it, beforeEach } from "mocha"; import { describe, it, beforeEach } from "mocha";
import { expect } from "chai"; import { expect } from "chai";
import type { Vault } from "../packages/opvault.js/index"; import type { Vault } from "../packages/opvault.js/src/index";
import { OnePassword } from "../packages/opvault.js/index"; import { OnePassword } from "../packages/opvault.js/src/index";
describe("OnePassword", () => { describe("OnePassword", () => {
const freddy = resolve(__dirname, "../freddy-2013-12-04.opvault"); const freddy = resolve(__dirname, "../freddy-2013-12-04.opvault");

View File

@ -1,7 +1,7 @@
import { describe, it } from "mocha"; import { describe, it } from "mocha";
import { expect } from "chai"; import { expect } from "chai";
import { WeakValueMap } from "../packages/opvault.js/weakMap"; import { WeakValueMap } from "../packages/opvault.js/src/weakMap";
declare const gc: () => void; declare const gc: () => void;