@tlog/shared 0.1.0
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 +141 -0
- package/dist/builders.d.ts +27 -0
- package/dist/builders.d.ts.map +1 -0
- package/dist/builders.js +53 -0
- package/dist/builders.js.map +1 -0
- package/dist/domain.d.ts +64 -0
- package/dist/domain.d.ts.map +1 -0
- package/dist/domain.js +40 -0
- package/dist/domain.js.map +1 -0
- package/dist/filter.d.ts +27 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +90 -0
- package/dist/filter.js.map +1 -0
- package/dist/id-index.d.ts +26 -0
- package/dist/id-index.d.ts.map +1 -0
- package/dist/id-index.js +99 -0
- package/dist/id-index.js.map +1 -0
- package/dist/index.d.ts +131 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/naming.d.ts +6 -0
- package/dist/naming.d.ts.map +1 -0
- package/dist/naming.js +32 -0
- package/dist/naming.js.map +1 -0
- package/dist/result.d.ts +25 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +10 -0
- package/dist/result.js.map +1 -0
- package/dist/schemas.d.ts +299 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +88 -0
- package/dist/schemas.js.map +1 -0
- package/dist/statistics.d.ts +20 -0
- package/dist/statistics.d.ts.map +1 -0
- package/dist/statistics.js +59 -0
- package/dist/statistics.js.map +1 -0
- package/dist/template.d.ts +23 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +51 -0
- package/dist/template.js.map +1 -0
- package/dist/validation.d.ts +14 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +77 -0
- package/dist/validation.js.map +1 -0
- package/dist/yaml-io.d.ts +10 -0
- package/dist/yaml-io.d.ts.map +1 -0
- package/dist/yaml-io.js +43 -0
- package/dist/yaml-io.js.map +1 -0
- package/package.json +28 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statistics.d.ts","sourceRoot":"","sources":["../src/statistics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAYD,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,aAAa,CAqBhE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAqC/F"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
function formatDate(date) {
|
|
2
|
+
return date.toISOString().slice(0, 10);
|
|
3
|
+
}
|
|
4
|
+
function addDays(date, days) {
|
|
5
|
+
const next = new Date(date);
|
|
6
|
+
next.setUTCDate(next.getUTCDate() + days);
|
|
7
|
+
return next;
|
|
8
|
+
}
|
|
9
|
+
export function summarizeStatus(cases) {
|
|
10
|
+
let todo = 0;
|
|
11
|
+
let doing = 0;
|
|
12
|
+
let done = 0;
|
|
13
|
+
for (const testCase of cases) {
|
|
14
|
+
if (testCase.status === "todo") {
|
|
15
|
+
todo += 1;
|
|
16
|
+
}
|
|
17
|
+
else if (testCase.status === "doing") {
|
|
18
|
+
doing += 1;
|
|
19
|
+
}
|
|
20
|
+
else if (testCase.status === "done") {
|
|
21
|
+
done += 1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
todo,
|
|
26
|
+
doing,
|
|
27
|
+
done,
|
|
28
|
+
total: cases.length
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function calculateBurndown(cases, start, end) {
|
|
32
|
+
const anomalies = [];
|
|
33
|
+
const summary = summarizeStatus(cases);
|
|
34
|
+
if (summary.total === 0) {
|
|
35
|
+
anomalies.push("no_target_cases");
|
|
36
|
+
}
|
|
37
|
+
if (start > end) {
|
|
38
|
+
anomalies.push("invalid_date_range");
|
|
39
|
+
return { summary, buckets: [], anomalies };
|
|
40
|
+
}
|
|
41
|
+
const startDate = new Date(`${start}T00:00:00.000Z`);
|
|
42
|
+
const endDate = new Date(`${end}T00:00:00.000Z`);
|
|
43
|
+
const days = Math.floor((endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1000)) + 1;
|
|
44
|
+
const doneCases = cases.filter((testCase) => testCase.status === "done");
|
|
45
|
+
const buckets = [];
|
|
46
|
+
for (let offset = 0; offset < days; offset += 1) {
|
|
47
|
+
const day = addDays(startDate, offset);
|
|
48
|
+
const dayText = formatDate(day);
|
|
49
|
+
const plannedCompleted = Math.min(summary.total, Math.ceil(((offset + 1) / days) * summary.total));
|
|
50
|
+
const actualCompleted = doneCases.filter((testCase) => testCase.completedDay !== null && testCase.completedDay <= dayText).length;
|
|
51
|
+
buckets.push({
|
|
52
|
+
date: dayText,
|
|
53
|
+
plannedCompleted,
|
|
54
|
+
actualCompleted
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return { summary, buckets, anomalies };
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=statistics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statistics.js","sourceRoot":"","sources":["../src/statistics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Suite, TestCase } from "./domain.js";
|
|
2
|
+
export interface TlogTemplate {
|
|
3
|
+
suite: Partial<Suite>;
|
|
4
|
+
testCase: Partial<TestCase>;
|
|
5
|
+
}
|
|
6
|
+
export declare function applyTemplateToSuite(base: Suite, template: TlogTemplate): Suite;
|
|
7
|
+
export declare function applyTemplateToCase(base: TestCase, template: TlogTemplate): TestCase;
|
|
8
|
+
export declare function applyTemplate(suiteInput: {
|
|
9
|
+
id: string;
|
|
10
|
+
title: string;
|
|
11
|
+
}, caseInput: {
|
|
12
|
+
id: string;
|
|
13
|
+
title: string;
|
|
14
|
+
}, template?: TlogTemplate): {
|
|
15
|
+
suite: Suite;
|
|
16
|
+
testCase: TestCase;
|
|
17
|
+
};
|
|
18
|
+
export declare function extractTemplateFromDirectory(rootDir: string): Promise<TlogTemplate>;
|
|
19
|
+
export declare function validateTemplate(template: TlogTemplate): {
|
|
20
|
+
valid: boolean;
|
|
21
|
+
errors: string[];
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKnD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC7B;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,GAAG,KAAK,CAM/E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,GAAG,QAAQ,CAOpF;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACzC,SAAS,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACxC,QAAQ,CAAC,EAAE,YAAY,GACtB;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAYtC;AAED,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CASzF;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAY7F"}
|
package/dist/template.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { readdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { buildDefaultCase, buildDefaultSuite } from "./builders.js";
|
|
4
|
+
import { readYamlFile } from "./yaml-io.js";
|
|
5
|
+
import { validateCase, validateSuite } from "./validation.js";
|
|
6
|
+
export function applyTemplateToSuite(base, template) {
|
|
7
|
+
return {
|
|
8
|
+
...base,
|
|
9
|
+
...template.suite,
|
|
10
|
+
duration: template.suite.duration ?? base.duration
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function applyTemplateToCase(base, template) {
|
|
14
|
+
return {
|
|
15
|
+
...base,
|
|
16
|
+
...template.testCase,
|
|
17
|
+
tests: template.testCase.tests ?? base.tests,
|
|
18
|
+
issues: template.testCase.issues ?? base.issues
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function applyTemplate(suiteInput, caseInput, template) {
|
|
22
|
+
const baseSuite = buildDefaultSuite(suiteInput);
|
|
23
|
+
const baseCase = buildDefaultCase(caseInput);
|
|
24
|
+
if (!template) {
|
|
25
|
+
return { suite: baseSuite, testCase: baseCase };
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
suite: applyTemplateToSuite(baseSuite, template),
|
|
29
|
+
testCase: applyTemplateToCase(baseCase, template)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export async function extractTemplateFromDirectory(rootDir) {
|
|
33
|
+
const entries = await readdir(rootDir, { withFileTypes: true });
|
|
34
|
+
const suiteFile = entries.find((entry) => entry.isFile() && entry.name === "index.yaml");
|
|
35
|
+
const caseFile = entries.find((entry) => entry.isFile() && entry.name.endsWith(".yaml") && entry.name !== "index.yaml");
|
|
36
|
+
const suite = suiteFile ? await readYamlFile(join(rootDir, suiteFile.name)) : {};
|
|
37
|
+
const testCase = caseFile ? await readYamlFile(join(rootDir, caseFile.name)) : {};
|
|
38
|
+
return { suite, testCase };
|
|
39
|
+
}
|
|
40
|
+
export function validateTemplate(template) {
|
|
41
|
+
const suiteCandidate = buildDefaultSuite({ id: "template-suite", title: "Template Suite" });
|
|
42
|
+
const caseCandidate = buildDefaultCase({ id: "template-case", title: "Template Case" });
|
|
43
|
+
const suiteResult = validateSuite(applyTemplateToSuite(suiteCandidate, template));
|
|
44
|
+
const caseResult = validateCase(applyTemplateToCase(caseCandidate, template));
|
|
45
|
+
const errors = [...suiteResult.errors, ...caseResult.errors].map((error) => `${error.path}: ${error.message}`);
|
|
46
|
+
return {
|
|
47
|
+
valid: errors.length === 0,
|
|
48
|
+
errors
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Suite, TestCase } from "./domain.js";
|
|
2
|
+
export interface ValidationDiagnostic {
|
|
3
|
+
path: string;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ValidationResult<T> {
|
|
7
|
+
ok: boolean;
|
|
8
|
+
data?: T;
|
|
9
|
+
errors: ValidationDiagnostic[];
|
|
10
|
+
warnings: ValidationDiagnostic[];
|
|
11
|
+
}
|
|
12
|
+
export declare function validateSuite(input: unknown): ValidationResult<Suite>;
|
|
13
|
+
export declare function validateCase(input: unknown): ValidationResult<TestCase>;
|
|
14
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC/B,QAAQ,EAAE,oBAAoB,EAAE,CAAC;CAClC;AAkED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAgBrE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAgBvE"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { suiteSchema, testCaseSchema } from "./schemas.js";
|
|
2
|
+
function formatPath(path) {
|
|
3
|
+
if (path.length === 0) {
|
|
4
|
+
return "$";
|
|
5
|
+
}
|
|
6
|
+
return path
|
|
7
|
+
.map((segment) => (typeof segment === "number" ? `[${segment}]` : segment))
|
|
8
|
+
.join(".")
|
|
9
|
+
.replace(".[", "[");
|
|
10
|
+
}
|
|
11
|
+
function mapZodErrors(error) {
|
|
12
|
+
return error.issues.map((issue) => ({
|
|
13
|
+
path: formatPath(issue.path),
|
|
14
|
+
message: issue.message
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
function pushArrayWarnings(warnings, value, path, message) {
|
|
18
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
19
|
+
warnings.push({ path, message });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function pushStringWarnings(warnings, value, path, message) {
|
|
23
|
+
if (typeof value === "string" && value.trim().length === 0) {
|
|
24
|
+
warnings.push({ path, message });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function buildSuiteWarnings(suite) {
|
|
28
|
+
const warnings = [];
|
|
29
|
+
pushArrayWarnings(warnings, suite.tags, "tags", "tags is empty");
|
|
30
|
+
pushArrayWarnings(warnings, suite.owners, "owners", "owners is empty");
|
|
31
|
+
pushArrayWarnings(warnings, suite.related, "related", "related is empty");
|
|
32
|
+
pushArrayWarnings(warnings, suite.remarks, "remarks", "remarks is empty");
|
|
33
|
+
pushStringWarnings(warnings, suite.description, "description", "description is empty");
|
|
34
|
+
return warnings;
|
|
35
|
+
}
|
|
36
|
+
function buildCaseWarnings(testCase) {
|
|
37
|
+
const warnings = [];
|
|
38
|
+
pushArrayWarnings(warnings, testCase.tags, "tags", "tags is empty");
|
|
39
|
+
pushArrayWarnings(warnings, testCase.operations, "operations", "operations is empty");
|
|
40
|
+
pushArrayWarnings(warnings, testCase.tests, "tests", "tests is empty");
|
|
41
|
+
pushArrayWarnings(warnings, testCase.issues, "issues", "issues is empty");
|
|
42
|
+
pushStringWarnings(warnings, testCase.description, "description", "description is empty");
|
|
43
|
+
return warnings;
|
|
44
|
+
}
|
|
45
|
+
export function validateSuite(input) {
|
|
46
|
+
const parsed = suiteSchema.safeParse(input);
|
|
47
|
+
if (!parsed.success) {
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
errors: mapZodErrors(parsed.error),
|
|
51
|
+
warnings: []
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
ok: true,
|
|
56
|
+
data: parsed.data,
|
|
57
|
+
errors: [],
|
|
58
|
+
warnings: buildSuiteWarnings(parsed.data)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function validateCase(input) {
|
|
62
|
+
const parsed = testCaseSchema.safeParse(input);
|
|
63
|
+
if (!parsed.success) {
|
|
64
|
+
return {
|
|
65
|
+
ok: false,
|
|
66
|
+
errors: mapZodErrors(parsed.error),
|
|
67
|
+
warnings: []
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
ok: true,
|
|
72
|
+
data: parsed.data,
|
|
73
|
+
errors: [],
|
|
74
|
+
warnings: buildCaseWarnings(parsed.data)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class TlogYamlParseError extends Error {
|
|
2
|
+
readonly line: number;
|
|
3
|
+
readonly column: number;
|
|
4
|
+
constructor(message: string, line: number, column: number);
|
|
5
|
+
}
|
|
6
|
+
export declare function parseYaml<T>(source: string): T;
|
|
7
|
+
export declare function stringifyYaml(value: unknown): string;
|
|
8
|
+
export declare function readYamlFile<T>(path: string): Promise<T>;
|
|
9
|
+
export declare function writeYamlFileAtomic(path: string, value: unknown): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=yaml-io.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-io.d.ts","sourceRoot":"","sources":["../src/yaml-io.ts"],"names":[],"mappings":"AAKA,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,MAAM,EAAE,MAAM,CAAC;gBAEnB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAM1D;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,CAY9C;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIpD;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAG9D;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAQrF"}
|
package/dist/yaml-io.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { parseDocument, stringify } from "yaml";
|
|
5
|
+
export class TlogYamlParseError extends Error {
|
|
6
|
+
line;
|
|
7
|
+
column;
|
|
8
|
+
constructor(message, line, column) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "TlogYamlParseError";
|
|
11
|
+
this.line = line;
|
|
12
|
+
this.column = column;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function parseYaml(source) {
|
|
16
|
+
const document = parseDocument(source, { prettyErrors: false });
|
|
17
|
+
const parseError = document.errors[0];
|
|
18
|
+
if (parseError) {
|
|
19
|
+
const linePos = parseError.linePos?.[0];
|
|
20
|
+
const line = linePos?.line ?? 1;
|
|
21
|
+
const column = linePos?.col ?? 1;
|
|
22
|
+
throw new TlogYamlParseError(parseError.message, line, column);
|
|
23
|
+
}
|
|
24
|
+
return document.toJS();
|
|
25
|
+
}
|
|
26
|
+
export function stringifyYaml(value) {
|
|
27
|
+
return stringify(value, {
|
|
28
|
+
lineWidth: 0
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export async function readYamlFile(path) {
|
|
32
|
+
const raw = await readFile(path, "utf8");
|
|
33
|
+
return parseYaml(raw);
|
|
34
|
+
}
|
|
35
|
+
export async function writeYamlFileAtomic(path, value) {
|
|
36
|
+
const content = stringifyYaml(value);
|
|
37
|
+
const parent = dirname(path);
|
|
38
|
+
await mkdir(parent, { recursive: true });
|
|
39
|
+
const tempPath = `${path}.${randomUUID()}.tmp`;
|
|
40
|
+
await writeFile(tempPath, content, "utf8");
|
|
41
|
+
await rename(tempPath, path);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=yaml-io.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-io.js","sourceRoot":"","sources":["../src/yaml-io.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEhD,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3B,IAAI,CAAS;IACb,MAAM,CAAS;IAE/B,YAAY,OAAe,EAAE,IAAY,EAAE,MAAc;QACvD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,MAAM,UAAU,SAAS,CAAI,MAAc;IACzC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAEtC,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;QACjC,MAAM,IAAI,kBAAkB,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAO,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,SAAS,CAAC,KAAK,EAAE;QACtB,SAAS,EAAE,CAAC;KACb,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,IAAY;IAChD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,OAAO,SAAS,CAAI,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAY,EAAE,KAAc;IACpE,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,UAAU,EAAE,MAAM,CAAC;IAC/C,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tlog/shared",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared TypeScript utilities for tlog",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc -p tsconfig.json",
|
|
20
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:coverage": "vitest run --coverage --coverage.reporter=lcov --coverage.reporter=text"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"yaml": "^2.8.2",
|
|
26
|
+
"zod": "^3.25.76"
|
|
27
|
+
}
|
|
28
|
+
}
|