@verbatra/sdk 0.4.4 → 0.5.0-next.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/dist/index.cjs +229 -100
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +216 -57
- package/dist/index.d.ts +216 -57
- package/dist/index.js +227 -102
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { existsSync } from 'fs';
|
|
2
|
-
import { resolve, join,
|
|
2
|
+
import { dirname, resolve, join, basename, extname } from 'path';
|
|
3
3
|
import { cosmiconfig } from 'cosmiconfig';
|
|
4
4
|
import { TypeScriptLoader } from 'cosmiconfig-typescript-loader';
|
|
5
|
+
import { randomUUID } from 'crypto';
|
|
6
|
+
import { access, writeFile, rename, rm, open } from 'fs/promises';
|
|
5
7
|
import { z } from 'zod';
|
|
6
8
|
import Anthropic from '@anthropic-ai/sdk';
|
|
7
9
|
import * as deepl from 'deepl-node';
|
|
@@ -9,8 +11,6 @@ import { createRequire } from 'module';
|
|
|
9
11
|
import log from 'loglevel';
|
|
10
12
|
import { GoogleGenAI } from '@google/genai';
|
|
11
13
|
import OpenAI from 'openai';
|
|
12
|
-
import { randomUUID } from 'crypto';
|
|
13
|
-
import { access, writeFile, rename, rm, open } from 'fs/promises';
|
|
14
14
|
import { parse as parse$1, TYPE } from '@formatjs/icu-messageformat-parser';
|
|
15
15
|
import { XMLSerializer, DOMParser } from '@xmldom/xmldom';
|
|
16
16
|
import { stringify, parse } from 'yaml';
|
|
@@ -38,6 +38,155 @@ var SdkError = class extends Error {
|
|
|
38
38
|
this.code = code;
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
+
async function readBoundedUtf8(handle, size) {
|
|
42
|
+
const buffer = Buffer.allocUnsafe(size);
|
|
43
|
+
let offset = 0;
|
|
44
|
+
while (offset < size) {
|
|
45
|
+
const { bytesRead } = await handle.read(buffer, offset, size - offset, offset);
|
|
46
|
+
if (bytesRead === 0) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
offset += bytesRead;
|
|
50
|
+
}
|
|
51
|
+
return buffer.toString("utf8", 0, offset);
|
|
52
|
+
}
|
|
53
|
+
async function readBounded(path, maxBytes) {
|
|
54
|
+
let handle;
|
|
55
|
+
try {
|
|
56
|
+
handle = await open(path, "r");
|
|
57
|
+
} catch {
|
|
58
|
+
return { kind: "missing" };
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const info = await handle.stat();
|
|
62
|
+
if (!info.isFile()) {
|
|
63
|
+
return { kind: "missing" };
|
|
64
|
+
}
|
|
65
|
+
if (info.size > maxBytes) {
|
|
66
|
+
return { kind: "too-large" };
|
|
67
|
+
}
|
|
68
|
+
return { kind: "ok", content: await readBoundedUtf8(handle, info.size) };
|
|
69
|
+
} finally {
|
|
70
|
+
await handle.close();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function readBoundedBytesInto(handle, size) {
|
|
74
|
+
const buffer = Buffer.allocUnsafeSlow(size);
|
|
75
|
+
let offset = 0;
|
|
76
|
+
while (offset < size) {
|
|
77
|
+
const { bytesRead } = await handle.read(buffer, offset, size - offset, offset);
|
|
78
|
+
if (bytesRead === 0) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
offset += bytesRead;
|
|
82
|
+
}
|
|
83
|
+
return new Uint8Array(buffer.buffer, buffer.byteOffset, offset);
|
|
84
|
+
}
|
|
85
|
+
async function readBoundedBytes(path, maxBytes) {
|
|
86
|
+
let handle;
|
|
87
|
+
try {
|
|
88
|
+
handle = await open(path, "r");
|
|
89
|
+
} catch {
|
|
90
|
+
return { kind: "missing" };
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const info = await handle.stat();
|
|
94
|
+
if (!info.isFile()) {
|
|
95
|
+
return { kind: "missing" };
|
|
96
|
+
}
|
|
97
|
+
if (info.size > maxBytes) {
|
|
98
|
+
return { kind: "too-large" };
|
|
99
|
+
}
|
|
100
|
+
return { kind: "ok", bytes: await readBoundedBytesInto(handle, info.size) };
|
|
101
|
+
} finally {
|
|
102
|
+
await handle.close();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function tempFileName(path) {
|
|
106
|
+
return join(dirname(path), `.${basename(path)}.tmp-${process.pid}-${Date.now()}-${randomUUID()}`);
|
|
107
|
+
}
|
|
108
|
+
async function atomicWrite(path, data) {
|
|
109
|
+
const tmp = tempFileName(path);
|
|
110
|
+
await (typeof data === "string" ? writeFile(tmp, data, "utf8") : writeFile(tmp, data));
|
|
111
|
+
try {
|
|
112
|
+
await rename(tmp, path);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
await rm(tmp, { force: true });
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
var defaultFs = {
|
|
119
|
+
async fileExists(path) {
|
|
120
|
+
try {
|
|
121
|
+
await access(path);
|
|
122
|
+
return true;
|
|
123
|
+
} catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
readFileBounded: (path, maxBytes) => readBounded(path, maxBytes),
|
|
128
|
+
readBytesBounded: (path, maxBytes) => readBoundedBytes(path, maxBytes),
|
|
129
|
+
writeFile: (path, data) => atomicWrite(path, data),
|
|
130
|
+
writeBytes: (path, data) => atomicWrite(path, data)
|
|
131
|
+
};
|
|
132
|
+
var MAX_GLOSSARY_FILE_BYTES = 1024 * 1024;
|
|
133
|
+
var glossaryRecordSchema = z.record(z.string(), z.string());
|
|
134
|
+
var BOM = "\uFEFF";
|
|
135
|
+
var REPLACEMENT_CHARACTER = "\uFFFD";
|
|
136
|
+
var NUL = "\0";
|
|
137
|
+
function stripBom(content) {
|
|
138
|
+
return content.startsWith(BOM) ? content.slice(BOM.length) : content;
|
|
139
|
+
}
|
|
140
|
+
function looksLikeInvalidEncoding(content) {
|
|
141
|
+
return content.startsWith(REPLACEMENT_CHARACTER) || content.includes(NUL);
|
|
142
|
+
}
|
|
143
|
+
async function readGlossaryFile(resolvedPath, fs) {
|
|
144
|
+
const read = await fs.readFileBounded(resolvedPath, MAX_GLOSSARY_FILE_BYTES);
|
|
145
|
+
if (read.kind === "missing") {
|
|
146
|
+
throw new SdkError(
|
|
147
|
+
"CONFIG_INVALID",
|
|
148
|
+
`The glossary file at ${resolvedPath} was not found or could not be read.`
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
if (read.kind === "too-large") {
|
|
152
|
+
throw new SdkError(
|
|
153
|
+
"CONFIG_INVALID",
|
|
154
|
+
`The glossary file at ${resolvedPath} exceeds the maximum allowed size of ${MAX_GLOSSARY_FILE_BYTES} bytes.`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const content = stripBom(read.content);
|
|
158
|
+
if (looksLikeInvalidEncoding(content)) {
|
|
159
|
+
throw new SdkError(
|
|
160
|
+
"CONFIG_INVALID",
|
|
161
|
+
`The glossary file at ${resolvedPath} must be UTF-8 encoded.`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
let parsed;
|
|
165
|
+
try {
|
|
166
|
+
parsed = JSON.parse(content);
|
|
167
|
+
} catch {
|
|
168
|
+
throw new SdkError("CONFIG_INVALID", `The glossary file at ${resolvedPath} is not valid JSON.`);
|
|
169
|
+
}
|
|
170
|
+
const result = glossaryRecordSchema.safeParse(parsed);
|
|
171
|
+
if (!result.success) {
|
|
172
|
+
throw new SdkError(
|
|
173
|
+
"CONFIG_INVALID",
|
|
174
|
+
`The glossary file at ${resolvedPath} must contain a flat object of string keys to string values.`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
return result.data;
|
|
178
|
+
}
|
|
179
|
+
async function resolveGlossary(glossary, baseDir, fs) {
|
|
180
|
+
if (glossary === void 0) {
|
|
181
|
+
return { glossary: void 0, provenance: { source: "none" } };
|
|
182
|
+
}
|
|
183
|
+
if (typeof glossary === "string") {
|
|
184
|
+
const resolvedPath = resolve(baseDir, glossary);
|
|
185
|
+
const record = await readGlossaryFile(resolvedPath, fs);
|
|
186
|
+
return { glossary: record, provenance: { source: "file", path: resolvedPath } };
|
|
187
|
+
}
|
|
188
|
+
return { glossary, provenance: { source: "inline" } };
|
|
189
|
+
}
|
|
41
190
|
var FNV_OFFSET_BASIS = 14695981039346656037n;
|
|
42
191
|
var FNV_PRIME = 1099511628211n;
|
|
43
192
|
var U64_MASK = (1n << 64n) - 1n;
|
|
@@ -873,7 +1022,13 @@ var verbatraConfigSchema = z.strictObject({
|
|
|
873
1022
|
pattern: z.string().min(1)
|
|
874
1023
|
}),
|
|
875
1024
|
provider: providerConfigSchema,
|
|
876
|
-
|
|
1025
|
+
/**
|
|
1026
|
+
* A glossary of source terms to preferred target terms, either inline or as a path to a JSON file
|
|
1027
|
+
* carrying the same shape. The two forms are mutually exclusive by type; there is no merge or
|
|
1028
|
+
* precedence between them. A path is resolved and validated by the loader, not by this schema; see
|
|
1029
|
+
* `resolve-glossary.ts`.
|
|
1030
|
+
*/
|
|
1031
|
+
glossary: z.union([z.record(z.string(), z.string()), z.string().min(1)]).optional(),
|
|
877
1032
|
tone: z.enum(["formal", "informal", "neutral"]).optional(),
|
|
878
1033
|
/**
|
|
879
1034
|
* Opt-in orphan pruning, off by default. When true, keys present in a target file but absent from
|
|
@@ -927,7 +1082,7 @@ function formatIssues(error) {
|
|
|
927
1082
|
return issue.code === "unrecognized_keys" ? `${base} (API keys are read from the environment, not the config)` : base;
|
|
928
1083
|
}).join("; ");
|
|
929
1084
|
}
|
|
930
|
-
function
|
|
1085
|
+
function parseConfig(input) {
|
|
931
1086
|
const parsed = verbatraConfigSchema.safeParse(input);
|
|
932
1087
|
if (!parsed.success) {
|
|
933
1088
|
throw new SdkError(
|
|
@@ -937,7 +1092,16 @@ function validate(input) {
|
|
|
937
1092
|
}
|
|
938
1093
|
return parsed.data;
|
|
939
1094
|
}
|
|
940
|
-
async function
|
|
1095
|
+
async function finalizeConfig(parsed, baseDir, fs) {
|
|
1096
|
+
const { glossary: glossaryInput, ...rest } = parsed;
|
|
1097
|
+
const resolved = await resolveGlossary(glossaryInput, baseDir, fs);
|
|
1098
|
+
const config = {
|
|
1099
|
+
...rest,
|
|
1100
|
+
...resolved.glossary !== void 0 ? { glossary: resolved.glossary } : {}
|
|
1101
|
+
};
|
|
1102
|
+
return { config, glossary: resolved.provenance };
|
|
1103
|
+
}
|
|
1104
|
+
async function loadExplicitWithMeta(explorer, configPath, cwd, fs) {
|
|
941
1105
|
const resolved = resolve(cwd ?? process.cwd(), configPath);
|
|
942
1106
|
if (!existsSync(resolved)) {
|
|
943
1107
|
throw new SdkError("CONFIG_NOT_FOUND", `No verbatra configuration file at ${resolved}.`);
|
|
@@ -949,18 +1113,23 @@ async function loadExplicit(explorer, configPath, cwd) {
|
|
|
949
1113
|
const detail = error instanceof Error ? error.message : String(error);
|
|
950
1114
|
throw new SdkError("CONFIG_INVALID", `Failed to load the verbatra configuration: ${detail}`);
|
|
951
1115
|
}
|
|
952
|
-
|
|
1116
|
+
const parsed = parseConfig(result?.config);
|
|
1117
|
+
const { config, glossary } = await finalizeConfig(parsed, dirname(resolved), fs);
|
|
1118
|
+
return { config, source: { kind: "explicit", filepath: resolved }, glossary };
|
|
953
1119
|
}
|
|
954
|
-
async function
|
|
1120
|
+
async function loadConfigWithMeta(options = {}) {
|
|
1121
|
+
const fs = options.fs ?? defaultFs;
|
|
955
1122
|
if (options.configOverride !== void 0) {
|
|
956
|
-
|
|
1123
|
+
const parsed2 = parseConfig(options.configOverride);
|
|
1124
|
+
const { config: config2, glossary: glossary2 } = await finalizeConfig(parsed2, options.cwd ?? process.cwd(), fs);
|
|
1125
|
+
return { config: config2, source: { kind: "override" }, glossary: glossary2 };
|
|
957
1126
|
}
|
|
958
1127
|
const explorer = cosmiconfig(MODULE_NAME, {
|
|
959
1128
|
searchPlaces: SEARCH_PLACES,
|
|
960
1129
|
loaders: { ".ts": TypeScriptLoader() }
|
|
961
1130
|
});
|
|
962
1131
|
if (options.configPath !== void 0) {
|
|
963
|
-
return
|
|
1132
|
+
return loadExplicitWithMeta(explorer, options.configPath, options.cwd, fs);
|
|
964
1133
|
}
|
|
965
1134
|
let result;
|
|
966
1135
|
try {
|
|
@@ -975,99 +1144,14 @@ async function loadConfig(options = {}) {
|
|
|
975
1144
|
"No verbatra configuration found. Create a verbatra.config.ts, a .verbatrarc.json, or a 'verbatra' property in package.json."
|
|
976
1145
|
);
|
|
977
1146
|
}
|
|
978
|
-
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
const buffer = Buffer.allocUnsafe(size);
|
|
982
|
-
let offset = 0;
|
|
983
|
-
while (offset < size) {
|
|
984
|
-
const { bytesRead } = await handle.read(buffer, offset, size - offset, offset);
|
|
985
|
-
if (bytesRead === 0) {
|
|
986
|
-
break;
|
|
987
|
-
}
|
|
988
|
-
offset += bytesRead;
|
|
989
|
-
}
|
|
990
|
-
return buffer.toString("utf8", 0, offset);
|
|
991
|
-
}
|
|
992
|
-
async function readBounded(path, maxBytes) {
|
|
993
|
-
let handle;
|
|
994
|
-
try {
|
|
995
|
-
handle = await open(path, "r");
|
|
996
|
-
} catch {
|
|
997
|
-
return { kind: "missing" };
|
|
998
|
-
}
|
|
999
|
-
try {
|
|
1000
|
-
const info = await handle.stat();
|
|
1001
|
-
if (!info.isFile()) {
|
|
1002
|
-
return { kind: "missing" };
|
|
1003
|
-
}
|
|
1004
|
-
if (info.size > maxBytes) {
|
|
1005
|
-
return { kind: "too-large" };
|
|
1006
|
-
}
|
|
1007
|
-
return { kind: "ok", content: await readBoundedUtf8(handle, info.size) };
|
|
1008
|
-
} finally {
|
|
1009
|
-
await handle.close();
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
async function readBoundedBytesInto(handle, size) {
|
|
1013
|
-
const buffer = Buffer.allocUnsafeSlow(size);
|
|
1014
|
-
let offset = 0;
|
|
1015
|
-
while (offset < size) {
|
|
1016
|
-
const { bytesRead } = await handle.read(buffer, offset, size - offset, offset);
|
|
1017
|
-
if (bytesRead === 0) {
|
|
1018
|
-
break;
|
|
1019
|
-
}
|
|
1020
|
-
offset += bytesRead;
|
|
1021
|
-
}
|
|
1022
|
-
return new Uint8Array(buffer.buffer, buffer.byteOffset, offset);
|
|
1023
|
-
}
|
|
1024
|
-
async function readBoundedBytes(path, maxBytes) {
|
|
1025
|
-
let handle;
|
|
1026
|
-
try {
|
|
1027
|
-
handle = await open(path, "r");
|
|
1028
|
-
} catch {
|
|
1029
|
-
return { kind: "missing" };
|
|
1030
|
-
}
|
|
1031
|
-
try {
|
|
1032
|
-
const info = await handle.stat();
|
|
1033
|
-
if (!info.isFile()) {
|
|
1034
|
-
return { kind: "missing" };
|
|
1035
|
-
}
|
|
1036
|
-
if (info.size > maxBytes) {
|
|
1037
|
-
return { kind: "too-large" };
|
|
1038
|
-
}
|
|
1039
|
-
return { kind: "ok", bytes: await readBoundedBytesInto(handle, info.size) };
|
|
1040
|
-
} finally {
|
|
1041
|
-
await handle.close();
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
function tempFileName(path) {
|
|
1045
|
-
return join(dirname(path), `.${basename(path)}.tmp-${process.pid}-${Date.now()}-${randomUUID()}`);
|
|
1147
|
+
const parsed = parseConfig(result.config);
|
|
1148
|
+
const { config, glossary } = await finalizeConfig(parsed, dirname(result.filepath), fs);
|
|
1149
|
+
return { config, source: { kind: "search", filepath: result.filepath }, glossary };
|
|
1046
1150
|
}
|
|
1047
|
-
async function
|
|
1048
|
-
const
|
|
1049
|
-
|
|
1050
|
-
try {
|
|
1051
|
-
await rename(tmp, path);
|
|
1052
|
-
} catch (error) {
|
|
1053
|
-
await rm(tmp, { force: true });
|
|
1054
|
-
throw error;
|
|
1055
|
-
}
|
|
1151
|
+
async function loadConfig(options = {}) {
|
|
1152
|
+
const { config } = await loadConfigWithMeta(options);
|
|
1153
|
+
return config;
|
|
1056
1154
|
}
|
|
1057
|
-
var defaultFs = {
|
|
1058
|
-
async fileExists(path) {
|
|
1059
|
-
try {
|
|
1060
|
-
await access(path);
|
|
1061
|
-
return true;
|
|
1062
|
-
} catch {
|
|
1063
|
-
return false;
|
|
1064
|
-
}
|
|
1065
|
-
},
|
|
1066
|
-
readFileBounded: (path, maxBytes) => readBounded(path, maxBytes),
|
|
1067
|
-
readBytesBounded: (path, maxBytes) => readBoundedBytes(path, maxBytes),
|
|
1068
|
-
writeFile: (path, data) => atomicWrite(path, data),
|
|
1069
|
-
writeBytes: (path, data) => atomicWrite(path, data)
|
|
1070
|
-
};
|
|
1071
1155
|
var LOCK_FILE_NAME = "verbatra.lock.json";
|
|
1072
1156
|
var CURRENT_VERSION = 1;
|
|
1073
1157
|
var EMPTY_LOCK = { version: CURRENT_VERSION, locales: {} };
|
|
@@ -2224,6 +2308,40 @@ async function diff(input, deps = {}) {
|
|
|
2224
2308
|
return { hasPendingChanges: locales.some((entry) => entry.hasPendingChanges), locales };
|
|
2225
2309
|
}
|
|
2226
2310
|
|
|
2311
|
+
// src/flow/lock-state.ts
|
|
2312
|
+
function toLockLocaleState(locale, keyCount, diff2) {
|
|
2313
|
+
return {
|
|
2314
|
+
locale,
|
|
2315
|
+
keyCount,
|
|
2316
|
+
missing: diff2.missing.length,
|
|
2317
|
+
stale: diff2.changed.length,
|
|
2318
|
+
upToDate: diff2.unchanged.length
|
|
2319
|
+
};
|
|
2320
|
+
}
|
|
2321
|
+
async function lockState(input, deps = {}) {
|
|
2322
|
+
const config = input.config;
|
|
2323
|
+
const cwd = input.cwd ?? process.cwd();
|
|
2324
|
+
const fs = deps.fs ?? defaultFs;
|
|
2325
|
+
const locales = selectLocales(config, input.locales);
|
|
2326
|
+
const path = lockFilePath(cwd);
|
|
2327
|
+
const exists = await fs.fileExists(path);
|
|
2328
|
+
if (!exists) {
|
|
2329
|
+
return { exists: false };
|
|
2330
|
+
}
|
|
2331
|
+
const lock = await readLockFile(path, fs);
|
|
2332
|
+
const adapter = selectAdapter(config.format, deps.adapterRegistry);
|
|
2333
|
+
const source = await readSource(config, cwd, fs, adapter);
|
|
2334
|
+
const localeStates = await Promise.all(
|
|
2335
|
+
locales.map(async (locale) => {
|
|
2336
|
+
const target = await readTarget(cwd, config, adapter, fs, locale);
|
|
2337
|
+
const baseline = baselineFor(lock, locale);
|
|
2338
|
+
const diff2 = diffResources(source.resource, target, { baseline });
|
|
2339
|
+
return toLockLocaleState(locale, baseline.size, diff2);
|
|
2340
|
+
})
|
|
2341
|
+
);
|
|
2342
|
+
return { exists: true, version: lock.version, locales: localeStates };
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2227
2345
|
// src/selection/select-provider.ts
|
|
2228
2346
|
function selectProvider(config, createProvider = buildProvider) {
|
|
2229
2347
|
try {
|
|
@@ -3429,6 +3547,13 @@ async function importWorkbook(input, deps = {}) {
|
|
|
3429
3547
|
return { dryRun, locales: summaries, succeeded, failed };
|
|
3430
3548
|
}
|
|
3431
3549
|
|
|
3550
|
+
// src/lock/load-lock-file.ts
|
|
3551
|
+
async function loadLockFile(input = {}, deps = {}) {
|
|
3552
|
+
const cwd = input.cwd ?? process.cwd();
|
|
3553
|
+
const fs = deps.fs ?? defaultFs;
|
|
3554
|
+
return readLockFile(lockFilePath(cwd), fs);
|
|
3555
|
+
}
|
|
3556
|
+
|
|
3432
3557
|
// src/scaffolding.ts
|
|
3433
3558
|
var scaffoldingMetadata = {
|
|
3434
3559
|
/** Provider id -> the environment variable its API key is read from. Owned by ai-providers. */
|
|
@@ -3544,6 +3669,6 @@ async function watch(input, deps = {}) {
|
|
|
3544
3669
|
return { stop };
|
|
3545
3670
|
}
|
|
3546
3671
|
|
|
3547
|
-
export { DEFAULT_WORKBOOK_PATH, SdkError, check, defineConfig, diff, exportWorkbook, importWorkbook, loadConfig, scaffoldingMetadata, translate2 as translate, verbatraConfigSchema, watch };
|
|
3672
|
+
export { DEFAULT_WORKBOOK_PATH, LOCK_FILE_NAME, SdkError, check, defineConfig, diff, exportWorkbook, importWorkbook, loadConfig, loadConfigWithMeta, loadLockFile, lockState, scaffoldingMetadata, translate2 as translate, verbatraConfigSchema, watch };
|
|
3548
3673
|
//# sourceMappingURL=index.js.map
|
|
3549
3674
|
//# sourceMappingURL=index.js.map
|