obsidian-testing-framework 0.0.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 +32 -0
- package/lib/fixtures.d.ts +9 -0
- package/lib/fixtures.js +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +120 -0
- package/lib/util.d.ts +82 -0
- package/lib/util.js +135 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# the Obsidian Testing Framework
|
|
2
|
+
|
|
3
|
+
## what is this?
|
|
4
|
+
|
|
5
|
+
this is a library that (finally!) lets you end-to-end test your obsidian plugins.
|
|
6
|
+
it uses [playwright](https://playwright.dev/docs/intro) to interact with obsidian,
|
|
7
|
+
which is an Electron app under the hood.
|
|
8
|
+
|
|
9
|
+
## great! how do i use it?
|
|
10
|
+
|
|
11
|
+
### basic usage
|
|
12
|
+
```ts
|
|
13
|
+
import {test} from "obsidian-testing-library";
|
|
14
|
+
test('obsidian app url', async ({ page }) => {
|
|
15
|
+
console.log(page.url());
|
|
16
|
+
expect(/obsidian\.md/i.test(page.url())).toBeTruthy()
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
### usage with the `app` instance
|
|
20
|
+
```ts
|
|
21
|
+
test("idk", async({page}) => {
|
|
22
|
+
console.log("idk")
|
|
23
|
+
let tfile = await doWithApp(page, async (app) => {
|
|
24
|
+
return app.metadataCache.getFirstLinkpathDest("Welcome", "/");
|
|
25
|
+
});
|
|
26
|
+
expect(tfile.basename).toEqual("Welcome")
|
|
27
|
+
})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### other utilities
|
|
31
|
+
|
|
32
|
+
see `src/util.ts` for the currently included utilities and their documentation.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ElectronApplication, JSHandle, Page } from "playwright";
|
|
2
|
+
import { ObsidianTestingConfig } from "./index.js";
|
|
3
|
+
import { App } from "obsidian";
|
|
4
|
+
export interface ObsidianTestFixtures {
|
|
5
|
+
electronApp: ElectronApplication;
|
|
6
|
+
page: Page;
|
|
7
|
+
obsidian: ObsidianTestingConfig;
|
|
8
|
+
appHandle: JSHandle<App>;
|
|
9
|
+
}
|
package/lib/fixtures.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ObsidianTestFixtures } from "./fixtures.js";
|
|
2
|
+
export interface ObsidianTestingConfig {
|
|
3
|
+
vault?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function getExe(): string;
|
|
6
|
+
export declare const test: import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions & ObsidianTestFixtures, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions>;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { test as base } from "@playwright/test";
|
|
2
|
+
import { _electron as electron } from "playwright";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
5
|
+
import { pageUtils, waitForIndexingComplete } from "./util.js";
|
|
6
|
+
import { randomBytes } from "crypto";
|
|
7
|
+
export function getExe() {
|
|
8
|
+
checkToy();
|
|
9
|
+
if (process.platform == "win32") {
|
|
10
|
+
return path.join(process.env.LOCALAPPDATA, "Obsidian", "Resources", "app.asar");
|
|
11
|
+
}
|
|
12
|
+
const possibleDirs = [
|
|
13
|
+
"/opt/Obsidian",
|
|
14
|
+
"/usr/lib/Obsidian",
|
|
15
|
+
"/opt/obsidian",
|
|
16
|
+
"/usr/lib/obsidian",
|
|
17
|
+
"/var/lib/flatpak/app/md.obsidian.Obsidian/current/active/files",
|
|
18
|
+
"/snap/obsidian/current",
|
|
19
|
+
];
|
|
20
|
+
for (let i = 0; i < possibleDirs.length; i++) {
|
|
21
|
+
if (existsSync(possibleDirs[i])) {
|
|
22
|
+
// console.log(execSync(`ls -l ${possibleDirs[i]}`).toString());
|
|
23
|
+
return path.join(possibleDirs[i], "resources", "app.asar");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return "";
|
|
27
|
+
}
|
|
28
|
+
function checkToy() {
|
|
29
|
+
if (process.platform == "darwin") {
|
|
30
|
+
throw new Error("use a non-toy operating system, dumbass");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function generateVaultConfig(vault) {
|
|
34
|
+
const vaultHash = randomBytes(8).toString("hex").toLocaleLowerCase();
|
|
35
|
+
let configLocation;
|
|
36
|
+
console.log("vault is", vault, existsSync(vault));
|
|
37
|
+
checkToy();
|
|
38
|
+
if (process.platform == "win32") {
|
|
39
|
+
configLocation = path.join(`${process.env.APPDATA}`, "Obsidian");
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
configLocation = path.join(`${process.env.XDG_CONFIG_HOME}`, "obsidian");
|
|
43
|
+
try {
|
|
44
|
+
mkdirSync(configLocation, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
catch (e) { }
|
|
47
|
+
}
|
|
48
|
+
const obsidianConfigFile = path.join(configLocation, "obsidian.json");
|
|
49
|
+
if (!existsSync(obsidianConfigFile)) {
|
|
50
|
+
writeFileSync(obsidianConfigFile, JSON.stringify({ vaults: {} }));
|
|
51
|
+
}
|
|
52
|
+
const json = JSON.parse(readFileSync(obsidianConfigFile).toString());
|
|
53
|
+
if (!Object.values(json.vaults).some((a) => a.path === vault)) {
|
|
54
|
+
json.vaults[vaultHash] = {
|
|
55
|
+
path: vault,
|
|
56
|
+
ts: Date.now(),
|
|
57
|
+
};
|
|
58
|
+
writeFileSync(obsidianConfigFile, JSON.stringify(json));
|
|
59
|
+
writeFileSync(path.join(configLocation, `${vaultHash}.json`), "{}");
|
|
60
|
+
return vaultHash;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return Object.entries(json.vaults).find(a => a[1].path === vault)[0];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const obsidianTestFixtures = {
|
|
67
|
+
electronApp: [
|
|
68
|
+
async ({ obsidian: { vault } }, run) => {
|
|
69
|
+
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = "true";
|
|
70
|
+
console.log("asar located at:", getExe());
|
|
71
|
+
let uriArg = "";
|
|
72
|
+
if (vault) {
|
|
73
|
+
let id = generateVaultConfig(vault);
|
|
74
|
+
if (!!id) {
|
|
75
|
+
uriArg = `obsidian://open?vault=${encodeURIComponent(id)}`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const electronApp = await electron.launch({
|
|
79
|
+
timeout: 60000,
|
|
80
|
+
args: [getExe(), uriArg].filter((a) => !!a),
|
|
81
|
+
});
|
|
82
|
+
electronApp.on("console", async (msg) => {
|
|
83
|
+
console.log(...(await Promise.all(msg.args().map((a) => a.jsonValue()))));
|
|
84
|
+
});
|
|
85
|
+
await electronApp.waitForEvent("window");
|
|
86
|
+
await run(electronApp);
|
|
87
|
+
await electronApp.close();
|
|
88
|
+
},
|
|
89
|
+
{ timeout: 60000 },
|
|
90
|
+
],
|
|
91
|
+
page: [
|
|
92
|
+
async ({ electronApp }, run) => {
|
|
93
|
+
const windows = electronApp.windows();
|
|
94
|
+
// console.log("windows", windows);
|
|
95
|
+
let page = windows[windows.length - 1];
|
|
96
|
+
await page.waitForLoadState("domcontentloaded");
|
|
97
|
+
try {
|
|
98
|
+
await waitForIndexingComplete(page);
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
console.warn("timed out waiting for metadata cache. continuing...");
|
|
102
|
+
}
|
|
103
|
+
for (let fn of Object.entries(pageUtils)) {
|
|
104
|
+
await page.exposeFunction(fn[0], fn[1]);
|
|
105
|
+
}
|
|
106
|
+
page.on("pageerror", exc => {
|
|
107
|
+
console.error("EXCEPTION");
|
|
108
|
+
console.error(exc);
|
|
109
|
+
});
|
|
110
|
+
page.on("console", async (msg) => {
|
|
111
|
+
console.log(...(await Promise.all(msg.args().map((a) => a.jsonValue()))));
|
|
112
|
+
});
|
|
113
|
+
await run(page);
|
|
114
|
+
},
|
|
115
|
+
{ timeout: 60000 },
|
|
116
|
+
],
|
|
117
|
+
obsidian: [{}, { option: true }],
|
|
118
|
+
};
|
|
119
|
+
// @ts-ignore some error about a string type now having `undefined` as part of it's union
|
|
120
|
+
export const test = base.extend(obsidianTestFixtures);
|
package/lib/util.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { App, TFile } from "obsidian";
|
|
2
|
+
import { Page } from "playwright";
|
|
3
|
+
/**
|
|
4
|
+
* asserts that the contents of the file at `path` is equal to `expectedContent`.
|
|
5
|
+
*
|
|
6
|
+
* @export
|
|
7
|
+
* @param {Page} page - a Playwright page
|
|
8
|
+
* @param {string} path - the file to check
|
|
9
|
+
* @param {string} expectedContent - the expected content
|
|
10
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
11
|
+
*/
|
|
12
|
+
export declare function assertFileEquals(page: Page, path: string, expectedContent: string, cached?: boolean): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* asserts that the line at `lineNumber` in the file at `path` is equal
|
|
15
|
+
* to `expectedContent`.
|
|
16
|
+
*
|
|
17
|
+
* @export
|
|
18
|
+
* @param {Page} page - a Playwright page
|
|
19
|
+
* @param {string} path - the file to check
|
|
20
|
+
* @param {number} lineNumber - the line in the file to check (0-based)
|
|
21
|
+
* @param {string} expectedContent - the expected content
|
|
22
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
23
|
+
*/
|
|
24
|
+
export declare function assertLineEquals(page: Page, path: string, lineNumber: number, expectedContent: string, cached?: boolean): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* asserts that the lines in the specified range are equal to the expected
|
|
27
|
+
* content.
|
|
28
|
+
*
|
|
29
|
+
* @export
|
|
30
|
+
* @param {Page} page - a Playwright page
|
|
31
|
+
* @param {string} path - the file to check
|
|
32
|
+
* @param {number} start - the start of the desired line range (0-based)
|
|
33
|
+
* @param {number} end - the end of the desired line range (1-based)
|
|
34
|
+
* @param {string} expected - the expected content
|
|
35
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
36
|
+
*/
|
|
37
|
+
export declare function assertLinesEqual(page: Page, path: string, start: number, end: number, expected: string, cached?: boolean): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* asserts all lines in the given range match a regex.
|
|
40
|
+
*
|
|
41
|
+
* @export
|
|
42
|
+
* @param {Page} page - a Playwright page
|
|
43
|
+
* @param {string} path - the file to check
|
|
44
|
+
* @param {number} start - the start of the desired line range (0-based)
|
|
45
|
+
* @param {number} end - the end of the desired line range (1-based)
|
|
46
|
+
* @param {RegExp} regex - the regex to test against
|
|
47
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
48
|
+
*/
|
|
49
|
+
export declare function assertLinesMatch(page: Page, path: string, start: number, end: number, regex: RegExp, cached?: boolean): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* reads the file at `path` and returns its contents
|
|
52
|
+
*
|
|
53
|
+
* @export
|
|
54
|
+
* @param {Page} page - a Playwright page
|
|
55
|
+
* @param {string} path the file to read
|
|
56
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
57
|
+
* @return {Promise<string>} the file's contents
|
|
58
|
+
*/
|
|
59
|
+
export declare function readFile(page: Page, path: string, cached?: boolean): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* do something with the global `App` instance,
|
|
62
|
+
* and return the result of that invocation
|
|
63
|
+
*
|
|
64
|
+
* @export
|
|
65
|
+
* @typeParam - T the return type of the callback
|
|
66
|
+
* @typeParam - A the additional argument(s) to pass
|
|
67
|
+
* @param {Page} page - a Playwright page
|
|
68
|
+
* @param {((a: App, args?: A) => T | Promise<T>)} callback - the function to execute
|
|
69
|
+
* @param {A} [args] - optional arguments to pass to the callback
|
|
70
|
+
* @return {Promise<T>} a promise containing `callback`'s return value (if any)
|
|
71
|
+
*/
|
|
72
|
+
export declare function doWithApp<T = unknown, A = any>(page: Page, callback: (a: App, args?: A) => T | Promise<T>, args?: A): Promise<T>;
|
|
73
|
+
/**
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
export declare function waitForIndexingComplete(page: Page): Promise<unknown>;
|
|
77
|
+
/**
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
80
|
+
export declare const pageUtils: {
|
|
81
|
+
getFile: (file: string) => TFile;
|
|
82
|
+
};
|
package/lib/util.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { expect } from "@playwright/test";
|
|
2
|
+
/**
|
|
3
|
+
* asserts that the contents of the file at `path` is equal to `expectedContent`.
|
|
4
|
+
*
|
|
5
|
+
* @export
|
|
6
|
+
* @param {Page} page - a Playwright page
|
|
7
|
+
* @param {string} path - the file to check
|
|
8
|
+
* @param {string} expectedContent - the expected content
|
|
9
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
10
|
+
*/
|
|
11
|
+
export async function assertFileEquals(page, path, expectedContent, cached = true) {
|
|
12
|
+
const fileContent = await readFile(page, path, cached);
|
|
13
|
+
expect(fileContent).toEqual(normalizeEOL(expectedContent));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* asserts that the line at `lineNumber` in the file at `path` is equal
|
|
17
|
+
* to `expectedContent`.
|
|
18
|
+
*
|
|
19
|
+
* @export
|
|
20
|
+
* @param {Page} page - a Playwright page
|
|
21
|
+
* @param {string} path - the file to check
|
|
22
|
+
* @param {number} lineNumber - the line in the file to check (0-based)
|
|
23
|
+
* @param {string} expectedContent - the expected content
|
|
24
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
25
|
+
*/
|
|
26
|
+
export async function assertLineEquals(page, path, lineNumber, expectedContent, cached = true) {
|
|
27
|
+
const fileContent = await readFile(page, path, cached);
|
|
28
|
+
expect(fileContent.split("\n")[lineNumber]).toEqual(normalizeEOL(expectedContent));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* asserts that the lines in the specified range are equal to the expected
|
|
32
|
+
* content.
|
|
33
|
+
*
|
|
34
|
+
* @export
|
|
35
|
+
* @param {Page} page - a Playwright page
|
|
36
|
+
* @param {string} path - the file to check
|
|
37
|
+
* @param {number} start - the start of the desired line range (0-based)
|
|
38
|
+
* @param {number} end - the end of the desired line range (1-based)
|
|
39
|
+
* @param {string} expected - the expected content
|
|
40
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
41
|
+
*/
|
|
42
|
+
export async function assertLinesEqual(page, path, start, end, expected, cached = true) {
|
|
43
|
+
const fileContent = await readFile(page, path, cached);
|
|
44
|
+
const lines = fileContent.split("\n").slice(start, end);
|
|
45
|
+
const expectedLines = normalizeEOL(expected).split("\n");
|
|
46
|
+
expect(lines.every((l, i) => l == expectedLines[i])).toEqual(true);
|
|
47
|
+
}
|
|
48
|
+
const getFile = (file) => {
|
|
49
|
+
let f = window.app.vault.getFileByPath(file);
|
|
50
|
+
if (!f) {
|
|
51
|
+
throw new Error("File does not exist in vault.");
|
|
52
|
+
}
|
|
53
|
+
return f;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* asserts all lines in the given range match a regex.
|
|
57
|
+
*
|
|
58
|
+
* @export
|
|
59
|
+
* @param {Page} page - a Playwright page
|
|
60
|
+
* @param {string} path - the file to check
|
|
61
|
+
* @param {number} start - the start of the desired line range (0-based)
|
|
62
|
+
* @param {number} end - the end of the desired line range (1-based)
|
|
63
|
+
* @param {RegExp} regex - the regex to test against
|
|
64
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
65
|
+
*/
|
|
66
|
+
export async function assertLinesMatch(page, path, start, end, regex, cached = true) {
|
|
67
|
+
const fileContent = await readFile(page, path, cached);
|
|
68
|
+
const lines = fileContent.split("\n").slice(start, end);
|
|
69
|
+
expect(lines.every(l => regex.test(l))).toEqual(true);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* reads the file at `path` and returns its contents
|
|
73
|
+
*
|
|
74
|
+
* @export
|
|
75
|
+
* @param {Page} page - a Playwright page
|
|
76
|
+
* @param {string} path the file to read
|
|
77
|
+
* @param {boolean} [cached=true] - whether to use `app.vault.cachedRead`
|
|
78
|
+
* @return {Promise<string>} the file's contents
|
|
79
|
+
*/
|
|
80
|
+
export async function readFile(page, path, cached = true) {
|
|
81
|
+
const fn = getFile.toString();
|
|
82
|
+
return normalizeEOL(await doWithApp(page, async (app, args) => {
|
|
83
|
+
const gf = eval(`(${args.getFile})`);
|
|
84
|
+
const file = gf(args.path);
|
|
85
|
+
return await (args.cached ? app.vault.cachedRead(file) : app.vault.read(file));
|
|
86
|
+
}, { path, cached, getFile: fn }));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* do something with the global `App` instance,
|
|
90
|
+
* and return the result of that invocation
|
|
91
|
+
*
|
|
92
|
+
* @export
|
|
93
|
+
* @typeParam - T the return type of the callback
|
|
94
|
+
* @typeParam - A the additional argument(s) to pass
|
|
95
|
+
* @param {Page} page - a Playwright page
|
|
96
|
+
* @param {((a: App, args?: A) => T | Promise<T>)} callback - the function to execute
|
|
97
|
+
* @param {A} [args] - optional arguments to pass to the callback
|
|
98
|
+
* @return {Promise<T>} a promise containing `callback`'s return value (if any)
|
|
99
|
+
*/
|
|
100
|
+
export async function doWithApp(page, callback, args) {
|
|
101
|
+
const cbStr = callback.toString();
|
|
102
|
+
return await page.evaluate(async ({ __callback: cb, args }) => {
|
|
103
|
+
const func = new Function("args", `return ((${cb}))(window.app, args)`);
|
|
104
|
+
return await func(args);
|
|
105
|
+
}, { __callback: cbStr, args });
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* @internal
|
|
109
|
+
*/
|
|
110
|
+
export function waitForIndexingComplete(page) {
|
|
111
|
+
return page.evaluateHandle("window.app").then((appHandle) => {
|
|
112
|
+
return appHandle.evaluate((app) => {
|
|
113
|
+
return new Promise((res2, rej2) => {
|
|
114
|
+
let resolved = false;
|
|
115
|
+
app.metadataCache.on("resolved", () => {
|
|
116
|
+
res2(null);
|
|
117
|
+
resolved = true;
|
|
118
|
+
});
|
|
119
|
+
setTimeout(() => !resolved && rej2("timeout"), 10000);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* @internal
|
|
126
|
+
*/
|
|
127
|
+
function normalizeEOL(str) {
|
|
128
|
+
return str.split(/\r\n|\r|\n/).join("\n");
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* @internal
|
|
132
|
+
*/
|
|
133
|
+
export const pageUtils = {
|
|
134
|
+
getFile,
|
|
135
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "obsidian-testing-framework",
|
|
3
|
+
"packageManager": "yarn@4.5.1",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"@codemirror/language": "https://github.com/lishid/cm-language",
|
|
6
|
+
"@codemirror/state": "^6.0.1",
|
|
7
|
+
"@codemirror/view": "^6.0.1",
|
|
8
|
+
"@playwright/test": "^1.48.1",
|
|
9
|
+
"asar": "^3.2.0",
|
|
10
|
+
"electron": "^33.0.2",
|
|
11
|
+
"obsidian": "latest",
|
|
12
|
+
"playwright": "^1.48.1",
|
|
13
|
+
"tmp": "^0.2.3",
|
|
14
|
+
"typescript": "^5.6.3",
|
|
15
|
+
"xvfb-maybe": "^0.2.1"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"./lib",
|
|
19
|
+
"../../README.md"
|
|
20
|
+
],
|
|
21
|
+
"readme": "",
|
|
22
|
+
"version": "0.0.4",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./lib/index.d.ts",
|
|
26
|
+
"default": "./lib/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./utils": {
|
|
29
|
+
"types": "./lib/util.d.ts",
|
|
30
|
+
"default": "./lib/util.js"
|
|
31
|
+
},
|
|
32
|
+
"./fixture": {
|
|
33
|
+
"types": "./lib/fixtures.d.ts",
|
|
34
|
+
"default": "./lib/fixtures.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"main": "./lib/index.js",
|
|
38
|
+
"typings": "./lib/index.d.ts",
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc",
|
|
41
|
+
"lint": "tslint -c tslint.json src/**/*.ts",
|
|
42
|
+
"prepublishOnly": "rm README.md && cp ../../README.md . && rimraf lib && npm run build"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/tmp": "^0",
|
|
46
|
+
"rimraf": "^6.0.1",
|
|
47
|
+
"vitest": "^2.1.3"
|
|
48
|
+
},
|
|
49
|
+
"type": "module"
|
|
50
|
+
}
|