@uniformdev/cli 20.57.2-alpha.22 → 20.57.2-alpha.23
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,21 +12,22 @@ 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
|
-
include:
|
|
18
|
-
ids?: string[];
|
|
19
|
-
namePattern?: string;
|
|
20
|
-
};
|
|
24
|
+
include: EntityFilterCriteriaConfig;
|
|
21
25
|
exclude?: never;
|
|
22
26
|
};
|
|
23
27
|
type EntityFilterExclude = {
|
|
24
28
|
include?: never;
|
|
25
29
|
/** If set, entities matching the criteria will be excluded from sync. Cannot be combined with `include`. */
|
|
26
|
-
exclude:
|
|
27
|
-
ids?: string[];
|
|
28
|
-
namePattern?: string;
|
|
29
|
-
};
|
|
30
|
+
exclude: EntityFilterCriteriaConfig;
|
|
30
31
|
};
|
|
31
32
|
type EntityFilterNone = {
|
|
32
33
|
include?: never;
|
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-DlNAs61A.mjs';
|
package/dist/index.mjs
CHANGED
|
@@ -560,68 +560,139 @@ 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 includeNamePattern = resolvedInclude?.namePattern;
|
|
569
|
-
const excludeNamePattern = resolvedExclude?.namePattern;
|
|
570
|
-
const hasInclude = !!(includeIds?.length || includeNamePattern);
|
|
571
|
-
const hasExclude = !!(excludeIds?.length || excludeNamePattern);
|
|
569
|
+
const hasInclude = hasCriteria(resolvedInclude);
|
|
570
|
+
const hasExclude = hasCriteria(resolvedExclude);
|
|
572
571
|
if (hasInclude && hasExclude) {
|
|
573
572
|
const includeSource = directional?.include ? `${operation}.include` : "include";
|
|
574
573
|
const excludeSource = directional?.exclude ? `${operation}.exclude` : "exclude";
|
|
575
574
|
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.`
|
|
575
|
+
`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 { type: 'ids', match: [] } to clear it.`
|
|
577
576
|
);
|
|
578
577
|
}
|
|
579
|
-
return createEntityFilter(
|
|
580
|
-
{ ids: includeIds, namePattern: includeNamePattern },
|
|
581
|
-
{ ids: excludeIds, namePattern: excludeNamePattern }
|
|
582
|
-
);
|
|
578
|
+
return createEntityFilter(resolvedInclude, resolvedExclude);
|
|
583
579
|
}
|
|
584
580
|
function createEntityFilter(include, exclude) {
|
|
585
|
-
const
|
|
586
|
-
const
|
|
587
|
-
const
|
|
588
|
-
const
|
|
589
|
-
const hasInclude = !!(includeIds?.length || includeNamePattern);
|
|
590
|
-
const hasExclude = !!(excludeIds?.length || excludeNamePattern);
|
|
581
|
+
const normalizedInclude = normalizeCriteria(include);
|
|
582
|
+
const normalizedExclude = normalizeCriteria(exclude);
|
|
583
|
+
const hasInclude = hasCriteria(normalizedInclude);
|
|
584
|
+
const hasExclude = hasCriteria(normalizedExclude);
|
|
591
585
|
if (hasInclude && hasExclude) {
|
|
592
586
|
throw new Error("Entity filter cannot have both `include` and `exclude` defined. Use one or the other.");
|
|
593
587
|
}
|
|
594
588
|
if (!hasInclude && !hasExclude) {
|
|
595
589
|
return void 0;
|
|
596
590
|
}
|
|
597
|
-
const includeRegex = includeNamePattern ? safeRegex(includeNamePattern) : void 0;
|
|
598
|
-
const excludeRegex = excludeNamePattern ? safeRegex(excludeNamePattern) : void 0;
|
|
599
591
|
if (hasInclude) {
|
|
600
|
-
|
|
592
|
+
return buildMatcher(normalizedInclude, true);
|
|
593
|
+
}
|
|
594
|
+
return buildMatcher(normalizedExclude, false);
|
|
595
|
+
}
|
|
596
|
+
function normalizeCriteria(criteria) {
|
|
597
|
+
if (Array.isArray(criteria)) {
|
|
598
|
+
return criteria.length > 0 ? { type: "ids", match: criteria } : void 0;
|
|
599
|
+
}
|
|
600
|
+
return criteria;
|
|
601
|
+
}
|
|
602
|
+
var VALID_FILTER_TYPES = ["ids", "nameContains"];
|
|
603
|
+
var VALID_FILTER_FIELDS = ["include", "exclude"];
|
|
604
|
+
var VALID_DIRECTION_KEYS = ["pull", "push"];
|
|
605
|
+
var VALID_ENTITY_CONFIG_KEYS = /* @__PURE__ */ new Set([...VALID_DIRECTION_KEYS, ...VALID_FILTER_FIELDS]);
|
|
606
|
+
function validateEntityConfig(entityConfig, operation) {
|
|
607
|
+
const validKeysLabel = [...VALID_ENTITY_CONFIG_KEYS].join(", ");
|
|
608
|
+
for (const key of Object.keys(entityConfig)) {
|
|
609
|
+
if (!VALID_ENTITY_CONFIG_KEYS.has(key)) {
|
|
610
|
+
const suggestion = VALID_DIRECTION_KEYS.find((valid) => key.startsWith(valid));
|
|
611
|
+
const hint = suggestion ? ` Did you mean "${suggestion}"?` : "";
|
|
612
|
+
throw new Error(`Unknown entity filter key "${key}".${hint} Valid keys are: ${validKeysLabel}.`);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
const directional = entityConfig[operation];
|
|
616
|
+
if (directional && typeof directional === "object") {
|
|
617
|
+
const validFilterLabel = VALID_FILTER_FIELDS.join(", ");
|
|
618
|
+
for (const key of Object.keys(directional)) {
|
|
619
|
+
if (!VALID_FILTER_FIELDS.includes(key)) {
|
|
620
|
+
throw new Error(
|
|
621
|
+
`Unknown key "${key}" in ${operation} filter config. Valid keys are: ${validFilterLabel}.`
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
for (const field of VALID_FILTER_FIELDS) {
|
|
627
|
+
validateFilterValue(entityConfig[field], field);
|
|
628
|
+
}
|
|
629
|
+
if (directional && typeof directional === "object") {
|
|
630
|
+
for (const field of VALID_FILTER_FIELDS) {
|
|
631
|
+
validateFilterValue(directional[field], `${operation}.${field}`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
function validateFilterValue(value, label) {
|
|
636
|
+
if (value === void 0 || value === null) {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
if (typeof value === "string") {
|
|
640
|
+
throw new Error(
|
|
641
|
+
`"${label}" must be an object like { type: 'nameContains', match: '${value}' }, not a plain string.`
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
if (Array.isArray(value)) {
|
|
645
|
+
throw new Error(`"${label}" must be an object like { type: 'ids', match: [...] }, not a plain array.`);
|
|
646
|
+
}
|
|
647
|
+
if (typeof value !== "object") {
|
|
648
|
+
throw new Error(`"${label}" must be an object with "type" and "match" fields, but got ${typeof value}.`);
|
|
649
|
+
}
|
|
650
|
+
const criteria = value;
|
|
651
|
+
if (!criteria.type) {
|
|
652
|
+
throw new Error(
|
|
653
|
+
`${label} is missing required "type" field. Expected one of: ${VALID_FILTER_TYPES.join(", ")}.`
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
if (!VALID_FILTER_TYPES.includes(criteria.type)) {
|
|
657
|
+
throw new Error(
|
|
658
|
+
`${label} has unknown type "${criteria.type}". Expected one of: ${VALID_FILTER_TYPES.join(", ")}.`
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
if (criteria.type === "ids" && !Array.isArray(criteria.match)) {
|
|
662
|
+
throw new Error(
|
|
663
|
+
`${label} with type "ids" requires "match" to be a string array, but got ${typeof criteria.match}.`
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
if (criteria.type === "nameContains" && typeof criteria.match !== "string") {
|
|
667
|
+
throw new Error(
|
|
668
|
+
`${label} with type "nameContains" requires "match" to be a string, but got ${typeof criteria.match}.`
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
function hasCriteria(criteria) {
|
|
673
|
+
if (!criteria) {
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
676
|
+
if (criteria.type === "ids") {
|
|
677
|
+
return criteria.match.length > 0;
|
|
678
|
+
}
|
|
679
|
+
return criteria.match.length > 0;
|
|
680
|
+
}
|
|
681
|
+
function buildMatcher(criteria, isInclude) {
|
|
682
|
+
if (criteria.type === "ids") {
|
|
683
|
+
const idSet = new Set(criteria.match);
|
|
601
684
|
return (obj) => {
|
|
602
685
|
const ids = Array.isArray(obj.id) ? obj.id : [obj.id];
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
return matchesIds && matchesName;
|
|
686
|
+
const matches = ids.some((id) => idSet.has(id));
|
|
687
|
+
return isInclude ? matches : !matches;
|
|
606
688
|
};
|
|
607
689
|
}
|
|
608
|
-
const
|
|
690
|
+
const needle = criteria.match.toLowerCase();
|
|
609
691
|
return (obj) => {
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
const matchesName = excludeRegex ? excludeRegex.test(obj.displayName ?? "") : false;
|
|
613
|
-
return !(matchesIds || matchesName);
|
|
692
|
+
const matches = (obj.displayName ?? "").toLowerCase().includes(needle);
|
|
693
|
+
return isInclude ? matches : !matches;
|
|
614
694
|
};
|
|
615
695
|
}
|
|
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
696
|
|
|
626
697
|
// src/sync/fileSyncEngineDataSource.ts
|
|
627
698
|
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.23+75d5946be1",
|
|
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.23+75d5946be1",
|
|
32
|
+
"@uniformdev/canvas": "20.57.2-alpha.23+75d5946be1",
|
|
33
|
+
"@uniformdev/context": "20.57.2-alpha.23+75d5946be1",
|
|
34
|
+
"@uniformdev/files": "20.57.2-alpha.23+75d5946be1",
|
|
35
|
+
"@uniformdev/project-map": "20.57.2-alpha.23+75d5946be1",
|
|
36
|
+
"@uniformdev/redirect": "20.57.2-alpha.23+75d5946be1",
|
|
37
|
+
"@uniformdev/richtext": "20.57.2-alpha.23+75d5946be1",
|
|
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": "75d5946be1860adc22df527dd84b2d553dd61f54"
|
|
85
85
|
}
|