@fractary/codex 0.8.0 → 0.9.1
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 +613 -125
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +754 -48
- package/dist/index.d.ts +754 -48
- package/dist/index.js +595 -125
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import micromatch3 from 'micromatch';
|
|
2
|
-
import path3 from 'path';
|
|
2
|
+
import * as path3 from 'path';
|
|
3
|
+
import path3__default from 'path';
|
|
3
4
|
import { execFile, execSync } from 'child_process';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
import yaml from 'js-yaml';
|
|
6
|
-
import
|
|
7
|
+
import * as fs3 from 'fs/promises';
|
|
8
|
+
import fs3__default from 'fs/promises';
|
|
7
9
|
import { promisify } from 'util';
|
|
8
10
|
|
|
9
11
|
var __defProp = Object.defineProperty;
|
|
@@ -161,7 +163,7 @@ function validatePath(filePath) {
|
|
|
161
163
|
return false;
|
|
162
164
|
}
|
|
163
165
|
}
|
|
164
|
-
const normalized =
|
|
166
|
+
const normalized = path3__default.normalize(filePath);
|
|
165
167
|
if (normalized.startsWith("..") || normalized.includes("/../") || normalized.includes("\\..\\")) {
|
|
166
168
|
return false;
|
|
167
169
|
}
|
|
@@ -179,7 +181,7 @@ function sanitizePath(filePath) {
|
|
|
179
181
|
}
|
|
180
182
|
sanitized = sanitized.replace(/^\/+/, "");
|
|
181
183
|
sanitized = sanitized.replace(/^~\//, "");
|
|
182
|
-
sanitized =
|
|
184
|
+
sanitized = path3__default.normalize(sanitized);
|
|
183
185
|
sanitized = sanitized.replace(/\.\.\//g, "").replace(/\.\./g, "");
|
|
184
186
|
sanitized = sanitized.replace(/^\.\//, "");
|
|
185
187
|
sanitized = sanitized.replace(/\0/g, "");
|
|
@@ -280,10 +282,10 @@ function parseReference(uri, options = {}) {
|
|
|
280
282
|
path: filePath
|
|
281
283
|
};
|
|
282
284
|
}
|
|
283
|
-
function buildUri(org, project,
|
|
285
|
+
function buildUri(org, project, path7) {
|
|
284
286
|
const base = `${CODEX_URI_PREFIX}${org}/${project}`;
|
|
285
|
-
if (
|
|
286
|
-
const cleanPath =
|
|
287
|
+
if (path7) {
|
|
288
|
+
const cleanPath = path7.startsWith("/") ? path7.slice(1) : path7;
|
|
287
289
|
return `${base}/${cleanPath}`;
|
|
288
290
|
}
|
|
289
291
|
return base;
|
|
@@ -354,7 +356,7 @@ function getCurrentContext(options = {}) {
|
|
|
354
356
|
return detectCurrentProject(options.cwd);
|
|
355
357
|
}
|
|
356
358
|
function calculateCachePath(org, project, filePath, cacheDir) {
|
|
357
|
-
return
|
|
359
|
+
return path3__default.join(cacheDir, org, project, filePath);
|
|
358
360
|
}
|
|
359
361
|
function resolveReference(uri, options = {}) {
|
|
360
362
|
const parsed = parseReference(uri);
|
|
@@ -363,7 +365,7 @@ function resolveReference(uri, options = {}) {
|
|
|
363
365
|
}
|
|
364
366
|
const cacheDir = options.cacheDir || DEFAULT_CACHE_DIR;
|
|
365
367
|
const currentContext = getCurrentContext(options);
|
|
366
|
-
const cachePath = parsed.path ? calculateCachePath(parsed.org, parsed.project, parsed.path, cacheDir) :
|
|
368
|
+
const cachePath = parsed.path ? calculateCachePath(parsed.org, parsed.project, parsed.path, cacheDir) : path3__default.join(cacheDir, parsed.org, parsed.project);
|
|
367
369
|
const isCurrentProject = currentContext.org === parsed.org && currentContext.project === parsed.project;
|
|
368
370
|
const resolved = {
|
|
369
371
|
...parsed,
|
|
@@ -372,9 +374,45 @@ function resolveReference(uri, options = {}) {
|
|
|
372
374
|
};
|
|
373
375
|
if (isCurrentProject && parsed.path) {
|
|
374
376
|
resolved.localPath = parsed.path;
|
|
377
|
+
if (options.config) {
|
|
378
|
+
const fileSource = detectFilePluginSource(parsed.path, options.config);
|
|
379
|
+
if (fileSource) {
|
|
380
|
+
resolved.sourceType = "file-plugin";
|
|
381
|
+
resolved.filePluginSource = fileSource.name;
|
|
382
|
+
resolved.localPath = fileSource.fullPath;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
375
385
|
}
|
|
376
386
|
return resolved;
|
|
377
387
|
}
|
|
388
|
+
function detectFilePluginSource(filePath, config) {
|
|
389
|
+
if (!config?.file?.sources) {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
for (const [sourceName, source] of Object.entries(config.file.sources)) {
|
|
393
|
+
const basePath = source.local?.base_path;
|
|
394
|
+
if (!basePath) {
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
const normalizedPath = filePath.replace(/^\.\//, "").replace(/^\//, "");
|
|
398
|
+
const normalizedBasePath = basePath.replace(/^\.\//, "").replace(/^\//, "").replace(/\/$/, "");
|
|
399
|
+
if (normalizedPath.startsWith(normalizedBasePath)) {
|
|
400
|
+
return {
|
|
401
|
+
name: sourceName,
|
|
402
|
+
fullPath: path3__default.join(basePath, normalizedPath.substring(normalizedBasePath.length).replace(/^\//, ""))
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
const sourceNameInPath = normalizedBasePath.split("/").pop();
|
|
406
|
+
if (sourceNameInPath && normalizedPath.startsWith(sourceNameInPath + "/")) {
|
|
407
|
+
const pathWithoutSource = normalizedPath.substring(sourceNameInPath.length + 1);
|
|
408
|
+
return {
|
|
409
|
+
name: sourceName,
|
|
410
|
+
fullPath: path3__default.join(basePath, pathWithoutSource)
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
378
416
|
function resolveReferences(uris, options = {}) {
|
|
379
417
|
return uris.map((uri) => resolveReference(uri, options)).filter((r) => r !== null);
|
|
380
418
|
}
|
|
@@ -388,9 +426,9 @@ function getRelativeCachePath(uri) {
|
|
|
388
426
|
return null;
|
|
389
427
|
}
|
|
390
428
|
if (parsed.path) {
|
|
391
|
-
return
|
|
429
|
+
return path3__default.join(parsed.org, parsed.project, parsed.path);
|
|
392
430
|
}
|
|
393
|
-
return
|
|
431
|
+
return path3__default.join(parsed.org, parsed.project);
|
|
394
432
|
}
|
|
395
433
|
|
|
396
434
|
// src/types/built-in.ts
|
|
@@ -845,8 +883,40 @@ var ArchiveProjectConfigSchema = z.object({
|
|
|
845
883
|
var ArchiveConfigSchema = z.object({
|
|
846
884
|
projects: z.record(ArchiveProjectConfigSchema)
|
|
847
885
|
});
|
|
886
|
+
var GitHubAuthConfigSchema = z.object({
|
|
887
|
+
/** Default token environment variable name (default: GITHUB_TOKEN) */
|
|
888
|
+
default_token_env: z.string().optional(),
|
|
889
|
+
/** Fallback to public access if authentication fails */
|
|
890
|
+
fallback_to_public: z.boolean().optional()
|
|
891
|
+
});
|
|
892
|
+
var AuthConfigSchema = z.object({
|
|
893
|
+
/** GitHub authentication configuration */
|
|
894
|
+
github: GitHubAuthConfigSchema.optional()
|
|
895
|
+
});
|
|
896
|
+
var SourceConfigSchema = z.object({
|
|
897
|
+
/** Source type */
|
|
898
|
+
type: z.enum(["github", "s3", "http", "local"]),
|
|
899
|
+
/** Environment variable containing the authentication token */
|
|
900
|
+
token_env: z.string().optional(),
|
|
901
|
+
/** Direct token value (not recommended, use token_env instead) */
|
|
902
|
+
token: z.string().optional(),
|
|
903
|
+
/** Branch to fetch from (for GitHub sources) */
|
|
904
|
+
branch: z.string().optional(),
|
|
905
|
+
/** Base URL (for HTTP sources) */
|
|
906
|
+
base_url: z.string().optional(),
|
|
907
|
+
/** Bucket name (for S3 sources) */
|
|
908
|
+
bucket: z.string().optional(),
|
|
909
|
+
/** Prefix/path within bucket (for S3 sources) */
|
|
910
|
+
prefix: z.string().optional()
|
|
911
|
+
});
|
|
912
|
+
var DependencyConfigSchema = z.object({
|
|
913
|
+
/** Sources within this dependency */
|
|
914
|
+
sources: z.record(SourceConfigSchema)
|
|
915
|
+
});
|
|
848
916
|
var CodexConfigSchema = z.object({
|
|
849
917
|
organizationSlug: z.string(),
|
|
918
|
+
/** Project name (optional) */
|
|
919
|
+
project: z.string().optional(),
|
|
850
920
|
directories: z.object({
|
|
851
921
|
source: z.string().optional(),
|
|
852
922
|
target: z.string().optional(),
|
|
@@ -856,8 +926,47 @@ var CodexConfigSchema = z.object({
|
|
|
856
926
|
// Directional sync configuration
|
|
857
927
|
sync: DirectionalSyncSchema.optional(),
|
|
858
928
|
// Archive configuration
|
|
859
|
-
archive: ArchiveConfigSchema.optional()
|
|
929
|
+
archive: ArchiveConfigSchema.optional(),
|
|
930
|
+
// Authentication configuration
|
|
931
|
+
auth: AuthConfigSchema.optional(),
|
|
932
|
+
// Dependencies configuration (external projects)
|
|
933
|
+
dependencies: z.record(DependencyConfigSchema).optional()
|
|
860
934
|
}).strict();
|
|
935
|
+
var FileSourceSchema = z.object({
|
|
936
|
+
type: z.enum(["s3", "r2", "gcs", "local"]),
|
|
937
|
+
bucket: z.string().optional(),
|
|
938
|
+
prefix: z.string().optional(),
|
|
939
|
+
region: z.string().optional(),
|
|
940
|
+
local: z.object({
|
|
941
|
+
base_path: z.string()
|
|
942
|
+
}),
|
|
943
|
+
push: z.object({
|
|
944
|
+
compress: z.boolean().optional(),
|
|
945
|
+
keep_local: z.boolean().optional()
|
|
946
|
+
}).optional(),
|
|
947
|
+
auth: z.object({
|
|
948
|
+
profile: z.string().optional()
|
|
949
|
+
}).optional()
|
|
950
|
+
}).refine(
|
|
951
|
+
(data) => {
|
|
952
|
+
if (data.type !== "local" && !data.bucket) {
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
return true;
|
|
956
|
+
},
|
|
957
|
+
{
|
|
958
|
+
message: "Bucket is required for s3, r2, and gcs storage types",
|
|
959
|
+
path: ["bucket"]
|
|
960
|
+
}
|
|
961
|
+
);
|
|
962
|
+
var FileConfigSchema = z.object({
|
|
963
|
+
schema_version: z.string(),
|
|
964
|
+
sources: z.record(FileSourceSchema)
|
|
965
|
+
});
|
|
966
|
+
z.object({
|
|
967
|
+
file: FileConfigSchema.optional(),
|
|
968
|
+
codex: CodexConfigSchema.optional()
|
|
969
|
+
});
|
|
861
970
|
function parseMetadata(content, options = {}) {
|
|
862
971
|
const { strict = true, normalize = true } = options;
|
|
863
972
|
const normalizedContent = normalize ? content.replace(/\r\n/g, "\n") : content;
|
|
@@ -1187,18 +1296,18 @@ function parseCustomDestination(value) {
|
|
|
1187
1296
|
);
|
|
1188
1297
|
}
|
|
1189
1298
|
const repo = value.substring(0, colonIndex).trim();
|
|
1190
|
-
const
|
|
1299
|
+
const path7 = value.substring(colonIndex + 1).trim();
|
|
1191
1300
|
if (!repo) {
|
|
1192
1301
|
throw new ValidationError(
|
|
1193
1302
|
`Invalid custom destination: repository name cannot be empty in "${value}"`
|
|
1194
1303
|
);
|
|
1195
1304
|
}
|
|
1196
|
-
if (!
|
|
1305
|
+
if (!path7) {
|
|
1197
1306
|
throw new ValidationError(
|
|
1198
1307
|
`Invalid custom destination: path cannot be empty in "${value}"`
|
|
1199
1308
|
);
|
|
1200
1309
|
}
|
|
1201
|
-
return { repo, path:
|
|
1310
|
+
return { repo, path: path7 };
|
|
1202
1311
|
}
|
|
1203
1312
|
function getCustomSyncDestinations(metadata) {
|
|
1204
1313
|
const customDestinations = metadata.codex_sync_custom;
|
|
@@ -1234,8 +1343,8 @@ function mergeFetchOptions(options) {
|
|
|
1234
1343
|
...options
|
|
1235
1344
|
};
|
|
1236
1345
|
}
|
|
1237
|
-
function detectContentType(
|
|
1238
|
-
const ext =
|
|
1346
|
+
function detectContentType(path7) {
|
|
1347
|
+
const ext = path7.split(".").pop()?.toLowerCase();
|
|
1239
1348
|
const mimeTypes = {
|
|
1240
1349
|
md: "text/markdown",
|
|
1241
1350
|
markdown: "text/markdown",
|
|
@@ -1295,19 +1404,19 @@ var LocalStorage = class {
|
|
|
1295
1404
|
if (!reference.localPath) {
|
|
1296
1405
|
throw new Error(`No local path for reference: ${reference.uri}`);
|
|
1297
1406
|
}
|
|
1298
|
-
const fullPath =
|
|
1407
|
+
const fullPath = path3__default.isAbsolute(reference.localPath) ? reference.localPath : path3__default.join(this.baseDir, reference.localPath);
|
|
1299
1408
|
try {
|
|
1300
|
-
await
|
|
1409
|
+
await fs3__default.access(fullPath);
|
|
1301
1410
|
} catch {
|
|
1302
1411
|
throw new Error(`File not found: ${fullPath}`);
|
|
1303
1412
|
}
|
|
1304
|
-
const stats = await
|
|
1413
|
+
const stats = await fs3__default.stat(fullPath);
|
|
1305
1414
|
if (stats.size > opts.maxSize) {
|
|
1306
1415
|
throw new Error(
|
|
1307
1416
|
`File too large: ${stats.size} bytes (max: ${opts.maxSize} bytes)`
|
|
1308
1417
|
);
|
|
1309
1418
|
}
|
|
1310
|
-
const content = await
|
|
1419
|
+
const content = await fs3__default.readFile(fullPath);
|
|
1311
1420
|
return {
|
|
1312
1421
|
content,
|
|
1313
1422
|
contentType: detectContentType(reference.localPath),
|
|
@@ -1326,9 +1435,9 @@ var LocalStorage = class {
|
|
|
1326
1435
|
if (!reference.localPath) {
|
|
1327
1436
|
return false;
|
|
1328
1437
|
}
|
|
1329
|
-
const fullPath =
|
|
1438
|
+
const fullPath = path3__default.isAbsolute(reference.localPath) ? reference.localPath : path3__default.join(this.baseDir, reference.localPath);
|
|
1330
1439
|
try {
|
|
1331
|
-
await
|
|
1440
|
+
await fs3__default.access(fullPath);
|
|
1332
1441
|
return true;
|
|
1333
1442
|
} catch {
|
|
1334
1443
|
return false;
|
|
@@ -1338,24 +1447,24 @@ var LocalStorage = class {
|
|
|
1338
1447
|
* Read file content as string
|
|
1339
1448
|
*/
|
|
1340
1449
|
async readText(filePath) {
|
|
1341
|
-
const fullPath =
|
|
1342
|
-
return
|
|
1450
|
+
const fullPath = path3__default.isAbsolute(filePath) ? filePath : path3__default.join(this.baseDir, filePath);
|
|
1451
|
+
return fs3__default.readFile(fullPath, "utf-8");
|
|
1343
1452
|
}
|
|
1344
1453
|
/**
|
|
1345
1454
|
* Write content to file
|
|
1346
1455
|
*/
|
|
1347
1456
|
async write(filePath, content) {
|
|
1348
|
-
const fullPath =
|
|
1349
|
-
await
|
|
1350
|
-
await
|
|
1457
|
+
const fullPath = path3__default.isAbsolute(filePath) ? filePath : path3__default.join(this.baseDir, filePath);
|
|
1458
|
+
await fs3__default.mkdir(path3__default.dirname(fullPath), { recursive: true });
|
|
1459
|
+
await fs3__default.writeFile(fullPath, content);
|
|
1351
1460
|
}
|
|
1352
1461
|
/**
|
|
1353
1462
|
* Delete a file
|
|
1354
1463
|
*/
|
|
1355
1464
|
async delete(filePath) {
|
|
1356
|
-
const fullPath =
|
|
1465
|
+
const fullPath = path3__default.isAbsolute(filePath) ? filePath : path3__default.join(this.baseDir, filePath);
|
|
1357
1466
|
try {
|
|
1358
|
-
await
|
|
1467
|
+
await fs3__default.unlink(fullPath);
|
|
1359
1468
|
return true;
|
|
1360
1469
|
} catch {
|
|
1361
1470
|
return false;
|
|
@@ -1365,10 +1474,10 @@ var LocalStorage = class {
|
|
|
1365
1474
|
* List files in a directory
|
|
1366
1475
|
*/
|
|
1367
1476
|
async list(dirPath) {
|
|
1368
|
-
const fullPath =
|
|
1477
|
+
const fullPath = path3__default.isAbsolute(dirPath) ? dirPath : path3__default.join(this.baseDir, dirPath);
|
|
1369
1478
|
try {
|
|
1370
|
-
const entries = await
|
|
1371
|
-
return entries.filter((e) => e.isFile()).map((e) =>
|
|
1479
|
+
const entries = await fs3__default.readdir(fullPath, { withFileTypes: true });
|
|
1480
|
+
return entries.filter((e) => e.isFile()).map((e) => path3__default.join(dirPath, e.name));
|
|
1372
1481
|
} catch {
|
|
1373
1482
|
return [];
|
|
1374
1483
|
}
|
|
@@ -1713,6 +1822,300 @@ var HttpStorage = class {
|
|
|
1713
1822
|
function createHttpStorage(options) {
|
|
1714
1823
|
return new HttpStorage(options);
|
|
1715
1824
|
}
|
|
1825
|
+
|
|
1826
|
+
// src/file-integration/source-resolver.ts
|
|
1827
|
+
var FileSourceResolver = class {
|
|
1828
|
+
constructor(config) {
|
|
1829
|
+
this.config = config;
|
|
1830
|
+
this.initializeSources();
|
|
1831
|
+
}
|
|
1832
|
+
sources = /* @__PURE__ */ new Map();
|
|
1833
|
+
/**
|
|
1834
|
+
* Initialize sources from config
|
|
1835
|
+
*/
|
|
1836
|
+
initializeSources() {
|
|
1837
|
+
if (!this.config.file?.sources) {
|
|
1838
|
+
return;
|
|
1839
|
+
}
|
|
1840
|
+
for (const [name, sourceConfig] of Object.entries(this.config.file.sources)) {
|
|
1841
|
+
const resolved = {
|
|
1842
|
+
name,
|
|
1843
|
+
type: "file-plugin",
|
|
1844
|
+
localPath: sourceConfig.local.base_path,
|
|
1845
|
+
isCurrentProject: true,
|
|
1846
|
+
config: sourceConfig
|
|
1847
|
+
};
|
|
1848
|
+
if (sourceConfig.bucket && sourceConfig.type !== "local") {
|
|
1849
|
+
resolved.bucket = sourceConfig.bucket;
|
|
1850
|
+
resolved.prefix = sourceConfig.prefix;
|
|
1851
|
+
resolved.remotePath = this.buildRemotePath(sourceConfig);
|
|
1852
|
+
}
|
|
1853
|
+
this.sources.set(name, resolved);
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
/**
|
|
1857
|
+
* Build remote path from source config
|
|
1858
|
+
*/
|
|
1859
|
+
buildRemotePath(source) {
|
|
1860
|
+
const protocol = source.type === "s3" ? "s3://" : source.type === "r2" ? "r2://" : "gcs://";
|
|
1861
|
+
const bucket = source.bucket;
|
|
1862
|
+
const prefix = source.prefix ? `/${source.prefix}` : "";
|
|
1863
|
+
return `${protocol}${bucket}${prefix}`;
|
|
1864
|
+
}
|
|
1865
|
+
/**
|
|
1866
|
+
* Get all available file plugin sources
|
|
1867
|
+
*
|
|
1868
|
+
* @returns Array of resolved file sources
|
|
1869
|
+
*/
|
|
1870
|
+
getAvailableSources() {
|
|
1871
|
+
return Array.from(this.sources.values());
|
|
1872
|
+
}
|
|
1873
|
+
/**
|
|
1874
|
+
* Resolve a source by name
|
|
1875
|
+
*
|
|
1876
|
+
* @param name - Source name (e.g., "specs", "logs")
|
|
1877
|
+
* @returns Resolved source or null if not found
|
|
1878
|
+
*/
|
|
1879
|
+
resolveSource(name) {
|
|
1880
|
+
return this.sources.get(name) || null;
|
|
1881
|
+
}
|
|
1882
|
+
/**
|
|
1883
|
+
* Check if a path belongs to any file plugin source
|
|
1884
|
+
*
|
|
1885
|
+
* @param path - File path to check
|
|
1886
|
+
* @returns True if path matches any source's base_path
|
|
1887
|
+
*/
|
|
1888
|
+
isFilePluginPath(path7) {
|
|
1889
|
+
return this.getSourceForPath(path7) !== null;
|
|
1890
|
+
}
|
|
1891
|
+
/**
|
|
1892
|
+
* Get the source for a given path
|
|
1893
|
+
*
|
|
1894
|
+
* Matches path against all source base_paths and returns the matching source.
|
|
1895
|
+
* Uses longest-match strategy if multiple sources match.
|
|
1896
|
+
*
|
|
1897
|
+
* @param path - File path to match
|
|
1898
|
+
* @returns Matching source or null
|
|
1899
|
+
*/
|
|
1900
|
+
getSourceForPath(path7) {
|
|
1901
|
+
let bestMatch = null;
|
|
1902
|
+
let bestMatchLength = 0;
|
|
1903
|
+
for (const source of this.sources.values()) {
|
|
1904
|
+
const normalizedPath = this.normalizePath(path7);
|
|
1905
|
+
const normalizedBasePath = this.normalizePath(source.localPath);
|
|
1906
|
+
if (normalizedPath.startsWith(normalizedBasePath)) {
|
|
1907
|
+
const matchLength = normalizedBasePath.length;
|
|
1908
|
+
if (matchLength > bestMatchLength) {
|
|
1909
|
+
bestMatch = source;
|
|
1910
|
+
bestMatchLength = matchLength;
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
return bestMatch;
|
|
1915
|
+
}
|
|
1916
|
+
/**
|
|
1917
|
+
* Normalize path for comparison
|
|
1918
|
+
* - Remove leading "./" or "/"
|
|
1919
|
+
* - Remove trailing "/"
|
|
1920
|
+
* - Convert to lowercase for case-insensitive comparison
|
|
1921
|
+
*/
|
|
1922
|
+
normalizePath(path7) {
|
|
1923
|
+
return path7.replace(/^\.\//, "").replace(/^\//, "").replace(/\/$/, "").toLowerCase();
|
|
1924
|
+
}
|
|
1925
|
+
/**
|
|
1926
|
+
* Get source names
|
|
1927
|
+
*
|
|
1928
|
+
* @returns Array of source names
|
|
1929
|
+
*/
|
|
1930
|
+
getSourceNames() {
|
|
1931
|
+
return Array.from(this.sources.keys());
|
|
1932
|
+
}
|
|
1933
|
+
/**
|
|
1934
|
+
* Check if sources are configured
|
|
1935
|
+
*
|
|
1936
|
+
* @returns True if any file plugin sources are configured
|
|
1937
|
+
*/
|
|
1938
|
+
hasSources() {
|
|
1939
|
+
return this.sources.size > 0;
|
|
1940
|
+
}
|
|
1941
|
+
};
|
|
1942
|
+
|
|
1943
|
+
// src/storage/errors.ts
|
|
1944
|
+
var FilePluginFileNotFoundError = class _FilePluginFileNotFoundError extends Error {
|
|
1945
|
+
constructor(filePath, sourceName, options) {
|
|
1946
|
+
const includeCloudSuggestions = options?.includeCloudSuggestions !== false;
|
|
1947
|
+
const storageType = options?.storageType;
|
|
1948
|
+
let message = `File not found: ${filePath}
|
|
1949
|
+
|
|
1950
|
+
`;
|
|
1951
|
+
if (includeCloudSuggestions) {
|
|
1952
|
+
if (storageType) {
|
|
1953
|
+
message += `This file may be in cloud storage (${storageType}).
|
|
1954
|
+
|
|
1955
|
+
`;
|
|
1956
|
+
} else {
|
|
1957
|
+
message += `This file may not have been synced from remote storage yet.
|
|
1958
|
+
`;
|
|
1959
|
+
}
|
|
1960
|
+
message += `To fetch from cloud storage, run:
|
|
1961
|
+
`;
|
|
1962
|
+
message += ` file pull ${sourceName}
|
|
1963
|
+
|
|
1964
|
+
`;
|
|
1965
|
+
message += `Or sync all sources:
|
|
1966
|
+
`;
|
|
1967
|
+
message += ` file sync`;
|
|
1968
|
+
} else {
|
|
1969
|
+
message += `Please ensure the file exists locally or pull it from cloud storage.`;
|
|
1970
|
+
}
|
|
1971
|
+
super(message);
|
|
1972
|
+
this.filePath = filePath;
|
|
1973
|
+
this.sourceName = sourceName;
|
|
1974
|
+
this.name = "FilePluginFileNotFoundError";
|
|
1975
|
+
if (Error.captureStackTrace) {
|
|
1976
|
+
Error.captureStackTrace(this, _FilePluginFileNotFoundError);
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
};
|
|
1980
|
+
|
|
1981
|
+
// src/storage/file-plugin.ts
|
|
1982
|
+
var FilePluginStorage = class {
|
|
1983
|
+
constructor(options) {
|
|
1984
|
+
this.options = options;
|
|
1985
|
+
this.sourceResolver = new FileSourceResolver(options.config);
|
|
1986
|
+
this.baseDir = options.baseDir || process.cwd();
|
|
1987
|
+
}
|
|
1988
|
+
name = "file-plugin";
|
|
1989
|
+
type = "local";
|
|
1990
|
+
// Reuse local type for compatibility
|
|
1991
|
+
sourceResolver;
|
|
1992
|
+
baseDir;
|
|
1993
|
+
/**
|
|
1994
|
+
* Check if this provider can handle the reference
|
|
1995
|
+
*
|
|
1996
|
+
* Only handles:
|
|
1997
|
+
* - Current project references
|
|
1998
|
+
* - With sourceType === 'file-plugin'
|
|
1999
|
+
*
|
|
2000
|
+
* @param reference - Resolved reference
|
|
2001
|
+
* @returns True if this provider can handle the reference
|
|
2002
|
+
*/
|
|
2003
|
+
canHandle(reference) {
|
|
2004
|
+
return reference.isCurrentProject && reference.sourceType === "file-plugin";
|
|
2005
|
+
}
|
|
2006
|
+
/**
|
|
2007
|
+
* Fetch content for a reference
|
|
2008
|
+
*
|
|
2009
|
+
* Reads from local filesystem based on the resolved local path.
|
|
2010
|
+
* If file not found and S3 fallback is enabled, throws helpful error.
|
|
2011
|
+
*
|
|
2012
|
+
* @param reference - Resolved reference
|
|
2013
|
+
* @param options - Fetch options (unused for local reads)
|
|
2014
|
+
* @returns Fetch result with content
|
|
2015
|
+
*/
|
|
2016
|
+
async fetch(reference, _options) {
|
|
2017
|
+
if (!reference.localPath) {
|
|
2018
|
+
throw new Error(`File plugin reference missing localPath: ${reference.uri}`);
|
|
2019
|
+
}
|
|
2020
|
+
if (!reference.filePluginSource) {
|
|
2021
|
+
throw new Error(`File plugin reference missing source name: ${reference.uri}`);
|
|
2022
|
+
}
|
|
2023
|
+
const absolutePath = path3.isAbsolute(reference.localPath) ? path3.resolve(reference.localPath) : path3.resolve(this.baseDir, reference.localPath);
|
|
2024
|
+
const source = this.sourceResolver.resolveSource(reference.filePluginSource);
|
|
2025
|
+
if (source) {
|
|
2026
|
+
const allowedDir = path3.resolve(this.baseDir, source.localPath);
|
|
2027
|
+
if (!absolutePath.startsWith(allowedDir + path3.sep) && absolutePath !== allowedDir) {
|
|
2028
|
+
throw new Error(
|
|
2029
|
+
`Path traversal detected: ${reference.localPath} resolves outside allowed directory ${source.localPath}`
|
|
2030
|
+
);
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
try {
|
|
2034
|
+
const content = await fs3.readFile(absolutePath);
|
|
2035
|
+
const contentType = this.detectContentType(absolutePath);
|
|
2036
|
+
return {
|
|
2037
|
+
content,
|
|
2038
|
+
contentType,
|
|
2039
|
+
size: content.length,
|
|
2040
|
+
source: "file-plugin",
|
|
2041
|
+
metadata: {
|
|
2042
|
+
filePluginSource: reference.filePluginSource,
|
|
2043
|
+
localPath: absolutePath
|
|
2044
|
+
}
|
|
2045
|
+
};
|
|
2046
|
+
} catch (error) {
|
|
2047
|
+
if (error.code === "ENOENT") {
|
|
2048
|
+
const source2 = this.sourceResolver.resolveSource(reference.filePluginSource);
|
|
2049
|
+
throw this.createFileNotFoundError(reference, source2);
|
|
2050
|
+
}
|
|
2051
|
+
throw error;
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
/**
|
|
2055
|
+
* Check if a reference exists
|
|
2056
|
+
*
|
|
2057
|
+
* @param reference - Resolved reference
|
|
2058
|
+
* @param options - Fetch options (unused)
|
|
2059
|
+
* @returns True if file exists
|
|
2060
|
+
*/
|
|
2061
|
+
async exists(reference, _options) {
|
|
2062
|
+
if (!reference.localPath) {
|
|
2063
|
+
return false;
|
|
2064
|
+
}
|
|
2065
|
+
const absolutePath = path3.isAbsolute(reference.localPath) ? path3.resolve(reference.localPath) : path3.resolve(this.baseDir, reference.localPath);
|
|
2066
|
+
if (reference.filePluginSource) {
|
|
2067
|
+
const source = this.sourceResolver.resolveSource(reference.filePluginSource);
|
|
2068
|
+
if (source) {
|
|
2069
|
+
const allowedDir = path3.resolve(this.baseDir, source.localPath);
|
|
2070
|
+
if (!absolutePath.startsWith(allowedDir + path3.sep) && absolutePath !== allowedDir) {
|
|
2071
|
+
return false;
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
try {
|
|
2076
|
+
await fs3.access(absolutePath);
|
|
2077
|
+
return true;
|
|
2078
|
+
} catch {
|
|
2079
|
+
return false;
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
/**
|
|
2083
|
+
* Detect content type from file extension
|
|
2084
|
+
*/
|
|
2085
|
+
detectContentType(filePath) {
|
|
2086
|
+
const ext = path3.extname(filePath).toLowerCase();
|
|
2087
|
+
const mimeTypes = {
|
|
2088
|
+
".md": "text/markdown",
|
|
2089
|
+
".txt": "text/plain",
|
|
2090
|
+
".json": "application/json",
|
|
2091
|
+
".yaml": "text/yaml",
|
|
2092
|
+
".yml": "text/yaml",
|
|
2093
|
+
".html": "text/html",
|
|
2094
|
+
".xml": "application/xml",
|
|
2095
|
+
".log": "text/plain",
|
|
2096
|
+
".js": "application/javascript",
|
|
2097
|
+
".ts": "application/typescript",
|
|
2098
|
+
".py": "text/x-python",
|
|
2099
|
+
".sh": "application/x-sh"
|
|
2100
|
+
};
|
|
2101
|
+
return mimeTypes[ext] || "application/octet-stream";
|
|
2102
|
+
}
|
|
2103
|
+
/**
|
|
2104
|
+
* Create a helpful error message when file is not found
|
|
2105
|
+
*/
|
|
2106
|
+
createFileNotFoundError(reference, source) {
|
|
2107
|
+
const includeCloudSuggestions = this.options.enableS3Fallback !== false;
|
|
2108
|
+
const storageType = source?.config.type;
|
|
2109
|
+
return new FilePluginFileNotFoundError(
|
|
2110
|
+
reference.localPath || reference.path || "",
|
|
2111
|
+
reference.filePluginSource || "",
|
|
2112
|
+
{
|
|
2113
|
+
includeCloudSuggestions,
|
|
2114
|
+
storageType
|
|
2115
|
+
}
|
|
2116
|
+
);
|
|
2117
|
+
}
|
|
2118
|
+
};
|
|
1716
2119
|
var execFileAsync = promisify(execFile);
|
|
1717
2120
|
async function execFileNoThrow(command, args = [], options) {
|
|
1718
2121
|
try {
|
|
@@ -1862,10 +2265,10 @@ var S3ArchiveStorage = class {
|
|
|
1862
2265
|
*
|
|
1863
2266
|
* Used to organize archives by type
|
|
1864
2267
|
*/
|
|
1865
|
-
detectType(
|
|
1866
|
-
if (
|
|
1867
|
-
if (
|
|
1868
|
-
if (
|
|
2268
|
+
detectType(path7) {
|
|
2269
|
+
if (path7.startsWith("specs/")) return "specs";
|
|
2270
|
+
if (path7.startsWith("docs/")) return "docs";
|
|
2271
|
+
if (path7.includes("/logs/")) return "logs";
|
|
1869
2272
|
return "misc";
|
|
1870
2273
|
}
|
|
1871
2274
|
/**
|
|
@@ -1876,9 +2279,9 @@ var S3ArchiveStorage = class {
|
|
|
1876
2279
|
* - *.md (all markdown files)
|
|
1877
2280
|
* - docs/*.md (markdown files in docs/)
|
|
1878
2281
|
*/
|
|
1879
|
-
matchesPatterns(
|
|
2282
|
+
matchesPatterns(path7, patterns) {
|
|
1880
2283
|
for (const pattern of patterns) {
|
|
1881
|
-
if (this.matchesPattern(
|
|
2284
|
+
if (this.matchesPattern(path7, pattern)) {
|
|
1882
2285
|
return true;
|
|
1883
2286
|
}
|
|
1884
2287
|
}
|
|
@@ -1887,14 +2290,14 @@ var S3ArchiveStorage = class {
|
|
|
1887
2290
|
/**
|
|
1888
2291
|
* Check if path matches a single pattern
|
|
1889
2292
|
*/
|
|
1890
|
-
matchesPattern(
|
|
2293
|
+
matchesPattern(path7, pattern) {
|
|
1891
2294
|
const DOUBLE_STAR = "\0DOUBLE_STAR\0";
|
|
1892
2295
|
let regexPattern = pattern.replace(/\*\*/g, DOUBLE_STAR);
|
|
1893
2296
|
regexPattern = regexPattern.replace(/[.[\](){}+^$|\\]/g, "\\$&");
|
|
1894
2297
|
regexPattern = regexPattern.replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]");
|
|
1895
2298
|
regexPattern = regexPattern.replace(new RegExp(DOUBLE_STAR, "g"), ".*");
|
|
1896
2299
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
1897
|
-
return regex.test(
|
|
2300
|
+
return regex.test(path7);
|
|
1898
2301
|
}
|
|
1899
2302
|
};
|
|
1900
2303
|
|
|
@@ -1902,14 +2305,61 @@ var S3ArchiveStorage = class {
|
|
|
1902
2305
|
var StorageManager = class {
|
|
1903
2306
|
providers = /* @__PURE__ */ new Map();
|
|
1904
2307
|
priority;
|
|
2308
|
+
codexConfig;
|
|
1905
2309
|
constructor(config = {}) {
|
|
2310
|
+
this.codexConfig = config.codexConfig;
|
|
1906
2311
|
this.providers.set("local", new LocalStorage(config.local));
|
|
1907
2312
|
this.providers.set("github", new GitHubStorage(config.github));
|
|
1908
2313
|
this.providers.set("http", new HttpStorage(config.http));
|
|
1909
2314
|
if (config.s3Archive) {
|
|
1910
2315
|
this.providers.set("s3-archive", new S3ArchiveStorage(config.s3Archive));
|
|
1911
2316
|
}
|
|
1912
|
-
|
|
2317
|
+
if (config.filePlugin) {
|
|
2318
|
+
this.providers.set("file-plugin", new FilePluginStorage(config.filePlugin));
|
|
2319
|
+
}
|
|
2320
|
+
this.priority = config.priority || (config.filePlugin && config.s3Archive ? ["file-plugin", "local", "s3-archive", "github", "http"] : config.filePlugin ? ["file-plugin", "local", "github", "http"] : config.s3Archive ? ["local", "s3-archive", "github", "http"] : ["local", "github", "http"]);
|
|
2321
|
+
}
|
|
2322
|
+
/**
|
|
2323
|
+
* Resolve authentication token for a reference
|
|
2324
|
+
*
|
|
2325
|
+
* Looks up dependency-specific authentication or falls back to default
|
|
2326
|
+
*/
|
|
2327
|
+
resolveToken(reference) {
|
|
2328
|
+
if (!this.codexConfig) {
|
|
2329
|
+
return void 0;
|
|
2330
|
+
}
|
|
2331
|
+
const dependencyKey = `${reference.org}/${reference.project}`;
|
|
2332
|
+
if (this.codexConfig.dependencies?.[dependencyKey]) {
|
|
2333
|
+
const dependency = this.codexConfig.dependencies[dependencyKey];
|
|
2334
|
+
for (const [, sourceConfig] of Object.entries(dependency.sources)) {
|
|
2335
|
+
if (sourceConfig.type === "github") {
|
|
2336
|
+
if (sourceConfig.token_env) {
|
|
2337
|
+
const token = process.env[sourceConfig.token_env];
|
|
2338
|
+
if (token) {
|
|
2339
|
+
return token;
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
if (sourceConfig.token) {
|
|
2343
|
+
return sourceConfig.token;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
const defaultTokenEnv = this.codexConfig.auth?.github?.default_token_env || "GITHUB_TOKEN";
|
|
2349
|
+
return process.env[defaultTokenEnv];
|
|
2350
|
+
}
|
|
2351
|
+
/**
|
|
2352
|
+
* Resolve fetch options with authentication
|
|
2353
|
+
*
|
|
2354
|
+
* Merges reference-specific authentication with provided options
|
|
2355
|
+
*/
|
|
2356
|
+
resolveFetchOptions(reference, options) {
|
|
2357
|
+
const token = this.resolveToken(reference);
|
|
2358
|
+
return {
|
|
2359
|
+
...options,
|
|
2360
|
+
token: options?.token || token
|
|
2361
|
+
// Explicit option overrides resolved token
|
|
2362
|
+
};
|
|
1913
2363
|
}
|
|
1914
2364
|
/**
|
|
1915
2365
|
* Register a custom storage provider
|
|
@@ -1951,8 +2401,10 @@ var StorageManager = class {
|
|
|
1951
2401
|
* Fetch content for a reference
|
|
1952
2402
|
*
|
|
1953
2403
|
* Tries providers in priority order until one succeeds.
|
|
2404
|
+
* Automatically resolves authentication based on dependency configuration.
|
|
1954
2405
|
*/
|
|
1955
2406
|
async fetch(reference, options) {
|
|
2407
|
+
const resolvedOptions = this.resolveFetchOptions(reference, options);
|
|
1956
2408
|
const errors = [];
|
|
1957
2409
|
for (const type of this.priority) {
|
|
1958
2410
|
const provider = this.providers.get(type);
|
|
@@ -1960,7 +2412,7 @@ var StorageManager = class {
|
|
|
1960
2412
|
continue;
|
|
1961
2413
|
}
|
|
1962
2414
|
try {
|
|
1963
|
-
return await provider.fetch(reference,
|
|
2415
|
+
return await provider.fetch(reference, resolvedOptions);
|
|
1964
2416
|
} catch (error) {
|
|
1965
2417
|
errors.push(error instanceof Error ? error : new Error(String(error)));
|
|
1966
2418
|
}
|
|
@@ -1981,15 +2433,17 @@ var StorageManager = class {
|
|
|
1981
2433
|
* Check if content exists for a reference
|
|
1982
2434
|
*
|
|
1983
2435
|
* Returns true if any provider reports the content exists.
|
|
2436
|
+
* Automatically resolves authentication based on dependency configuration.
|
|
1984
2437
|
*/
|
|
1985
2438
|
async exists(reference, options) {
|
|
2439
|
+
const resolvedOptions = this.resolveFetchOptions(reference, options);
|
|
1986
2440
|
for (const type of this.priority) {
|
|
1987
2441
|
const provider = this.providers.get(type);
|
|
1988
2442
|
if (!provider || !provider.canHandle(reference)) {
|
|
1989
2443
|
continue;
|
|
1990
2444
|
}
|
|
1991
2445
|
try {
|
|
1992
|
-
if (await provider.exists(reference,
|
|
2446
|
+
if (await provider.exists(reference, resolvedOptions)) {
|
|
1993
2447
|
return true;
|
|
1994
2448
|
}
|
|
1995
2449
|
} catch {
|
|
@@ -2009,6 +2463,8 @@ var StorageManager = class {
|
|
|
2009
2463
|
}
|
|
2010
2464
|
/**
|
|
2011
2465
|
* Fetch multiple references in parallel
|
|
2466
|
+
*
|
|
2467
|
+
* Automatically resolves authentication for each reference based on dependency configuration.
|
|
2012
2468
|
*/
|
|
2013
2469
|
async fetchMany(references, options) {
|
|
2014
2470
|
const results = /* @__PURE__ */ new Map();
|
|
@@ -2149,7 +2605,7 @@ var CachePersistence = class {
|
|
|
2149
2605
|
}
|
|
2150
2606
|
const [, org, project, filePath] = match;
|
|
2151
2607
|
const relativePath = filePath || "index";
|
|
2152
|
-
return
|
|
2608
|
+
return path3__default.join(this.cacheDir, org, project, relativePath + this.extension);
|
|
2153
2609
|
}
|
|
2154
2610
|
/**
|
|
2155
2611
|
* Get the metadata file path for a URI
|
|
@@ -2165,8 +2621,8 @@ var CachePersistence = class {
|
|
|
2165
2621
|
const metadataPath = this.getMetadataPath(uri);
|
|
2166
2622
|
try {
|
|
2167
2623
|
const [metadataJson, content] = await Promise.all([
|
|
2168
|
-
|
|
2169
|
-
|
|
2624
|
+
fs3__default.readFile(metadataPath, "utf-8"),
|
|
2625
|
+
fs3__default.readFile(cachePath)
|
|
2170
2626
|
]);
|
|
2171
2627
|
const metadata = JSON.parse(metadataJson);
|
|
2172
2628
|
return {
|
|
@@ -2186,32 +2642,32 @@ var CachePersistence = class {
|
|
|
2186
2642
|
async write(entry) {
|
|
2187
2643
|
const cachePath = this.getCachePath(entry.metadata.uri);
|
|
2188
2644
|
const metadataPath = this.getMetadataPath(entry.metadata.uri);
|
|
2189
|
-
await
|
|
2645
|
+
await fs3__default.mkdir(path3__default.dirname(cachePath), { recursive: true });
|
|
2190
2646
|
if (this.atomicWrites) {
|
|
2191
2647
|
const tempCachePath = cachePath + ".tmp";
|
|
2192
2648
|
const tempMetadataPath = metadataPath + ".tmp";
|
|
2193
2649
|
try {
|
|
2194
2650
|
await Promise.all([
|
|
2195
|
-
|
|
2196
|
-
|
|
2651
|
+
fs3__default.writeFile(tempCachePath, entry.content),
|
|
2652
|
+
fs3__default.writeFile(tempMetadataPath, JSON.stringify(entry.metadata, null, 2))
|
|
2197
2653
|
]);
|
|
2198
2654
|
await Promise.all([
|
|
2199
|
-
|
|
2200
|
-
|
|
2655
|
+
fs3__default.rename(tempCachePath, cachePath),
|
|
2656
|
+
fs3__default.rename(tempMetadataPath, metadataPath)
|
|
2201
2657
|
]);
|
|
2202
2658
|
} catch (error) {
|
|
2203
2659
|
await Promise.all([
|
|
2204
|
-
|
|
2660
|
+
fs3__default.unlink(tempCachePath).catch(() => {
|
|
2205
2661
|
}),
|
|
2206
|
-
|
|
2662
|
+
fs3__default.unlink(tempMetadataPath).catch(() => {
|
|
2207
2663
|
})
|
|
2208
2664
|
]);
|
|
2209
2665
|
throw error;
|
|
2210
2666
|
}
|
|
2211
2667
|
} else {
|
|
2212
2668
|
await Promise.all([
|
|
2213
|
-
|
|
2214
|
-
|
|
2669
|
+
fs3__default.writeFile(cachePath, entry.content),
|
|
2670
|
+
fs3__default.writeFile(metadataPath, JSON.stringify(entry.metadata, null, 2))
|
|
2215
2671
|
]);
|
|
2216
2672
|
}
|
|
2217
2673
|
}
|
|
@@ -2222,7 +2678,7 @@ var CachePersistence = class {
|
|
|
2222
2678
|
const cachePath = this.getCachePath(uri);
|
|
2223
2679
|
const metadataPath = this.getMetadataPath(uri);
|
|
2224
2680
|
try {
|
|
2225
|
-
await Promise.all([
|
|
2681
|
+
await Promise.all([fs3__default.unlink(cachePath), fs3__default.unlink(metadataPath)]);
|
|
2226
2682
|
return true;
|
|
2227
2683
|
} catch (error) {
|
|
2228
2684
|
if (error.code === "ENOENT") {
|
|
@@ -2237,7 +2693,7 @@ var CachePersistence = class {
|
|
|
2237
2693
|
async exists(uri) {
|
|
2238
2694
|
const cachePath = this.getCachePath(uri);
|
|
2239
2695
|
try {
|
|
2240
|
-
await
|
|
2696
|
+
await fs3__default.access(cachePath);
|
|
2241
2697
|
return true;
|
|
2242
2698
|
} catch {
|
|
2243
2699
|
return false;
|
|
@@ -2249,20 +2705,20 @@ var CachePersistence = class {
|
|
|
2249
2705
|
async list() {
|
|
2250
2706
|
const uris = [];
|
|
2251
2707
|
try {
|
|
2252
|
-
const orgs = await
|
|
2708
|
+
const orgs = await fs3__default.readdir(this.cacheDir);
|
|
2253
2709
|
for (const org of orgs) {
|
|
2254
|
-
const orgPath =
|
|
2255
|
-
const orgStat = await
|
|
2710
|
+
const orgPath = path3__default.join(this.cacheDir, org);
|
|
2711
|
+
const orgStat = await fs3__default.stat(orgPath);
|
|
2256
2712
|
if (!orgStat.isDirectory()) continue;
|
|
2257
|
-
const projects = await
|
|
2713
|
+
const projects = await fs3__default.readdir(orgPath);
|
|
2258
2714
|
for (const project of projects) {
|
|
2259
|
-
const projectPath =
|
|
2260
|
-
const projectStat = await
|
|
2715
|
+
const projectPath = path3__default.join(orgPath, project);
|
|
2716
|
+
const projectStat = await fs3__default.stat(projectPath);
|
|
2261
2717
|
if (!projectStat.isDirectory()) continue;
|
|
2262
2718
|
const files = await this.listFilesRecursive(projectPath);
|
|
2263
2719
|
for (const file of files) {
|
|
2264
2720
|
if (file.endsWith(this.extension)) {
|
|
2265
|
-
const relativePath =
|
|
2721
|
+
const relativePath = path3__default.relative(projectPath, file);
|
|
2266
2722
|
const filePath = relativePath.slice(0, -this.extension.length);
|
|
2267
2723
|
uris.push(`codex://${org}/${project}/${filePath}`);
|
|
2268
2724
|
}
|
|
@@ -2282,9 +2738,9 @@ var CachePersistence = class {
|
|
|
2282
2738
|
*/
|
|
2283
2739
|
async listFilesRecursive(dir) {
|
|
2284
2740
|
const files = [];
|
|
2285
|
-
const entries = await
|
|
2741
|
+
const entries = await fs3__default.readdir(dir, { withFileTypes: true });
|
|
2286
2742
|
for (const entry of entries) {
|
|
2287
|
-
const fullPath =
|
|
2743
|
+
const fullPath = path3__default.join(dir, entry.name);
|
|
2288
2744
|
if (entry.isDirectory()) {
|
|
2289
2745
|
files.push(...await this.listFilesRecursive(fullPath));
|
|
2290
2746
|
} else if (entry.isFile()) {
|
|
@@ -2299,12 +2755,12 @@ var CachePersistence = class {
|
|
|
2299
2755
|
async clear() {
|
|
2300
2756
|
let count = 0;
|
|
2301
2757
|
try {
|
|
2302
|
-
const orgs = await
|
|
2758
|
+
const orgs = await fs3__default.readdir(this.cacheDir);
|
|
2303
2759
|
for (const org of orgs) {
|
|
2304
|
-
const orgPath =
|
|
2305
|
-
const stat = await
|
|
2760
|
+
const orgPath = path3__default.join(this.cacheDir, org);
|
|
2761
|
+
const stat = await fs3__default.stat(orgPath);
|
|
2306
2762
|
if (stat.isDirectory()) {
|
|
2307
|
-
await
|
|
2763
|
+
await fs3__default.rm(orgPath, { recursive: true });
|
|
2308
2764
|
count++;
|
|
2309
2765
|
}
|
|
2310
2766
|
}
|
|
@@ -2365,7 +2821,7 @@ var CachePersistence = class {
|
|
|
2365
2821
|
* Ensure cache directory exists
|
|
2366
2822
|
*/
|
|
2367
2823
|
async ensureDir() {
|
|
2368
|
-
await
|
|
2824
|
+
await fs3__default.mkdir(this.cacheDir, { recursive: true });
|
|
2369
2825
|
}
|
|
2370
2826
|
/**
|
|
2371
2827
|
* Get cache directory path
|
|
@@ -2413,8 +2869,17 @@ var CacheManager = class {
|
|
|
2413
2869
|
* Get content for a reference
|
|
2414
2870
|
*
|
|
2415
2871
|
* Implements cache-first strategy with stale-while-revalidate.
|
|
2872
|
+
*
|
|
2873
|
+
* EXCEPTION: File plugin sources (current project files) bypass cache entirely.
|
|
2874
|
+
* They are always read fresh from disk for optimal development experience.
|
|
2416
2875
|
*/
|
|
2417
2876
|
async get(reference, options) {
|
|
2877
|
+
if (reference.isCurrentProject && reference.sourceType === "file-plugin") {
|
|
2878
|
+
if (!this.storage) {
|
|
2879
|
+
throw new Error("Storage manager not set");
|
|
2880
|
+
}
|
|
2881
|
+
return await this.storage.fetch(reference, options);
|
|
2882
|
+
}
|
|
2418
2883
|
const ttl = options?.ttl ?? this.config.defaultTtl;
|
|
2419
2884
|
let entry = this.memoryCache.get(reference.uri);
|
|
2420
2885
|
if (!entry && this.persistence) {
|
|
@@ -2620,13 +3085,18 @@ var CacheManager = class {
|
|
|
2620
3085
|
}
|
|
2621
3086
|
/**
|
|
2622
3087
|
* Fetch content and store in cache
|
|
3088
|
+
*
|
|
3089
|
+
* EXCEPTION: File plugin sources are not cached (should not reach here,
|
|
3090
|
+
* but added as safety check).
|
|
2623
3091
|
*/
|
|
2624
3092
|
async fetchAndCache(reference, ttl, options) {
|
|
2625
3093
|
if (!this.storage) {
|
|
2626
3094
|
throw new Error("Storage manager not set");
|
|
2627
3095
|
}
|
|
2628
3096
|
const result = await this.storage.fetch(reference, options);
|
|
2629
|
-
|
|
3097
|
+
if (!(reference.isCurrentProject && reference.sourceType === "file-plugin")) {
|
|
3098
|
+
await this.set(reference.uri, result, ttl);
|
|
3099
|
+
}
|
|
2630
3100
|
return result;
|
|
2631
3101
|
}
|
|
2632
3102
|
/**
|
|
@@ -2745,11 +3215,11 @@ var DEFAULT_SYNC_CONFIG = {
|
|
|
2745
3215
|
deleteOrphans: false,
|
|
2746
3216
|
conflictStrategy: "newest"
|
|
2747
3217
|
};
|
|
2748
|
-
function evaluatePath(
|
|
3218
|
+
function evaluatePath(path7, rules, direction, defaultExcludes = []) {
|
|
2749
3219
|
for (const pattern of defaultExcludes) {
|
|
2750
|
-
if (micromatch3.isMatch(
|
|
3220
|
+
if (micromatch3.isMatch(path7, pattern)) {
|
|
2751
3221
|
return {
|
|
2752
|
-
path:
|
|
3222
|
+
path: path7,
|
|
2753
3223
|
shouldSync: false,
|
|
2754
3224
|
reason: `Excluded by default pattern: ${pattern}`
|
|
2755
3225
|
};
|
|
@@ -2760,9 +3230,9 @@ function evaluatePath(path6, rules, direction, defaultExcludes = []) {
|
|
|
2760
3230
|
if (rule.direction && rule.direction !== direction) {
|
|
2761
3231
|
continue;
|
|
2762
3232
|
}
|
|
2763
|
-
if (micromatch3.isMatch(
|
|
3233
|
+
if (micromatch3.isMatch(path7, rule.pattern)) {
|
|
2764
3234
|
return {
|
|
2765
|
-
path:
|
|
3235
|
+
path: path7,
|
|
2766
3236
|
shouldSync: rule.include,
|
|
2767
3237
|
matchedRule: rule,
|
|
2768
3238
|
reason: rule.include ? `Included by rule: ${rule.pattern}` : `Excluded by rule: ${rule.pattern}`
|
|
@@ -2770,21 +3240,21 @@ function evaluatePath(path6, rules, direction, defaultExcludes = []) {
|
|
|
2770
3240
|
}
|
|
2771
3241
|
}
|
|
2772
3242
|
return {
|
|
2773
|
-
path:
|
|
3243
|
+
path: path7,
|
|
2774
3244
|
shouldSync: true,
|
|
2775
3245
|
reason: "No matching rule, included by default"
|
|
2776
3246
|
};
|
|
2777
3247
|
}
|
|
2778
3248
|
function evaluatePaths(paths, rules, direction, defaultExcludes = []) {
|
|
2779
3249
|
const results = /* @__PURE__ */ new Map();
|
|
2780
|
-
for (const
|
|
2781
|
-
results.set(
|
|
3250
|
+
for (const path7 of paths) {
|
|
3251
|
+
results.set(path7, evaluatePath(path7, rules, direction, defaultExcludes));
|
|
2782
3252
|
}
|
|
2783
3253
|
return results;
|
|
2784
3254
|
}
|
|
2785
3255
|
function filterSyncablePaths(paths, rules, direction, defaultExcludes = []) {
|
|
2786
3256
|
return paths.filter(
|
|
2787
|
-
(
|
|
3257
|
+
(path7) => evaluatePath(path7, rules, direction, defaultExcludes).shouldSync
|
|
2788
3258
|
);
|
|
2789
3259
|
}
|
|
2790
3260
|
function createRulesFromPatterns(include = [], exclude = []) {
|
|
@@ -3050,8 +3520,8 @@ async function scanCodexWithRouting(options) {
|
|
|
3050
3520
|
for (const filePath of allFiles) {
|
|
3051
3521
|
totalScanned++;
|
|
3052
3522
|
try {
|
|
3053
|
-
const fullPath =
|
|
3054
|
-
const stats = await
|
|
3523
|
+
const fullPath = path3__default.join(codexDir, filePath);
|
|
3524
|
+
const stats = await fs3__default.stat(fullPath);
|
|
3055
3525
|
if (stats.size > maxFileSize) {
|
|
3056
3526
|
totalSkipped++;
|
|
3057
3527
|
errors.push({
|
|
@@ -3147,10 +3617,10 @@ async function listAllFilesRecursive(dirPath) {
|
|
|
3147
3617
|
const files = [];
|
|
3148
3618
|
async function scanDirectory(currentPath, relativePath = "") {
|
|
3149
3619
|
try {
|
|
3150
|
-
const entries = await
|
|
3620
|
+
const entries = await fs3__default.readdir(currentPath, { withFileTypes: true });
|
|
3151
3621
|
for (const entry of entries) {
|
|
3152
|
-
const entryPath =
|
|
3153
|
-
const entryRelativePath = relativePath ?
|
|
3622
|
+
const entryPath = path3__default.join(currentPath, entry.name);
|
|
3623
|
+
const entryRelativePath = relativePath ? path3__default.join(relativePath, entry.name) : entry.name;
|
|
3154
3624
|
if (entry.isDirectory()) {
|
|
3155
3625
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build") {
|
|
3156
3626
|
continue;
|
|
@@ -3389,17 +3859,17 @@ var SyncManager = class {
|
|
|
3389
3859
|
if (file.operation === "create" || file.operation === "update") {
|
|
3390
3860
|
const sourcePath = `${plan.source}/${file.path}`;
|
|
3391
3861
|
const targetPath = `${plan.target}/${file.path}`;
|
|
3392
|
-
const
|
|
3393
|
-
const
|
|
3394
|
-
const targetDir =
|
|
3395
|
-
await
|
|
3396
|
-
await
|
|
3862
|
+
const fs5 = await import('fs/promises');
|
|
3863
|
+
const path7 = await import('path');
|
|
3864
|
+
const targetDir = path7.dirname(targetPath);
|
|
3865
|
+
await fs5.mkdir(targetDir, { recursive: true });
|
|
3866
|
+
await fs5.copyFile(sourcePath, targetPath);
|
|
3397
3867
|
synced++;
|
|
3398
3868
|
} else if (file.operation === "delete") {
|
|
3399
3869
|
const targetPath = `${plan.target}/${file.path}`;
|
|
3400
|
-
const
|
|
3870
|
+
const fs5 = await import('fs/promises');
|
|
3401
3871
|
try {
|
|
3402
|
-
await
|
|
3872
|
+
await fs5.unlink(targetPath);
|
|
3403
3873
|
synced++;
|
|
3404
3874
|
} catch (error) {
|
|
3405
3875
|
if (error.code !== "ENOENT") {
|
|
@@ -3454,15 +3924,15 @@ var SyncManager = class {
|
|
|
3454
3924
|
/**
|
|
3455
3925
|
* Get sync status for a file
|
|
3456
3926
|
*/
|
|
3457
|
-
async getFileStatus(
|
|
3927
|
+
async getFileStatus(path7) {
|
|
3458
3928
|
const manifest = await this.loadManifest();
|
|
3459
|
-
return manifest?.entries[
|
|
3929
|
+
return manifest?.entries[path7] ?? null;
|
|
3460
3930
|
}
|
|
3461
3931
|
/**
|
|
3462
3932
|
* Check if a file is synced
|
|
3463
3933
|
*/
|
|
3464
|
-
async isFileSynced(
|
|
3465
|
-
const status = await this.getFileStatus(
|
|
3934
|
+
async isFileSynced(path7) {
|
|
3935
|
+
const status = await this.getFileStatus(path7);
|
|
3466
3936
|
return status !== null;
|
|
3467
3937
|
}
|
|
3468
3938
|
/**
|
|
@@ -3546,19 +4016,19 @@ function ruleMatchesContext(rule, context) {
|
|
|
3546
4016
|
}
|
|
3547
4017
|
return true;
|
|
3548
4018
|
}
|
|
3549
|
-
function ruleMatchesPath(rule,
|
|
3550
|
-
return micromatch3.isMatch(
|
|
4019
|
+
function ruleMatchesPath(rule, path7) {
|
|
4020
|
+
return micromatch3.isMatch(path7, rule.pattern);
|
|
3551
4021
|
}
|
|
3552
4022
|
function ruleMatchesAction(rule, action) {
|
|
3553
4023
|
return rule.actions.includes(action);
|
|
3554
4024
|
}
|
|
3555
|
-
function evaluatePermission(
|
|
4025
|
+
function evaluatePermission(path7, action, context, config) {
|
|
3556
4026
|
const sortedRules = [...config.rules].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
3557
4027
|
for (const rule of sortedRules) {
|
|
3558
4028
|
if (!ruleMatchesContext(rule, context)) {
|
|
3559
4029
|
continue;
|
|
3560
4030
|
}
|
|
3561
|
-
if (!ruleMatchesPath(rule,
|
|
4031
|
+
if (!ruleMatchesPath(rule, path7)) {
|
|
3562
4032
|
continue;
|
|
3563
4033
|
}
|
|
3564
4034
|
if (!ruleMatchesAction(rule, action)) {
|
|
@@ -3577,24 +4047,24 @@ function evaluatePermission(path6, action, context, config) {
|
|
|
3577
4047
|
reason: config.defaultAllow ? "Allowed by default" : "Denied by default"
|
|
3578
4048
|
};
|
|
3579
4049
|
}
|
|
3580
|
-
function isAllowed(
|
|
3581
|
-
const result = evaluatePermission(
|
|
4050
|
+
function isAllowed(path7, action, context, config) {
|
|
4051
|
+
const result = evaluatePermission(path7, action, context, config);
|
|
3582
4052
|
return result.allowed;
|
|
3583
4053
|
}
|
|
3584
|
-
function hasPermission(
|
|
3585
|
-
const result = evaluatePermission(
|
|
4054
|
+
function hasPermission(path7, action, requiredLevel, context, config) {
|
|
4055
|
+
const result = evaluatePermission(path7, action, context, config);
|
|
3586
4056
|
return levelGrants(result.level, requiredLevel);
|
|
3587
4057
|
}
|
|
3588
4058
|
function evaluatePermissions(paths, action, context, config) {
|
|
3589
4059
|
const results = /* @__PURE__ */ new Map();
|
|
3590
|
-
for (const
|
|
3591
|
-
results.set(
|
|
4060
|
+
for (const path7 of paths) {
|
|
4061
|
+
results.set(path7, evaluatePermission(path7, action, context, config));
|
|
3592
4062
|
}
|
|
3593
4063
|
return results;
|
|
3594
4064
|
}
|
|
3595
4065
|
function filterByPermission(paths, action, context, config, requiredLevel = "read") {
|
|
3596
|
-
return paths.filter((
|
|
3597
|
-
const result = evaluatePermission(
|
|
4066
|
+
return paths.filter((path7) => {
|
|
4067
|
+
const result = evaluatePermission(path7, action, context, config);
|
|
3598
4068
|
return levelGrants(result.level, requiredLevel);
|
|
3599
4069
|
});
|
|
3600
4070
|
}
|
|
@@ -3685,21 +4155,21 @@ var PermissionManager = class {
|
|
|
3685
4155
|
/**
|
|
3686
4156
|
* Check if an action is allowed for a path
|
|
3687
4157
|
*/
|
|
3688
|
-
isAllowed(
|
|
3689
|
-
const result = this.evaluate(
|
|
4158
|
+
isAllowed(path7, action, context) {
|
|
4159
|
+
const result = this.evaluate(path7, action, context);
|
|
3690
4160
|
return result.allowed;
|
|
3691
4161
|
}
|
|
3692
4162
|
/**
|
|
3693
4163
|
* Check if a permission level is granted
|
|
3694
4164
|
*/
|
|
3695
|
-
hasPermission(
|
|
3696
|
-
const result = this.evaluate(
|
|
4165
|
+
hasPermission(path7, action, requiredLevel, context) {
|
|
4166
|
+
const result = this.evaluate(path7, action, context);
|
|
3697
4167
|
return levelGrants(result.level, requiredLevel);
|
|
3698
4168
|
}
|
|
3699
4169
|
/**
|
|
3700
4170
|
* Evaluate permission for a path and action
|
|
3701
4171
|
*/
|
|
3702
|
-
evaluate(
|
|
4172
|
+
evaluate(path7, action, context) {
|
|
3703
4173
|
const mergedContext = { ...this.defaultContext, ...context };
|
|
3704
4174
|
if (!this.config.enforced) {
|
|
3705
4175
|
return {
|
|
@@ -3708,7 +4178,7 @@ var PermissionManager = class {
|
|
|
3708
4178
|
reason: "Permissions not enforced"
|
|
3709
4179
|
};
|
|
3710
4180
|
}
|
|
3711
|
-
return evaluatePermission(
|
|
4181
|
+
return evaluatePermission(path7, action, mergedContext, this.config);
|
|
3712
4182
|
}
|
|
3713
4183
|
/**
|
|
3714
4184
|
* Filter paths by permission
|
|
@@ -3811,12 +4281,12 @@ var PermissionManager = class {
|
|
|
3811
4281
|
/**
|
|
3812
4282
|
* Assert permission (throws if denied)
|
|
3813
4283
|
*/
|
|
3814
|
-
assertPermission(
|
|
3815
|
-
const result = this.evaluate(
|
|
4284
|
+
assertPermission(path7, action, requiredLevel = "read", context) {
|
|
4285
|
+
const result = this.evaluate(path7, action, context);
|
|
3816
4286
|
if (!levelGrants(result.level, requiredLevel)) {
|
|
3817
4287
|
throw new PermissionDeniedError(
|
|
3818
|
-
`Permission denied for ${action} on ${
|
|
3819
|
-
|
|
4288
|
+
`Permission denied for ${action} on ${path7}: ${result.reason}`,
|
|
4289
|
+
path7,
|
|
3820
4290
|
action,
|
|
3821
4291
|
result
|
|
3822
4292
|
);
|
|
@@ -3824,9 +4294,9 @@ var PermissionManager = class {
|
|
|
3824
4294
|
}
|
|
3825
4295
|
};
|
|
3826
4296
|
var PermissionDeniedError = class extends Error {
|
|
3827
|
-
constructor(message,
|
|
4297
|
+
constructor(message, path7, action, result) {
|
|
3828
4298
|
super(message);
|
|
3829
|
-
this.path =
|
|
4299
|
+
this.path = path7;
|
|
3830
4300
|
this.action = action;
|
|
3831
4301
|
this.result = result;
|
|
3832
4302
|
this.name = "PermissionDeniedError";
|
|
@@ -4323,8 +4793,8 @@ function convertToUri(reference, options = {}) {
|
|
|
4323
4793
|
const parts = parseReference2(trimmed);
|
|
4324
4794
|
const org = parts.org || options.defaultOrg || "_";
|
|
4325
4795
|
const project = parts.project || options.defaultProject || "_";
|
|
4326
|
-
const
|
|
4327
|
-
return `codex://${org}/${project}/${
|
|
4796
|
+
const path7 = parts.path;
|
|
4797
|
+
return `codex://${org}/${project}/${path7}`;
|
|
4328
4798
|
}
|
|
4329
4799
|
function parseReference2(reference) {
|
|
4330
4800
|
const trimmed = reference.trim();
|
|
@@ -4404,6 +4874,6 @@ function generateReferenceMigrationSummary(results) {
|
|
|
4404
4874
|
return lines.join("\n");
|
|
4405
4875
|
}
|
|
4406
4876
|
|
|
4407
|
-
export { AutoSyncPatternSchema, BUILT_IN_TYPES, CODEX_URI_PREFIX, CacheManager, CachePersistence, CodexConfigSchema, CodexError, CommonRules, ConfigurationError, CustomTypeSchema, DEFAULT_CACHE_DIR, DEFAULT_FETCH_OPTIONS, DEFAULT_MIGRATION_OPTIONS, DEFAULT_PERMISSION_CONFIG, DEFAULT_SYNC_CONFIG, DEFAULT_TYPE, GitHubStorage, HttpStorage, LEGACY_PATTERNS, LEGACY_REF_PREFIX, LocalStorage, MetadataSchema, PERMISSION_LEVEL_ORDER, PermissionDeniedError, PermissionManager, StorageManager, SyncManager, SyncRulesSchema, TTL, TypeRegistry, TypesConfigSchema, ValidationError, buildUri, calculateCachePath, calculateContentHash, convertLegacyReference, convertLegacyReferences, convertToUri, createCacheEntry, createCacheManager, createCachePersistence, createDefaultRegistry, createEmptyModernConfig, createEmptySyncPlan, createGitHubStorage, createHttpStorage, createLocalStorage, createPermissionManager, createRule, createRulesFromPatterns, createStorageManager, createSyncManager, createSyncPlan, deserializeCacheEntry, detectContentType, detectCurrentProject, detectVersion, estimateSyncTime, evaluatePath, evaluatePaths, evaluatePatterns, evaluatePermission, evaluatePermissions, extendType, extractOrgFromRepoName, extractRawFrontmatter, filterByPatterns, filterByPermission, filterPlanOperations, filterSyncablePaths, findLegacyReferences, formatPlanSummary, generateMigrationReport, generateReferenceMigrationSummary, getBuiltInType, getBuiltInTypeNames, getCacheEntryAge, getCacheEntryStatus, getCurrentContext, getCustomSyncDestinations, getDefaultCacheManager, getDefaultConfig, getDefaultDirectories, getDefaultPermissionManager, getDefaultRules, getDefaultStorageManager, getDirectory, getExtension, getFilename, getMigrationRequirements, getPlanStats, getRelativeCachePath, getRemainingTtl, getTargetRepos, hasContentChanged, hasFrontmatter, hasLegacyReferences, hasPermission as hasPermissionLevel, isBuiltInType, isCacheEntryFresh, isCacheEntryValid, isCurrentProjectUri, isLegacyConfig, isLegacyReference, isModernConfig, isAllowed as isPermissionAllowed, isValidUri, levelGrants, loadConfig, loadCustomTypes, matchAnyPattern, matchPattern, maxLevel, mergeFetchOptions, mergeRules, mergeTypes, migrateConfig, migrateFileReferences, minLevel, needsMigration, parseCustomDestination, parseMetadata, parseReference, parseTtl, resolveOrganization, resolveReference, resolveReferences, ruleMatchesAction, ruleMatchesContext, ruleMatchesPath, sanitizePath, serializeCacheEntry, setDefaultCacheManager, setDefaultPermissionManager, setDefaultStorageManager, shouldSyncToRepo, summarizeEvaluations, touchCacheEntry, validateCustomTypes, validateMetadata, validateMigratedConfig, validateOrg, validatePath, validateRules2 as validatePermissionRules, validateProject, validateRules, validateUri };
|
|
4877
|
+
export { AutoSyncPatternSchema, BUILT_IN_TYPES, CODEX_URI_PREFIX, CacheManager, CachePersistence, CodexConfigSchema, CodexError, CommonRules, ConfigurationError, CustomTypeSchema, DEFAULT_CACHE_DIR, DEFAULT_FETCH_OPTIONS, DEFAULT_MIGRATION_OPTIONS, DEFAULT_PERMISSION_CONFIG, DEFAULT_SYNC_CONFIG, DEFAULT_TYPE, FilePluginFileNotFoundError, FilePluginStorage, GitHubStorage, HttpStorage, LEGACY_PATTERNS, LEGACY_REF_PREFIX, LocalStorage, MetadataSchema, PERMISSION_LEVEL_ORDER, PermissionDeniedError, PermissionManager, StorageManager, SyncManager, SyncRulesSchema, TTL, TypeRegistry, TypesConfigSchema, ValidationError, buildUri, calculateCachePath, calculateContentHash, convertLegacyReference, convertLegacyReferences, convertToUri, createCacheEntry, createCacheManager, createCachePersistence, createDefaultRegistry, createEmptyModernConfig, createEmptySyncPlan, createGitHubStorage, createHttpStorage, createLocalStorage, createPermissionManager, createRule, createRulesFromPatterns, createStorageManager, createSyncManager, createSyncPlan, deserializeCacheEntry, detectContentType, detectCurrentProject, detectVersion, estimateSyncTime, evaluatePath, evaluatePaths, evaluatePatterns, evaluatePermission, evaluatePermissions, extendType, extractOrgFromRepoName, extractRawFrontmatter, filterByPatterns, filterByPermission, filterPlanOperations, filterSyncablePaths, findLegacyReferences, formatPlanSummary, generateMigrationReport, generateReferenceMigrationSummary, getBuiltInType, getBuiltInTypeNames, getCacheEntryAge, getCacheEntryStatus, getCurrentContext, getCustomSyncDestinations, getDefaultCacheManager, getDefaultConfig, getDefaultDirectories, getDefaultPermissionManager, getDefaultRules, getDefaultStorageManager, getDirectory, getExtension, getFilename, getMigrationRequirements, getPlanStats, getRelativeCachePath, getRemainingTtl, getTargetRepos, hasContentChanged, hasFrontmatter, hasLegacyReferences, hasPermission as hasPermissionLevel, isBuiltInType, isCacheEntryFresh, isCacheEntryValid, isCurrentProjectUri, isLegacyConfig, isLegacyReference, isModernConfig, isAllowed as isPermissionAllowed, isValidUri, levelGrants, loadConfig, loadCustomTypes, matchAnyPattern, matchPattern, maxLevel, mergeFetchOptions, mergeRules, mergeTypes, migrateConfig, migrateFileReferences, minLevel, needsMigration, parseCustomDestination, parseMetadata, parseReference, parseTtl, resolveOrganization, resolveReference, resolveReferences, ruleMatchesAction, ruleMatchesContext, ruleMatchesPath, sanitizePath, serializeCacheEntry, setDefaultCacheManager, setDefaultPermissionManager, setDefaultStorageManager, shouldSyncToRepo, summarizeEvaluations, touchCacheEntry, validateCustomTypes, validateMetadata, validateMigratedConfig, validateOrg, validatePath, validateRules2 as validatePermissionRules, validateProject, validateRules, validateUri };
|
|
4408
4878
|
//# sourceMappingURL=index.js.map
|
|
4409
4879
|
//# sourceMappingURL=index.js.map
|