@fractary/codex 0.11.2 → 0.12.2
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 +235 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +210 -65
- package/dist/index.d.ts +210 -65
- package/dist/index.js +222 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,7 +3,8 @@ import * as path3 from 'path';
|
|
|
3
3
|
import path3__default from 'path';
|
|
4
4
|
import { execFile, execSync } from 'child_process';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
-
import
|
|
6
|
+
import * as yaml2 from 'js-yaml';
|
|
7
|
+
import yaml2__default from 'js-yaml';
|
|
7
8
|
import * as fs3 from 'fs/promises';
|
|
8
9
|
import fs3__default from 'fs/promises';
|
|
9
10
|
import { promisify } from 'util';
|
|
@@ -63,11 +64,14 @@ function matchToCodexPattern(filePath, patterns) {
|
|
|
63
64
|
}
|
|
64
65
|
return patterns.some((pattern) => matchPattern(pattern, filePath));
|
|
65
66
|
}
|
|
66
|
-
function matchFromCodexPattern(codexFilePath, patterns, targetProject) {
|
|
67
|
+
function matchFromCodexPattern(codexFilePath, patterns, targetProject, options) {
|
|
67
68
|
if (!patterns || patterns.length === 0) {
|
|
68
69
|
return false;
|
|
69
70
|
}
|
|
70
71
|
return patterns.some((pattern) => {
|
|
72
|
+
if (pattern.startsWith(CODEX_URI_PREFIX2)) {
|
|
73
|
+
return matchCodexUri(pattern, codexFilePath, targetProject, options);
|
|
74
|
+
}
|
|
71
75
|
if (pattern.startsWith("projects/")) {
|
|
72
76
|
return matchPattern(pattern, codexFilePath);
|
|
73
77
|
}
|
|
@@ -85,6 +89,21 @@ function matchFromCodexPattern(codexFilePath, patterns, targetProject) {
|
|
|
85
89
|
}
|
|
86
90
|
});
|
|
87
91
|
}
|
|
92
|
+
function matchCodexUri(uriPattern, codexFilePath, targetProject, options) {
|
|
93
|
+
let withoutPrefix = uriPattern.slice(CODEX_URI_PREFIX2.length);
|
|
94
|
+
withoutPrefix = withoutPrefix.replace(/{org}/g, options?.org || "").replace(/{project}/g, targetProject).replace(/{codex_repo}/g, options?.codexRepo || "");
|
|
95
|
+
const parts = withoutPrefix.split("/");
|
|
96
|
+
if (parts.length < 2) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const project = parts[1];
|
|
100
|
+
const pathPattern = parts.slice(2).join("/");
|
|
101
|
+
if (!project) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const fullPattern = pathPattern ? `projects/${project}/${pathPattern}` : `projects/${project}/**`;
|
|
105
|
+
return matchPattern(fullPattern, codexFilePath);
|
|
106
|
+
}
|
|
88
107
|
function extractProjectFromCodexPath(codexFilePath) {
|
|
89
108
|
const firstSlashIndex = codexFilePath.indexOf("/");
|
|
90
109
|
if (firstSlashIndex === -1) {
|
|
@@ -99,15 +118,26 @@ function getRelativePath(codexFilePath) {
|
|
|
99
118
|
}
|
|
100
119
|
return codexFilePath.substring(firstSlashIndex + 1);
|
|
101
120
|
}
|
|
102
|
-
function expandPlaceholders(patterns, targetProject) {
|
|
121
|
+
function expandPlaceholders(patterns, targetProject, options) {
|
|
103
122
|
if (!patterns) {
|
|
104
123
|
return patterns;
|
|
105
124
|
}
|
|
106
|
-
return patterns.map((pattern) =>
|
|
125
|
+
return patterns.map((pattern) => {
|
|
126
|
+
let expanded = pattern.replace(/{project}/g, targetProject);
|
|
127
|
+
if (options?.org) {
|
|
128
|
+
expanded = expanded.replace(/{org}/g, options.org);
|
|
129
|
+
}
|
|
130
|
+
if (options?.codexRepo) {
|
|
131
|
+
expanded = expanded.replace(/{codex_repo}/g, options.codexRepo);
|
|
132
|
+
}
|
|
133
|
+
return expanded;
|
|
134
|
+
});
|
|
107
135
|
}
|
|
136
|
+
var CODEX_URI_PREFIX2;
|
|
108
137
|
var init_directional_patterns = __esm({
|
|
109
138
|
"src/sync/directional-patterns.ts"() {
|
|
110
139
|
init_matcher();
|
|
140
|
+
CODEX_URI_PREFIX2 = "codex://";
|
|
111
141
|
}
|
|
112
142
|
});
|
|
113
143
|
|
|
@@ -992,7 +1022,7 @@ function parseMetadata(content, options = {}) {
|
|
|
992
1022
|
const rawFrontmatter = frontmatterMatch[1];
|
|
993
1023
|
const documentContent = frontmatterMatch[2];
|
|
994
1024
|
try {
|
|
995
|
-
const parsed =
|
|
1025
|
+
const parsed = yaml2__default.load(rawFrontmatter);
|
|
996
1026
|
const normalized = normalizeLegacyMetadata(parsed);
|
|
997
1027
|
const metadata = strict ? MetadataSchema.parse(normalized) : MetadataSchema.safeParse(normalized).data || {};
|
|
998
1028
|
return {
|
|
@@ -3505,6 +3535,7 @@ async function scanCodexWithRouting(options) {
|
|
|
3505
3535
|
codexDir,
|
|
3506
3536
|
targetProject,
|
|
3507
3537
|
org,
|
|
3538
|
+
codexRepo,
|
|
3508
3539
|
rules,
|
|
3509
3540
|
storage,
|
|
3510
3541
|
skipNoFrontmatter = false,
|
|
@@ -3523,7 +3554,10 @@ async function scanCodexWithRouting(options) {
|
|
|
3523
3554
|
if (fromCodexPatterns && fromCodexPatterns.length > 0) {
|
|
3524
3555
|
const module = await Promise.resolve().then(() => (init_directional_patterns(), directional_patterns_exports));
|
|
3525
3556
|
matchFromCodexPattern2 = module.matchFromCodexPattern;
|
|
3526
|
-
expandedFromCodexPatterns = module.expandPlaceholders(fromCodexPatterns, targetProject
|
|
3557
|
+
expandedFromCodexPatterns = module.expandPlaceholders(fromCodexPatterns, targetProject, {
|
|
3558
|
+
org,
|
|
3559
|
+
codexRepo
|
|
3560
|
+
});
|
|
3527
3561
|
}
|
|
3528
3562
|
const allFiles = await listAllFilesRecursive(codexDir);
|
|
3529
3563
|
for (const filePath of allFiles) {
|
|
@@ -3545,7 +3579,10 @@ async function scanCodexWithRouting(options) {
|
|
|
3545
3579
|
let parseResult = null;
|
|
3546
3580
|
const useFrontmatter = options.routing?.use_frontmatter === true;
|
|
3547
3581
|
if (matchFromCodexPattern2 && expandedFromCodexPatterns && expandedFromCodexPatterns.length > 0) {
|
|
3548
|
-
shouldSync = matchFromCodexPattern2(filePath, expandedFromCodexPatterns, targetProject
|
|
3582
|
+
shouldSync = matchFromCodexPattern2(filePath, expandedFromCodexPatterns, targetProject, {
|
|
3583
|
+
org,
|
|
3584
|
+
codexRepo
|
|
3585
|
+
});
|
|
3549
3586
|
parseResult = parseMetadata(content, { strict: false });
|
|
3550
3587
|
} else if (useFrontmatter) {
|
|
3551
3588
|
parseResult = parseMetadata(content, { strict: false });
|
|
@@ -3826,6 +3863,8 @@ var SyncManager = class {
|
|
|
3826
3863
|
codexDir,
|
|
3827
3864
|
targetProject: project,
|
|
3828
3865
|
org,
|
|
3866
|
+
codexRepo: options?.codexRepo,
|
|
3867
|
+
// For codex:// URI {codex_repo} placeholder
|
|
3829
3868
|
rules: void 0,
|
|
3830
3869
|
// Use default routing rules (preventSelfSync, preventCodexSync, etc.)
|
|
3831
3870
|
storage: this.localStorage,
|
|
@@ -3891,17 +3930,17 @@ var SyncManager = class {
|
|
|
3891
3930
|
if (file.operation === "create" || file.operation === "update") {
|
|
3892
3931
|
const sourcePath = `${plan.source}/${file.path}`;
|
|
3893
3932
|
const targetPath = `${plan.target}/${file.path}`;
|
|
3894
|
-
const
|
|
3933
|
+
const fs6 = await import('fs/promises');
|
|
3895
3934
|
const path7 = await import('path');
|
|
3896
3935
|
const targetDir = path7.dirname(targetPath);
|
|
3897
|
-
await
|
|
3898
|
-
await
|
|
3936
|
+
await fs6.mkdir(targetDir, { recursive: true });
|
|
3937
|
+
await fs6.copyFile(sourcePath, targetPath);
|
|
3899
3938
|
synced++;
|
|
3900
3939
|
} else if (file.operation === "delete") {
|
|
3901
3940
|
const targetPath = `${plan.target}/${file.path}`;
|
|
3902
|
-
const
|
|
3941
|
+
const fs6 = await import('fs/promises');
|
|
3903
3942
|
try {
|
|
3904
|
-
await
|
|
3943
|
+
await fs6.unlink(targetPath);
|
|
3905
3944
|
synced++;
|
|
3906
3945
|
} catch (error) {
|
|
3907
3946
|
if (error.code !== "ENOENT") {
|
|
@@ -4906,6 +4945,176 @@ function generateReferenceMigrationSummary(results) {
|
|
|
4906
4945
|
return lines.join("\n");
|
|
4907
4946
|
}
|
|
4908
4947
|
|
|
4909
|
-
|
|
4948
|
+
// src/core/env/index.ts
|
|
4949
|
+
function expandEnvVars(value, options = {}) {
|
|
4950
|
+
const env = options.env ?? process.env;
|
|
4951
|
+
return value.replace(/\$\{([^}]+)\}/g, (match, varName) => {
|
|
4952
|
+
const envValue = env[varName];
|
|
4953
|
+
if (envValue === void 0) {
|
|
4954
|
+
if (options.warnOnMissing) {
|
|
4955
|
+
console.warn(`Warning: Environment variable ${varName} is not set`);
|
|
4956
|
+
}
|
|
4957
|
+
if (options.onMissing) {
|
|
4958
|
+
options.onMissing(varName);
|
|
4959
|
+
}
|
|
4960
|
+
return match;
|
|
4961
|
+
}
|
|
4962
|
+
return envValue;
|
|
4963
|
+
});
|
|
4964
|
+
}
|
|
4965
|
+
function expandEnvVarsInConfig(config, options = {}) {
|
|
4966
|
+
if (typeof config === "string") {
|
|
4967
|
+
return expandEnvVars(config, options);
|
|
4968
|
+
}
|
|
4969
|
+
if (Array.isArray(config)) {
|
|
4970
|
+
return config.map((item) => expandEnvVarsInConfig(item, options));
|
|
4971
|
+
}
|
|
4972
|
+
if (config !== null && typeof config === "object") {
|
|
4973
|
+
const result = {};
|
|
4974
|
+
for (const [key, value] of Object.entries(config)) {
|
|
4975
|
+
result[key] = expandEnvVarsInConfig(value, options);
|
|
4976
|
+
}
|
|
4977
|
+
return result;
|
|
4978
|
+
}
|
|
4979
|
+
return config;
|
|
4980
|
+
}
|
|
4981
|
+
function hasEnvVars(value) {
|
|
4982
|
+
return /\$\{[^}]+\}/.test(value);
|
|
4983
|
+
}
|
|
4984
|
+
function extractEnvVarNames(value) {
|
|
4985
|
+
const matches = value.matchAll(/\$\{([^}]+)\}/g);
|
|
4986
|
+
const names = [];
|
|
4987
|
+
for (const match of matches) {
|
|
4988
|
+
if (match[1]) {
|
|
4989
|
+
names.push(match[1]);
|
|
4990
|
+
}
|
|
4991
|
+
}
|
|
4992
|
+
return names;
|
|
4993
|
+
}
|
|
4994
|
+
async function readCodexConfig(configPath, options = {}) {
|
|
4995
|
+
const content = await fs3.readFile(configPath, "utf-8");
|
|
4996
|
+
const rawConfig = yaml2.load(content);
|
|
4997
|
+
let config;
|
|
4998
|
+
if (rawConfig?.codex && typeof rawConfig.codex === "object") {
|
|
4999
|
+
config = rawConfig.codex;
|
|
5000
|
+
} else {
|
|
5001
|
+
config = rawConfig;
|
|
5002
|
+
}
|
|
5003
|
+
if (!config.organization) {
|
|
5004
|
+
throw new Error("Invalid config: organization is required");
|
|
5005
|
+
}
|
|
5006
|
+
if (options.expandEnv !== false) {
|
|
5007
|
+
const envOptions = {
|
|
5008
|
+
env: options.env,
|
|
5009
|
+
warnOnMissing: options.warnOnMissingEnv
|
|
5010
|
+
};
|
|
5011
|
+
config = expandEnvVarsInConfig(config, envOptions);
|
|
5012
|
+
}
|
|
5013
|
+
return config;
|
|
5014
|
+
}
|
|
5015
|
+
async function readUnifiedConfig(configPath, options = {}) {
|
|
5016
|
+
const content = await fs3.readFile(configPath, "utf-8");
|
|
5017
|
+
let config = yaml2.load(content);
|
|
5018
|
+
if (options.expandEnv !== false) {
|
|
5019
|
+
const envOptions = {
|
|
5020
|
+
env: options.env,
|
|
5021
|
+
warnOnMissing: options.warnOnMissingEnv
|
|
5022
|
+
};
|
|
5023
|
+
config = expandEnvVarsInConfig(config, envOptions);
|
|
5024
|
+
}
|
|
5025
|
+
return config;
|
|
5026
|
+
}
|
|
5027
|
+
function isUnifiedConfig(config) {
|
|
5028
|
+
if (config === null || typeof config !== "object") {
|
|
5029
|
+
return false;
|
|
5030
|
+
}
|
|
5031
|
+
const maybeUnified = config;
|
|
5032
|
+
return "codex" in maybeUnified && maybeUnified.codex !== null && typeof maybeUnified.codex === "object";
|
|
5033
|
+
}
|
|
5034
|
+
|
|
5035
|
+
// src/core/utils/index.ts
|
|
5036
|
+
var DURATION_MULTIPLIERS = {
|
|
5037
|
+
s: 1,
|
|
5038
|
+
// seconds
|
|
5039
|
+
m: 60,
|
|
5040
|
+
// minutes
|
|
5041
|
+
h: 3600,
|
|
5042
|
+
// hours
|
|
5043
|
+
d: 86400,
|
|
5044
|
+
// days
|
|
5045
|
+
w: 604800,
|
|
5046
|
+
// weeks (7 days)
|
|
5047
|
+
M: 2592e3,
|
|
5048
|
+
// months (30 days)
|
|
5049
|
+
y: 31536e3
|
|
5050
|
+
// years (365 days)
|
|
5051
|
+
};
|
|
5052
|
+
var SIZE_MULTIPLIERS = {
|
|
5053
|
+
B: 1,
|
|
5054
|
+
KB: 1024,
|
|
5055
|
+
MB: 1024 * 1024,
|
|
5056
|
+
GB: 1024 * 1024 * 1024,
|
|
5057
|
+
TB: 1024 * 1024 * 1024 * 1024
|
|
5058
|
+
};
|
|
5059
|
+
function parseDuration(duration) {
|
|
5060
|
+
if (typeof duration === "number") {
|
|
5061
|
+
return duration;
|
|
5062
|
+
}
|
|
5063
|
+
const match = duration.match(/^(\d+(?:\.\d+)?)\s*([smhdwMy])$/);
|
|
5064
|
+
if (!match || !match[1] || !match[2]) {
|
|
5065
|
+
throw new Error(`Invalid duration format: ${duration}. Use format like "1h", "7d", "1M"`);
|
|
5066
|
+
}
|
|
5067
|
+
const valueStr = match[1];
|
|
5068
|
+
const unit = match[2];
|
|
5069
|
+
const value = parseFloat(valueStr);
|
|
5070
|
+
const multiplier = DURATION_MULTIPLIERS[unit];
|
|
5071
|
+
if (multiplier === void 0) {
|
|
5072
|
+
throw new Error(`Unknown duration unit: ${unit}`);
|
|
5073
|
+
}
|
|
5074
|
+
return Math.round(value * multiplier);
|
|
5075
|
+
}
|
|
5076
|
+
function parseSize(size) {
|
|
5077
|
+
if (typeof size === "number") {
|
|
5078
|
+
return size;
|
|
5079
|
+
}
|
|
5080
|
+
const match = size.match(/^(\d+(?:\.\d+)?)\s*(B|KB|MB|GB|TB)$/i);
|
|
5081
|
+
if (!match || !match[1] || !match[2]) {
|
|
5082
|
+
throw new Error(`Invalid size format: ${size}. Use format like "100MB", "1GB"`);
|
|
5083
|
+
}
|
|
5084
|
+
const valueStr = match[1];
|
|
5085
|
+
const unit = match[2];
|
|
5086
|
+
const value = parseFloat(valueStr);
|
|
5087
|
+
const multiplier = SIZE_MULTIPLIERS[unit.toUpperCase()];
|
|
5088
|
+
if (multiplier === void 0) {
|
|
5089
|
+
throw new Error(`Unknown size unit: ${unit}`);
|
|
5090
|
+
}
|
|
5091
|
+
return Math.round(value * multiplier);
|
|
5092
|
+
}
|
|
5093
|
+
function formatBytes2(bytes) {
|
|
5094
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
5095
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
5096
|
+
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
5097
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
5098
|
+
}
|
|
5099
|
+
function formatDuration(ms) {
|
|
5100
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
5101
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
5102
|
+
if (ms < 36e5) return `${(ms / 6e4).toFixed(1)}m`;
|
|
5103
|
+
return `${(ms / 36e5).toFixed(1)}h`;
|
|
5104
|
+
}
|
|
5105
|
+
function formatSeconds(seconds) {
|
|
5106
|
+
if (seconds < 60) return `${seconds}s`;
|
|
5107
|
+
if (seconds < 3600) return `${(seconds / 60).toFixed(1)}m`;
|
|
5108
|
+
if (seconds < 86400) return `${(seconds / 3600).toFixed(1)}h`;
|
|
5109
|
+
return `${(seconds / 86400).toFixed(1)}d`;
|
|
5110
|
+
}
|
|
5111
|
+
function isValidDuration(value) {
|
|
5112
|
+
return /^\d+(?:\.\d+)?\s*[smhdwMy]$/.test(value);
|
|
5113
|
+
}
|
|
5114
|
+
function isValidSize(value) {
|
|
5115
|
+
return /^\d+(?:\.\d+)?\s*(B|KB|MB|GB|TB)$/i.test(value);
|
|
5116
|
+
}
|
|
5117
|
+
|
|
5118
|
+
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, expandEnvVars, expandEnvVarsInConfig, extendType, extractEnvVarNames, extractOrgFromRepoName, extractRawFrontmatter, filterByPatterns, filterByPermission, filterPlanOperations, filterSyncablePaths, findLegacyReferences, formatBytes2 as formatBytes, formatDuration, formatPlanSummary, formatSeconds, generateMigrationReport, generateReferenceMigrationSummary, getBuiltInType, getBuiltInTypeNames, getCacheEntryAge, getCacheEntryStatus, getCurrentContext, getCustomSyncDestinations, getDefaultCacheManager, getDefaultConfig, getDefaultDirectories, getDefaultPermissionManager, getDefaultRules, getDefaultStorageManager, getDirectory, getExtension, getFilename, getMigrationRequirements, getPlanStats, getRelativeCachePath, getRemainingTtl, getTargetRepos, hasContentChanged, hasEnvVars, hasFrontmatter, hasLegacyReferences, hasPermission as hasPermissionLevel, isBuiltInType, isCacheEntryFresh, isCacheEntryValid, isCurrentProjectUri, isLegacyConfig, isLegacyReference, isModernConfig, isAllowed as isPermissionAllowed, isUnifiedConfig, isValidDuration, isValidSize, isValidUri, levelGrants, loadConfig, loadCustomTypes, matchAnyPattern, matchPattern, maxLevel, mergeFetchOptions, mergeRules, mergeTypes, migrateConfig, migrateFileReferences, minLevel, needsMigration, parseCustomDestination, parseDuration, parseMetadata, parseReference, parseSize, parseTtl, readCodexConfig, readUnifiedConfig, 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 };
|
|
4910
5119
|
//# sourceMappingURL=index.js.map
|
|
4911
5120
|
//# sourceMappingURL=index.js.map
|