@uniformdev/cli 20.57.2-alpha.22 → 20.57.2-alpha.24
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/defaultConfig.d.mts
CHANGED
|
@@ -12,11 +12,17 @@ type EntityConfigurationBase = {
|
|
|
12
12
|
format?: SyncFileFormat;
|
|
13
13
|
disabled?: true;
|
|
14
14
|
};
|
|
15
|
+
type EntityFilterCriteriaConfig = {
|
|
16
|
+
type: 'ids';
|
|
17
|
+
match: string[];
|
|
18
|
+
} | {
|
|
19
|
+
type: 'nameContains';
|
|
20
|
+
match: string;
|
|
21
|
+
};
|
|
15
22
|
type EntityFilterInclude = {
|
|
16
23
|
/** If set, only entities matching the criteria will be synced. Cannot be combined with `exclude`. */
|
|
17
24
|
include: {
|
|
18
|
-
|
|
19
|
-
namePattern?: string;
|
|
25
|
+
filters: EntityFilterCriteriaConfig;
|
|
20
26
|
};
|
|
21
27
|
exclude?: never;
|
|
22
28
|
};
|
|
@@ -24,8 +30,7 @@ type EntityFilterExclude = {
|
|
|
24
30
|
include?: never;
|
|
25
31
|
/** If set, entities matching the criteria will be excluded from sync. Cannot be combined with `include`. */
|
|
26
32
|
exclude: {
|
|
27
|
-
|
|
28
|
-
namePattern?: string;
|
|
33
|
+
filters: EntityFilterCriteriaConfig;
|
|
29
34
|
};
|
|
30
35
|
};
|
|
31
36
|
type EntityFilterNone = {
|
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { C as CLIConfiguration } from './index-
|
|
2
|
+
export { C as CLIConfiguration } from './index-B-KaB0aa.mjs';
|
package/dist/index.mjs
CHANGED
|
@@ -560,68 +560,169 @@ async function createArraySyncEngineDataSource({
|
|
|
560
560
|
|
|
561
561
|
// src/sync/entityFilter.ts
|
|
562
562
|
function resolveEntityFilter(entityConfig, operation) {
|
|
563
|
+
if (entityConfig) {
|
|
564
|
+
validateEntityConfig(entityConfig, operation);
|
|
565
|
+
}
|
|
563
566
|
const directional = entityConfig?.[operation];
|
|
564
567
|
const resolvedInclude = directional?.include ?? entityConfig?.include;
|
|
565
568
|
const resolvedExclude = directional?.exclude ?? entityConfig?.exclude;
|
|
566
|
-
const
|
|
567
|
-
const
|
|
568
|
-
const
|
|
569
|
-
const
|
|
570
|
-
const hasInclude = !!(includeIds?.length || includeNamePattern);
|
|
571
|
-
const hasExclude = !!(excludeIds?.length || excludeNamePattern);
|
|
569
|
+
const includeFilters = resolvedInclude?.filters;
|
|
570
|
+
const excludeFilters = resolvedExclude?.filters;
|
|
571
|
+
const hasInclude = hasCriteria(includeFilters);
|
|
572
|
+
const hasExclude = hasCriteria(excludeFilters);
|
|
572
573
|
if (hasInclude && hasExclude) {
|
|
573
574
|
const includeSource = directional?.include ? `${operation}.include` : "include";
|
|
574
575
|
const excludeSource = directional?.exclude ? `${operation}.exclude` : "exclude";
|
|
575
576
|
throw new Error(
|
|
576
|
-
`Entity filter for '${operation}' resolved both ${includeSource} and ${excludeSource}. Use one or the other. If a top-level filter conflicts with a per-direction filter, set the unwanted direction to { ids: [] } to clear it.`
|
|
577
|
+
`Entity filter for '${operation}' resolved both ${includeSource} and ${excludeSource}. Use one or the other. If a top-level filter conflicts with a per-direction filter, set the unwanted direction to { filters: { type: 'ids', match: [] } } to clear it.`
|
|
577
578
|
);
|
|
578
579
|
}
|
|
579
|
-
return createEntityFilter(
|
|
580
|
-
{ ids: includeIds, namePattern: includeNamePattern },
|
|
581
|
-
{ ids: excludeIds, namePattern: excludeNamePattern }
|
|
582
|
-
);
|
|
580
|
+
return createEntityFilter(includeFilters, excludeFilters);
|
|
583
581
|
}
|
|
584
582
|
function createEntityFilter(include, exclude) {
|
|
585
|
-
const
|
|
586
|
-
const
|
|
587
|
-
const
|
|
588
|
-
const
|
|
589
|
-
const hasInclude = !!(includeIds?.length || includeNamePattern);
|
|
590
|
-
const hasExclude = !!(excludeIds?.length || excludeNamePattern);
|
|
583
|
+
const normalizedInclude = normalizeCriteria(include);
|
|
584
|
+
const normalizedExclude = normalizeCriteria(exclude);
|
|
585
|
+
const hasInclude = hasCriteria(normalizedInclude);
|
|
586
|
+
const hasExclude = hasCriteria(normalizedExclude);
|
|
591
587
|
if (hasInclude && hasExclude) {
|
|
592
588
|
throw new Error("Entity filter cannot have both `include` and `exclude` defined. Use one or the other.");
|
|
593
589
|
}
|
|
594
590
|
if (!hasInclude && !hasExclude) {
|
|
595
591
|
return void 0;
|
|
596
592
|
}
|
|
597
|
-
const includeRegex = includeNamePattern ? safeRegex(includeNamePattern) : void 0;
|
|
598
|
-
const excludeRegex = excludeNamePattern ? safeRegex(excludeNamePattern) : void 0;
|
|
599
593
|
if (hasInclude) {
|
|
600
|
-
|
|
594
|
+
return buildMatcher(normalizedInclude, true);
|
|
595
|
+
}
|
|
596
|
+
return buildMatcher(normalizedExclude, false);
|
|
597
|
+
}
|
|
598
|
+
function normalizeCriteria(criteria) {
|
|
599
|
+
if (Array.isArray(criteria)) {
|
|
600
|
+
return criteria.length > 0 ? { type: "ids", match: criteria } : void 0;
|
|
601
|
+
}
|
|
602
|
+
return criteria;
|
|
603
|
+
}
|
|
604
|
+
var VALID_FILTER_TYPES = ["ids", "nameContains"];
|
|
605
|
+
var VALID_FILTER_FIELDS = ["include", "exclude"];
|
|
606
|
+
var VALID_DIRECTION_KEYS = ["pull", "push"];
|
|
607
|
+
var VALID_ENTITY_CONFIG_KEYS = /* @__PURE__ */ new Set([...VALID_DIRECTION_KEYS, ...VALID_FILTER_FIELDS]);
|
|
608
|
+
var VALID_FILTER_BLOCK_KEYS = ["filters"];
|
|
609
|
+
function validateEntityConfig(entityConfig, operation) {
|
|
610
|
+
const validKeysLabel = [...VALID_ENTITY_CONFIG_KEYS].join(", ");
|
|
611
|
+
for (const key of Object.keys(entityConfig)) {
|
|
612
|
+
if (!VALID_ENTITY_CONFIG_KEYS.has(key)) {
|
|
613
|
+
const suggestion = VALID_DIRECTION_KEYS.find((valid) => key.startsWith(valid));
|
|
614
|
+
const hint = suggestion ? ` Did you mean "${suggestion}"?` : "";
|
|
615
|
+
throw new Error(`Unknown entity filter key "${key}".${hint} Valid keys are: ${validKeysLabel}.`);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
const directional = entityConfig[operation];
|
|
619
|
+
if (directional && typeof directional === "object") {
|
|
620
|
+
const validFilterLabel = VALID_FILTER_FIELDS.join(", ");
|
|
621
|
+
for (const key of Object.keys(directional)) {
|
|
622
|
+
if (!VALID_FILTER_FIELDS.includes(key)) {
|
|
623
|
+
throw new Error(
|
|
624
|
+
`Unknown key "${key}" in ${operation} filter config. Valid keys are: ${validFilterLabel}.`
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
for (const field of VALID_FILTER_FIELDS) {
|
|
630
|
+
validateFilterBlock(entityConfig[field], field);
|
|
631
|
+
}
|
|
632
|
+
if (directional && typeof directional === "object") {
|
|
633
|
+
for (const field of VALID_FILTER_FIELDS) {
|
|
634
|
+
validateFilterBlock(directional[field], `${operation}.${field}`);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
function validateFilterBlock(value, label) {
|
|
639
|
+
if (value === void 0 || value === null) {
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
if (typeof value === "string") {
|
|
643
|
+
throw new Error(
|
|
644
|
+
`"${label}" must be an object like { filters: { type: 'nameContains', match: '${value}' } }, not a plain string.`
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
if (Array.isArray(value)) {
|
|
648
|
+
throw new Error(
|
|
649
|
+
`"${label}" must be an object like { filters: { type: 'ids', match: [...] } }, not a plain array.`
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
if (typeof value !== "object") {
|
|
653
|
+
throw new Error(`"${label}" must be an object with a "filters" field, but got ${typeof value}.`);
|
|
654
|
+
}
|
|
655
|
+
const block = value;
|
|
656
|
+
if ("type" in block && "match" in block) {
|
|
657
|
+
throw new Error(
|
|
658
|
+
`"${label}" has "type" and "match" at the top level. Wrap them in a "filters" key: { filters: { type: '${block.type}', match: ... } }.`
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
const validBlockKeysLabel = VALID_FILTER_BLOCK_KEYS.join(", ");
|
|
662
|
+
for (const key of Object.keys(block)) {
|
|
663
|
+
if (!VALID_FILTER_BLOCK_KEYS.includes(key)) {
|
|
664
|
+
throw new Error(`Unknown key "${key}" in ${label}. Valid keys are: ${validBlockKeysLabel}.`);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
if (block.filters !== void 0) {
|
|
668
|
+
validateFilterCriteria(block.filters, `${label}.filters`);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
function validateFilterCriteria(value, label) {
|
|
672
|
+
if (value === void 0 || value === null) {
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
676
|
+
throw new Error(
|
|
677
|
+
`${label} must be an object like { type: 'ids', match: [...] }, but got ${typeof value}.`
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
const criteria = value;
|
|
681
|
+
if (!criteria.type) {
|
|
682
|
+
throw new Error(
|
|
683
|
+
`${label} is missing required "type" field. Expected one of: ${VALID_FILTER_TYPES.join(", ")}.`
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
if (!VALID_FILTER_TYPES.includes(criteria.type)) {
|
|
687
|
+
throw new Error(
|
|
688
|
+
`${label} has unknown type "${criteria.type}". Expected one of: ${VALID_FILTER_TYPES.join(", ")}.`
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
if (criteria.type === "ids" && !Array.isArray(criteria.match)) {
|
|
692
|
+
throw new Error(
|
|
693
|
+
`${label} with type "ids" requires "match" to be a string array, but got ${typeof criteria.match}.`
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
if (criteria.type === "nameContains" && typeof criteria.match !== "string") {
|
|
697
|
+
throw new Error(
|
|
698
|
+
`${label} with type "nameContains" requires "match" to be a string, but got ${typeof criteria.match}.`
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
function hasCriteria(criteria) {
|
|
703
|
+
if (!criteria) {
|
|
704
|
+
return false;
|
|
705
|
+
}
|
|
706
|
+
if (criteria.type === "ids") {
|
|
707
|
+
return criteria.match.length > 0;
|
|
708
|
+
}
|
|
709
|
+
return criteria.match.length > 0;
|
|
710
|
+
}
|
|
711
|
+
function buildMatcher(criteria, isInclude) {
|
|
712
|
+
if (criteria.type === "ids") {
|
|
713
|
+
const idSet = new Set(criteria.match);
|
|
601
714
|
return (obj) => {
|
|
602
715
|
const ids = Array.isArray(obj.id) ? obj.id : [obj.id];
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
return matchesIds && matchesName;
|
|
716
|
+
const matches = ids.some((id) => idSet.has(id));
|
|
717
|
+
return isInclude ? matches : !matches;
|
|
606
718
|
};
|
|
607
719
|
}
|
|
608
|
-
const
|
|
720
|
+
const needle = criteria.match.toLowerCase();
|
|
609
721
|
return (obj) => {
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
const matchesName = excludeRegex ? excludeRegex.test(obj.displayName ?? "") : false;
|
|
613
|
-
return !(matchesIds || matchesName);
|
|
722
|
+
const matches = (obj.displayName ?? "").toLowerCase().includes(needle);
|
|
723
|
+
return isInclude ? matches : !matches;
|
|
614
724
|
};
|
|
615
725
|
}
|
|
616
|
-
function safeRegex(pattern) {
|
|
617
|
-
try {
|
|
618
|
-
return new RegExp(pattern);
|
|
619
|
-
} catch {
|
|
620
|
-
throw new Error(
|
|
621
|
-
`Invalid namePattern regex: "${pattern}". Provide a valid JavaScript regular expression.`
|
|
622
|
-
);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
726
|
|
|
626
727
|
// src/sync/fileSyncEngineDataSource.ts
|
|
627
728
|
import { red } from "colorette";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniformdev/cli",
|
|
3
|
-
"version": "20.57.2-alpha.
|
|
3
|
+
"version": "20.57.2-alpha.24+b45bd27ec0",
|
|
4
4
|
"description": "Uniform command line interface tool",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"main": "./cli.js",
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@inquirer/prompts": "^7.10.1",
|
|
30
30
|
"@thi.ng/mime": "^2.2.23",
|
|
31
|
-
"@uniformdev/assets": "20.57.2-alpha.
|
|
32
|
-
"@uniformdev/canvas": "20.57.2-alpha.
|
|
33
|
-
"@uniformdev/context": "20.57.2-alpha.
|
|
34
|
-
"@uniformdev/files": "20.57.2-alpha.
|
|
35
|
-
"@uniformdev/project-map": "20.57.2-alpha.
|
|
36
|
-
"@uniformdev/redirect": "20.57.2-alpha.
|
|
37
|
-
"@uniformdev/richtext": "20.57.2-alpha.
|
|
31
|
+
"@uniformdev/assets": "20.57.2-alpha.24+b45bd27ec0",
|
|
32
|
+
"@uniformdev/canvas": "20.57.2-alpha.24+b45bd27ec0",
|
|
33
|
+
"@uniformdev/context": "20.57.2-alpha.24+b45bd27ec0",
|
|
34
|
+
"@uniformdev/files": "20.57.2-alpha.24+b45bd27ec0",
|
|
35
|
+
"@uniformdev/project-map": "20.57.2-alpha.24+b45bd27ec0",
|
|
36
|
+
"@uniformdev/redirect": "20.57.2-alpha.24+b45bd27ec0",
|
|
37
|
+
"@uniformdev/richtext": "20.57.2-alpha.24+b45bd27ec0",
|
|
38
38
|
"call-bind": "^1.0.2",
|
|
39
39
|
"colorette": "2.0.20",
|
|
40
40
|
"cosmiconfig": "9.0.0",
|
|
@@ -81,5 +81,5 @@
|
|
|
81
81
|
"publishConfig": {
|
|
82
82
|
"access": "public"
|
|
83
83
|
},
|
|
84
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "b45bd27ec09cbc11c81b4abea2579548c5a57ed1"
|
|
85
85
|
}
|