@fractary/codex 0.4.0 → 0.5.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 +177 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +176 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,19 +1,119 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var micromatch3 = require('micromatch');
|
|
3
4
|
var path3 = require('path');
|
|
4
5
|
var child_process = require('child_process');
|
|
5
|
-
var micromatch3 = require('micromatch');
|
|
6
6
|
var zod = require('zod');
|
|
7
7
|
var yaml = require('js-yaml');
|
|
8
8
|
var fs2 = require('fs/promises');
|
|
9
9
|
|
|
10
10
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
11
|
|
|
12
|
-
var path3__default = /*#__PURE__*/_interopDefault(path3);
|
|
13
12
|
var micromatch3__default = /*#__PURE__*/_interopDefault(micromatch3);
|
|
13
|
+
var path3__default = /*#__PURE__*/_interopDefault(path3);
|
|
14
14
|
var yaml__default = /*#__PURE__*/_interopDefault(yaml);
|
|
15
15
|
var fs2__default = /*#__PURE__*/_interopDefault(fs2);
|
|
16
16
|
|
|
17
|
+
var __defProp = Object.defineProperty;
|
|
18
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
19
|
+
var __esm = (fn, res) => function __init() {
|
|
20
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
21
|
+
};
|
|
22
|
+
var __export = (target, all) => {
|
|
23
|
+
for (var name in all)
|
|
24
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
25
|
+
};
|
|
26
|
+
function matchPattern(pattern, value) {
|
|
27
|
+
if (pattern === value) return true;
|
|
28
|
+
return micromatch3__default.default.isMatch(value, pattern);
|
|
29
|
+
}
|
|
30
|
+
function matchAnyPattern(patterns, value) {
|
|
31
|
+
if (patterns.length === 1 && patterns[0] === "*") {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
if (patterns.length === 0) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return patterns.some((pattern) => matchPattern(pattern, value));
|
|
38
|
+
}
|
|
39
|
+
function filterByPatterns(patterns, values) {
|
|
40
|
+
return values.filter((value) => matchAnyPattern(patterns, value));
|
|
41
|
+
}
|
|
42
|
+
function evaluatePatterns(options) {
|
|
43
|
+
const { value, include = [], exclude = [] } = options;
|
|
44
|
+
if (exclude.length > 0 && matchAnyPattern(exclude, value)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (include.length === 0) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return matchAnyPattern(include, value);
|
|
51
|
+
}
|
|
52
|
+
var init_matcher = __esm({
|
|
53
|
+
"src/core/patterns/matcher.ts"() {
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// src/sync/directional-patterns.ts
|
|
58
|
+
var directional_patterns_exports = {};
|
|
59
|
+
__export(directional_patterns_exports, {
|
|
60
|
+
expandPlaceholders: () => expandPlaceholders,
|
|
61
|
+
extractProjectFromCodexPath: () => extractProjectFromCodexPath,
|
|
62
|
+
getRelativePath: () => getRelativePath,
|
|
63
|
+
matchFromCodexPattern: () => matchFromCodexPattern,
|
|
64
|
+
matchToCodexPattern: () => matchToCodexPattern
|
|
65
|
+
});
|
|
66
|
+
function matchToCodexPattern(filePath, patterns) {
|
|
67
|
+
if (!patterns || patterns.length === 0) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return patterns.some((pattern) => matchPattern(pattern, filePath));
|
|
71
|
+
}
|
|
72
|
+
function matchFromCodexPattern(codexFilePath, patterns, targetProject) {
|
|
73
|
+
if (!patterns || patterns.length === 0) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return patterns.some((pattern) => {
|
|
77
|
+
const projectSeparatorIndex = pattern.indexOf("/");
|
|
78
|
+
if (projectSeparatorIndex === -1) {
|
|
79
|
+
const fullPattern = `${targetProject}/${pattern}`;
|
|
80
|
+
return matchPattern(fullPattern, codexFilePath);
|
|
81
|
+
}
|
|
82
|
+
const firstSegment = pattern.substring(0, projectSeparatorIndex);
|
|
83
|
+
if (firstSegment.includes(".")) {
|
|
84
|
+
return matchPattern(pattern, codexFilePath);
|
|
85
|
+
} else {
|
|
86
|
+
const fullPattern = `${targetProject}/${pattern}`;
|
|
87
|
+
return matchPattern(fullPattern, codexFilePath);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function extractProjectFromCodexPath(codexFilePath) {
|
|
92
|
+
const firstSlashIndex = codexFilePath.indexOf("/");
|
|
93
|
+
if (firstSlashIndex === -1) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
return codexFilePath.substring(0, firstSlashIndex);
|
|
97
|
+
}
|
|
98
|
+
function getRelativePath(codexFilePath) {
|
|
99
|
+
const firstSlashIndex = codexFilePath.indexOf("/");
|
|
100
|
+
if (firstSlashIndex === -1) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
return codexFilePath.substring(firstSlashIndex + 1);
|
|
104
|
+
}
|
|
105
|
+
function expandPlaceholders(patterns, targetProject) {
|
|
106
|
+
if (!patterns) {
|
|
107
|
+
return patterns;
|
|
108
|
+
}
|
|
109
|
+
return patterns.map((pattern) => pattern.replace(/{project}/g, targetProject));
|
|
110
|
+
}
|
|
111
|
+
var init_directional_patterns = __esm({
|
|
112
|
+
"src/sync/directional-patterns.ts"() {
|
|
113
|
+
init_matcher();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
17
117
|
// src/errors/CodexError.ts
|
|
18
118
|
var CodexError = class _CodexError extends Error {
|
|
19
119
|
constructor(message, options) {
|
|
@@ -730,6 +830,16 @@ var SyncRulesSchema = zod.z.object({
|
|
|
730
830
|
defaultInclude: zod.z.array(zod.z.string()).optional(),
|
|
731
831
|
defaultExclude: zod.z.array(zod.z.string()).optional()
|
|
732
832
|
});
|
|
833
|
+
var DirectionalSyncSchema = zod.z.object({
|
|
834
|
+
// Patterns for files to push from this project to codex
|
|
835
|
+
to_codex: zod.z.array(zod.z.string()).optional(),
|
|
836
|
+
// Patterns for files to pull from codex to this project
|
|
837
|
+
// Format: "project-name/path/pattern" or "project-name/**"
|
|
838
|
+
from_codex: zod.z.array(zod.z.string()).optional(),
|
|
839
|
+
// Org-level defaults (only in codex repository config)
|
|
840
|
+
default_to_codex: zod.z.array(zod.z.string()).optional(),
|
|
841
|
+
default_from_codex: zod.z.array(zod.z.string()).optional()
|
|
842
|
+
});
|
|
733
843
|
var CodexConfigSchema = zod.z.object({
|
|
734
844
|
organizationSlug: zod.z.string(),
|
|
735
845
|
directories: zod.z.object({
|
|
@@ -737,7 +847,9 @@ var CodexConfigSchema = zod.z.object({
|
|
|
737
847
|
target: zod.z.string().optional(),
|
|
738
848
|
systems: zod.z.string().optional()
|
|
739
849
|
}).optional(),
|
|
740
|
-
rules: SyncRulesSchema.optional()
|
|
850
|
+
rules: SyncRulesSchema.optional(),
|
|
851
|
+
// Directional sync configuration
|
|
852
|
+
sync: DirectionalSyncSchema.optional()
|
|
741
853
|
}).strict();
|
|
742
854
|
function parseMetadata(content, options = {}) {
|
|
743
855
|
const { strict = true, normalize = true } = options;
|
|
@@ -812,32 +924,9 @@ function extractRawFrontmatter(content) {
|
|
|
812
924
|
const match = normalized.match(/^---\n([\s\S]*?)\n---\n/);
|
|
813
925
|
return match && match[1] ? match[1] : null;
|
|
814
926
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
}
|
|
819
|
-
function matchAnyPattern(patterns, value) {
|
|
820
|
-
if (patterns.length === 1 && patterns[0] === "*") {
|
|
821
|
-
return true;
|
|
822
|
-
}
|
|
823
|
-
if (patterns.length === 0) {
|
|
824
|
-
return false;
|
|
825
|
-
}
|
|
826
|
-
return patterns.some((pattern) => matchPattern(pattern, value));
|
|
827
|
-
}
|
|
828
|
-
function filterByPatterns(patterns, values) {
|
|
829
|
-
return values.filter((value) => matchAnyPattern(patterns, value));
|
|
830
|
-
}
|
|
831
|
-
function evaluatePatterns(options) {
|
|
832
|
-
const { value, include = [], exclude = [] } = options;
|
|
833
|
-
if (exclude.length > 0 && matchAnyPattern(exclude, value)) {
|
|
834
|
-
return false;
|
|
835
|
-
}
|
|
836
|
-
if (include.length === 0) {
|
|
837
|
-
return true;
|
|
838
|
-
}
|
|
839
|
-
return matchAnyPattern(include, value);
|
|
840
|
-
}
|
|
927
|
+
|
|
928
|
+
// src/core/patterns/index.ts
|
|
929
|
+
init_matcher();
|
|
841
930
|
|
|
842
931
|
// src/core/config/organization.ts
|
|
843
932
|
function resolveOrganization(options = {}) {
|
|
@@ -948,11 +1037,24 @@ function mergeConfigs(base, override) {
|
|
|
948
1037
|
autoSyncPatterns: override.rules?.autoSyncPatterns ?? base.rules?.autoSyncPatterns,
|
|
949
1038
|
defaultInclude: override.rules?.defaultInclude ?? base.rules?.defaultInclude,
|
|
950
1039
|
defaultExclude: override.rules?.defaultExclude ?? base.rules?.defaultExclude
|
|
951
|
-
}
|
|
1040
|
+
},
|
|
1041
|
+
// Only include sync if either base or override has sync config
|
|
1042
|
+
...base.sync || override.sync ? {
|
|
1043
|
+
sync: {
|
|
1044
|
+
...base.sync,
|
|
1045
|
+
...override.sync,
|
|
1046
|
+
// Arrays are replaced, not merged
|
|
1047
|
+
to_codex: override.sync?.to_codex ?? base.sync?.to_codex,
|
|
1048
|
+
from_codex: override.sync?.from_codex ?? base.sync?.from_codex,
|
|
1049
|
+
default_to_codex: override.sync?.default_to_codex ?? base.sync?.default_to_codex,
|
|
1050
|
+
default_from_codex: override.sync?.default_from_codex ?? base.sync?.default_from_codex
|
|
1051
|
+
}
|
|
1052
|
+
} : {}
|
|
952
1053
|
};
|
|
953
1054
|
}
|
|
954
1055
|
|
|
955
1056
|
// src/core/routing/evaluator.ts
|
|
1057
|
+
init_matcher();
|
|
956
1058
|
function shouldSyncToRepo(options) {
|
|
957
1059
|
const {
|
|
958
1060
|
filePath,
|
|
@@ -2727,8 +2829,9 @@ async function scanCodexWithRouting(options) {
|
|
|
2727
2829
|
rules,
|
|
2728
2830
|
storage,
|
|
2729
2831
|
skipNoFrontmatter = false,
|
|
2730
|
-
maxFileSize = 10 * 1024 * 1024
|
|
2832
|
+
maxFileSize = 10 * 1024 * 1024,
|
|
2731
2833
|
// 10MB default
|
|
2834
|
+
fromCodexPatterns
|
|
2732
2835
|
} = options;
|
|
2733
2836
|
const startTime = Date.now();
|
|
2734
2837
|
const routedFiles = [];
|
|
@@ -2736,6 +2839,13 @@ async function scanCodexWithRouting(options) {
|
|
|
2736
2839
|
const errors = [];
|
|
2737
2840
|
let totalScanned = 0;
|
|
2738
2841
|
let totalSkipped = 0;
|
|
2842
|
+
let expandedFromCodexPatterns = fromCodexPatterns;
|
|
2843
|
+
let matchFromCodexPattern2 = null;
|
|
2844
|
+
if (fromCodexPatterns && fromCodexPatterns.length > 0) {
|
|
2845
|
+
const module = await Promise.resolve().then(() => (init_directional_patterns(), directional_patterns_exports));
|
|
2846
|
+
matchFromCodexPattern2 = module.matchFromCodexPattern;
|
|
2847
|
+
expandedFromCodexPatterns = module.expandPlaceholders(fromCodexPatterns, targetProject);
|
|
2848
|
+
}
|
|
2739
2849
|
const allFiles = await listAllFilesRecursive(codexDir);
|
|
2740
2850
|
for (const filePath of allFiles) {
|
|
2741
2851
|
totalScanned++;
|
|
@@ -2752,18 +2862,23 @@ async function scanCodexWithRouting(options) {
|
|
|
2752
2862
|
}
|
|
2753
2863
|
const content = await storage.readText(fullPath);
|
|
2754
2864
|
const parseResult = parseMetadata(content, { strict: false });
|
|
2755
|
-
if (skipNoFrontmatter && Object.keys(parseResult.metadata).length === 0) {
|
|
2865
|
+
if (!matchFromCodexPattern2 && skipNoFrontmatter && Object.keys(parseResult.metadata).length === 0) {
|
|
2756
2866
|
totalSkipped++;
|
|
2757
2867
|
continue;
|
|
2758
2868
|
}
|
|
2759
2869
|
const sourceProject = extractProjectFromPath(filePath, org);
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2870
|
+
let shouldSync = false;
|
|
2871
|
+
if (matchFromCodexPattern2 && expandedFromCodexPatterns && expandedFromCodexPatterns.length > 0) {
|
|
2872
|
+
shouldSync = matchFromCodexPattern2(filePath, expandedFromCodexPatterns, targetProject);
|
|
2873
|
+
} else {
|
|
2874
|
+
shouldSync = shouldSyncToRepo({
|
|
2875
|
+
filePath,
|
|
2876
|
+
fileMetadata: parseResult.metadata,
|
|
2877
|
+
targetRepo: targetProject,
|
|
2878
|
+
sourceRepo: sourceProject,
|
|
2879
|
+
rules
|
|
2880
|
+
});
|
|
2881
|
+
}
|
|
2767
2882
|
if (shouldSync) {
|
|
2768
2883
|
const buffer = Buffer.from(content);
|
|
2769
2884
|
const hash = calculateContentHash(buffer);
|
|
@@ -2914,7 +3029,16 @@ var SyncManager = class {
|
|
|
2914
3029
|
* @param options - Sync options
|
|
2915
3030
|
*/
|
|
2916
3031
|
async createPlan(_org, _project, sourceDir, targetFiles, options) {
|
|
2917
|
-
|
|
3032
|
+
let sourceFiles = await this.listLocalFiles(sourceDir);
|
|
3033
|
+
if (options?.direction === "to-codex") {
|
|
3034
|
+
const toCodexPatterns = this.config.to_codex || this.config.default_to_codex;
|
|
3035
|
+
if (toCodexPatterns) {
|
|
3036
|
+
const { matchToCodexPattern: matchToCodexPattern2 } = await Promise.resolve().then(() => (init_directional_patterns(), directional_patterns_exports));
|
|
3037
|
+
sourceFiles = sourceFiles.filter(
|
|
3038
|
+
(file) => matchToCodexPattern2(file.path, toCodexPatterns)
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
2918
3042
|
const plan = createSyncPlan(
|
|
2919
3043
|
sourceFiles,
|
|
2920
3044
|
targetFiles,
|
|
@@ -2952,13 +3076,16 @@ var SyncManager = class {
|
|
|
2952
3076
|
* ```
|
|
2953
3077
|
*/
|
|
2954
3078
|
async createRoutingAwarePlan(org, project, codexDir, options) {
|
|
3079
|
+
const fromCodexPatterns = this.config.from_codex || this.config.default_from_codex;
|
|
2955
3080
|
const routingScan = await scanCodexWithRouting({
|
|
2956
3081
|
codexDir,
|
|
2957
3082
|
targetProject: project,
|
|
2958
3083
|
org,
|
|
2959
3084
|
rules: void 0,
|
|
2960
3085
|
// Use default routing rules (preventSelfSync, preventCodexSync, etc.)
|
|
2961
|
-
storage: this.localStorage
|
|
3086
|
+
storage: this.localStorage,
|
|
3087
|
+
fromCodexPatterns
|
|
3088
|
+
// Use directional patterns if configured
|
|
2962
3089
|
});
|
|
2963
3090
|
const sourceFiles = routingScan.files.map((rf) => ({
|
|
2964
3091
|
path: rf.path,
|
|
@@ -2967,7 +3094,15 @@ var SyncManager = class {
|
|
|
2967
3094
|
hash: rf.hash
|
|
2968
3095
|
}));
|
|
2969
3096
|
const targetFiles = await this.listLocalFiles(process.cwd());
|
|
2970
|
-
const
|
|
3097
|
+
const planOptions = {
|
|
3098
|
+
direction: options?.direction,
|
|
3099
|
+
force: options?.force,
|
|
3100
|
+
dryRun: options?.dryRun
|
|
3101
|
+
// Explicitly exclude include/exclude to prevent double filtering
|
|
3102
|
+
// include: undefined,
|
|
3103
|
+
// exclude: undefined,
|
|
3104
|
+
};
|
|
3105
|
+
const plan = createSyncPlan(sourceFiles, targetFiles, planOptions, this.config);
|
|
2971
3106
|
plan.estimatedTime = estimateSyncTime(plan);
|
|
2972
3107
|
return {
|
|
2973
3108
|
...plan,
|