@opencrvs/toolkit 2.0.0-rc.fdc585a → 2.0.0-rc.ff04b30
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/create-countryconfig/index.js +73 -0
- package/create-countryconfig/package.json +11 -0
- package/dist/application-config/index.js +27 -28
- package/dist/cli.js +392 -128
- package/dist/commons/api/router.d.ts +3301 -247
- package/dist/commons/conditionals/validate.d.ts +1 -0
- package/dist/commons/events/ActionInput.d.ts +108 -0
- package/dist/commons/events/Draft.d.ts +3 -0
- package/dist/commons/events/EventIndex.d.ts +0 -3
- package/dist/commons/events/EventMetadata.d.ts +0 -7
- package/dist/commons/events/WorkqueueConfig.d.ts +146 -146
- package/dist/commons/events/locations.d.ts +21 -0
- package/dist/commons/events/mocks.test.utils.d.ts +19 -0
- package/dist/commons/events/scopes.d.ts +24 -1
- package/dist/commons/events/state/index.d.ts +0 -4
- package/dist/commons/events/state/utils.d.ts +0 -2
- package/dist/commons/events/utils.d.ts +1 -1
- package/dist/conditionals/index.js +3 -1
- package/dist/events/index.js +109 -76
- package/dist/migrations/v2.0/checkout-upstream-files.d.ts +1 -1
- package/dist/migrations/v2.0/checkout-upstream-files.d.ts.map +1 -1
- package/dist/migrations/v2.0/checkout-upstream-files.js +1 -2
- package/dist/migrations/v2.0/delete-infrastructure-directory.d.ts +9 -1
- package/dist/migrations/v2.0/delete-infrastructure-directory.d.ts.map +1 -1
- package/dist/migrations/v2.0/delete-infrastructure-directory.js +66 -20
- package/dist/migrations/v2.0/fix-accept-requested-registration-function-type.d.ts +3 -0
- package/dist/migrations/v2.0/fix-accept-requested-registration-function-type.d.ts.map +1 -0
- package/dist/migrations/v2.0/fix-accept-requested-registration-function-type.js +110 -0
- package/dist/migrations/v2.0/index.d.ts +5 -3
- package/dist/migrations/v2.0/index.d.ts.map +1 -1
- package/dist/migrations/v2.0/index.js +390 -126
- package/dist/migrations/v2.0/merge-infrastructure-directory.d.ts +11 -1
- package/dist/migrations/v2.0/merge-infrastructure-directory.d.ts.map +1 -1
- package/dist/migrations/v2.0/merge-infrastructure-directory.js +17 -16
- package/dist/migrations/v2.0/migrate-scopes.d.ts.map +1 -1
- package/dist/migrations/v2.0/migrate-scopes.js +54 -30
- package/dist/migrations/v2.0/migrate-workqueue-configs.d.ts.map +1 -1
- package/dist/migrations/v2.0/migrate-workqueue-configs.js +140 -59
- package/dist/notification/index.js +41 -46
- package/dist/scopes/index.js +3 -1
- package/opencrvs-toolkit-2.0.0-rc.ff04b30.tgz +0 -0
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/opencrvs-toolkit-2.0.0-rc.fdc585a.tgz +0 -0
|
@@ -1895,9 +1895,9 @@ function updateRouteHandlers(sourceFiles, group, srcDir, relCwd) {
|
|
|
1895
1895
|
}
|
|
1896
1896
|
return replacedCount;
|
|
1897
1897
|
}
|
|
1898
|
-
function resolveConfigChain(configObj,
|
|
1898
|
+
function resolveConfigChain(configObj, path24) {
|
|
1899
1899
|
let current = configObj;
|
|
1900
|
-
for (const key of
|
|
1900
|
+
for (const key of path24) {
|
|
1901
1901
|
if (!import_ts_morph10.Node.isObjectLiteralExpression(current)) return null;
|
|
1902
1902
|
const prop = current.getProperty(key);
|
|
1903
1903
|
if (!prop || !import_ts_morph10.Node.isPropertyAssignment(prop)) return null;
|
|
@@ -2132,6 +2132,10 @@ Done. Converted ${convertedCount} config file(s), replaced ${totalReplaced} rout
|
|
|
2132
2132
|
var import_ts_morph11 = require("ts-morph");
|
|
2133
2133
|
var import_path11 = __toESM(require("path"));
|
|
2134
2134
|
|
|
2135
|
+
// ../commons/src/scopes.deprecated.do-not-use.ts
|
|
2136
|
+
var z4 = __toESM(require("zod/v4"));
|
|
2137
|
+
var import_lodash = require("lodash");
|
|
2138
|
+
|
|
2135
2139
|
// ../commons/src/scopes.ts
|
|
2136
2140
|
var z3 = __toESM(require("zod/v4"));
|
|
2137
2141
|
var qs = __toESM(require("qs"));
|
|
@@ -2401,11 +2405,12 @@ var decodeScope = (query) => {
|
|
|
2401
2405
|
};
|
|
2402
2406
|
var DEFAULT_SCOPE_OPTIONS = {
|
|
2403
2407
|
placeOfEvent: JurisdictionFilter.enum.all,
|
|
2404
|
-
accessLevel: JurisdictionFilter.enum.all
|
|
2408
|
+
accessLevel: JurisdictionFilter.enum.all,
|
|
2409
|
+
registeredIn: JurisdictionFilter.enum.all,
|
|
2410
|
+
declaredIn: JurisdictionFilter.enum.all
|
|
2405
2411
|
};
|
|
2406
2412
|
|
|
2407
2413
|
// ../commons/src/scopes.deprecated.do-not-use.ts
|
|
2408
|
-
var z4 = __toESM(require("zod/v4"));
|
|
2409
2414
|
var rawConfigurableScopeRegex = /^([a-zA-Z][a-zA-Z0-9.-]*(?:\.[a-zA-Z0-9.-]+)*)\[((?:\w+=[\w.-]+(?:\|[\w.-]+)*)(?:,[\w]+=[\w.-]+(?:\|[\w.-]+)*)*)\]$/;
|
|
2410
2415
|
var rawConfigurableScope = z4.string().regex(rawConfigurableScopeRegex);
|
|
2411
2416
|
var SearchScope = z4.object({
|
|
@@ -2639,6 +2644,74 @@ var legacyScopeToV2Scope = (v1Scope) => {
|
|
|
2639
2644
|
}
|
|
2640
2645
|
throw new Error(`Unsupported V1 scope type: ${v1Scope}`);
|
|
2641
2646
|
};
|
|
2647
|
+
var MERGEABLE_USER_SCOPE_TYPES = ["user.create", "user.edit"];
|
|
2648
|
+
function isMergeableUserScopeType(type) {
|
|
2649
|
+
return MERGEABLE_USER_SCOPE_TYPES.includes(type);
|
|
2650
|
+
}
|
|
2651
|
+
function decodeLegacyScope(legacy) {
|
|
2652
|
+
const encoded = legacyScopeToV2Scope(legacy);
|
|
2653
|
+
const scope = decodeScope(encoded);
|
|
2654
|
+
if (!scope) {
|
|
2655
|
+
throw new Error(
|
|
2656
|
+
`Could not decode migrated scope from legacy '${legacy}' (encoded: '${encoded}').`
|
|
2657
|
+
);
|
|
2658
|
+
}
|
|
2659
|
+
return { legacy, scope };
|
|
2660
|
+
}
|
|
2661
|
+
function groupByType(entries) {
|
|
2662
|
+
return entries.reduce(
|
|
2663
|
+
(groups, entry) => ({
|
|
2664
|
+
...groups,
|
|
2665
|
+
[entry.scope.type]: [...groups[entry.scope.type] ?? [], entry]
|
|
2666
|
+
}),
|
|
2667
|
+
{}
|
|
2668
|
+
);
|
|
2669
|
+
}
|
|
2670
|
+
function deduplicateEntries(entries) {
|
|
2671
|
+
return entries.filter(
|
|
2672
|
+
(entry, index) => entries.findIndex((e) => (0, import_lodash.isEqual)(e.scope, entry.scope)) === index
|
|
2673
|
+
);
|
|
2674
|
+
}
|
|
2675
|
+
function mergeEntries(type, entries) {
|
|
2676
|
+
const optionsList = entries.map(
|
|
2677
|
+
(e) => "options" in e.scope && e.scope.options ? e.scope.options : {}
|
|
2678
|
+
);
|
|
2679
|
+
const allKeys = optionsList.flatMap(
|
|
2680
|
+
(opts) => Object.keys(opts).filter((k) => opts[k] !== void 0)
|
|
2681
|
+
);
|
|
2682
|
+
const conflictKey = allKeys.find((key, i) => allKeys.indexOf(key) !== i);
|
|
2683
|
+
if (conflictKey) {
|
|
2684
|
+
const conflicting = entries.filter(
|
|
2685
|
+
(e) => conflictKey in ("options" in e.scope && e.scope.options || {})
|
|
2686
|
+
).map((e) => JSON.stringify(e.legacy));
|
|
2687
|
+
throw new Error(
|
|
2688
|
+
`Cannot auto-merge two '${type}' scopes that both define '${conflictKey}'. Conflicting legacy scopes: [${conflicting.join(", ")}]. Resolve manually in roles.ts and re-run.`
|
|
2689
|
+
);
|
|
2690
|
+
}
|
|
2691
|
+
const mergedOptions = Object.assign({}, ...optionsList);
|
|
2692
|
+
const merged = Object.keys(mergedOptions).length > 0 ? { type, options: mergedOptions } : { type };
|
|
2693
|
+
const parsed = Scope2.safeParse(merged);
|
|
2694
|
+
if (!parsed.success) {
|
|
2695
|
+
throw new Error(
|
|
2696
|
+
`Merged '${type}' scope failed schema validation: ${parsed.error.message}. Legacy scopes: [${entries.map((e) => JSON.stringify(e.legacy)).join(", ")}].`
|
|
2697
|
+
);
|
|
2698
|
+
}
|
|
2699
|
+
return parsed.data;
|
|
2700
|
+
}
|
|
2701
|
+
function migrateLegacyScopesArrayToV2Scopes(legacyScopes) {
|
|
2702
|
+
const groups = groupByType(legacyScopes.map(decodeLegacyScope));
|
|
2703
|
+
return Object.entries(groups).flatMap(([type, entries]) => {
|
|
2704
|
+
const deduped = deduplicateEntries(entries);
|
|
2705
|
+
if (deduped.length <= 1) return deduped.map((e) => e.scope);
|
|
2706
|
+
if (!isMergeableUserScopeType(type)) {
|
|
2707
|
+
console.warn(
|
|
2708
|
+
`Multiple non-mergeable '${type}' scopes detected after dedup \u2014 kept all as-is. Legacy scopes: [${deduped.map((e) => JSON.stringify(e.legacy)).join(", ")}]. Review whether the duplication is intentional.`
|
|
2709
|
+
);
|
|
2710
|
+
return deduped.map((e) => e.scope);
|
|
2711
|
+
}
|
|
2712
|
+
return [mergeEntries(type, deduped)];
|
|
2713
|
+
});
|
|
2714
|
+
}
|
|
2642
2715
|
|
|
2643
2716
|
// src/migrations/v2.0/migrate-scopes.ts
|
|
2644
2717
|
var ROLES_FILE_RELATIVE_PATH = "src/data-seeding/roles/roles.ts";
|
|
@@ -2676,57 +2749,65 @@ function resolveLegacyScopeFromElement(element) {
|
|
|
2676
2749
|
}
|
|
2677
2750
|
function migrateScopesArrays(rolesFilePath, project) {
|
|
2678
2751
|
const sourceFile = project.getSourceFile(rolesFilePath);
|
|
2679
|
-
if (!sourceFile)
|
|
2752
|
+
if (!sourceFile) {
|
|
2753
|
+
return { migratedCount: 0, removedCount: 0, mergedCount: 0 };
|
|
2754
|
+
}
|
|
2680
2755
|
let migratedCount = 0;
|
|
2681
2756
|
let removedCount = 0;
|
|
2757
|
+
let mergedCount = 0;
|
|
2682
2758
|
const scopesProperties = sourceFile.getDescendantsOfKind(import_ts_morph11.SyntaxKind.PropertyAssignment).filter((prop) => prop.getName() === SCOPES_PROPERTY_NAME);
|
|
2759
|
+
const relPath = import_path11.default.relative(process.cwd(), rolesFilePath);
|
|
2683
2760
|
for (const scopesProp of scopesProperties) {
|
|
2684
2761
|
const initializer = scopesProp.getInitializer();
|
|
2685
2762
|
if (!initializer || !import_ts_morph11.Node.isArrayLiteralExpression(initializer)) continue;
|
|
2686
|
-
const
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2763
|
+
const rawTexts = [];
|
|
2764
|
+
const legacyStrings = [];
|
|
2765
|
+
let anyChange = false;
|
|
2766
|
+
for (const element of initializer.getElements()) {
|
|
2690
2767
|
const scopeKey = resolveScopeKeyFromElementAccess(element);
|
|
2691
2768
|
if (scopeKey && !(scopeKey in SCOPES)) {
|
|
2692
2769
|
console.warn(
|
|
2693
|
-
` [${
|
|
2770
|
+
` [${relPath}] Removing unknown scope reference: SCOPES.${scopeKey}`
|
|
2694
2771
|
);
|
|
2695
|
-
initializer.removeElement(index);
|
|
2696
2772
|
removedCount++;
|
|
2773
|
+
anyChange = true;
|
|
2697
2774
|
continue;
|
|
2698
2775
|
}
|
|
2699
2776
|
const legacyScope = resolveLegacyScopeFromElement(element);
|
|
2700
2777
|
if (!legacyScope) {
|
|
2701
2778
|
console.warn(
|
|
2702
|
-
` [${
|
|
2779
|
+
` [${relPath}] Preserving non-literal scope expression verbatim: ${element.getText()}`
|
|
2703
2780
|
);
|
|
2781
|
+
rawTexts.push(element.getText());
|
|
2704
2782
|
continue;
|
|
2705
2783
|
}
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
console.warn(
|
|
2719
|
-
` [${import_path11.default.relative(process.cwd(), rolesFilePath)}] Could not migrate scope '${legacyScope}': ${error}`
|
|
2720
|
-
);
|
|
2721
|
-
}
|
|
2784
|
+
legacyStrings.push(legacyScope);
|
|
2785
|
+
anyChange = true;
|
|
2786
|
+
}
|
|
2787
|
+
if (!anyChange) continue;
|
|
2788
|
+
let mergedScopes;
|
|
2789
|
+
try {
|
|
2790
|
+
mergedScopes = migrateLegacyScopesArrayToV2Scopes(legacyStrings);
|
|
2791
|
+
} catch (error) {
|
|
2792
|
+
throw new Error(
|
|
2793
|
+
`[${relPath}] Failed to migrate scopes for role: ${error instanceof Error ? error.message : String(error)}`,
|
|
2794
|
+
{ cause: error }
|
|
2795
|
+
);
|
|
2722
2796
|
}
|
|
2797
|
+
migratedCount += legacyStrings.length;
|
|
2798
|
+
mergedCount += legacyStrings.length - mergedScopes.length;
|
|
2799
|
+
const outputElements = [
|
|
2800
|
+
...rawTexts,
|
|
2801
|
+
...mergedScopes.map((s) => JSON.stringify(s))
|
|
2802
|
+
];
|
|
2803
|
+
scopesProp.setInitializer(`[${outputElements.join(", ")}]`);
|
|
2723
2804
|
}
|
|
2724
2805
|
if (removedCount > 0) {
|
|
2725
2806
|
console.log(
|
|
2726
|
-
` Removed ${removedCount} unknown SCOPES reference(s) from '${
|
|
2807
|
+
` Removed ${removedCount} unknown SCOPES reference(s) from '${relPath}'.`
|
|
2727
2808
|
);
|
|
2728
2809
|
}
|
|
2729
|
-
return { migratedCount, removedCount };
|
|
2810
|
+
return { migratedCount, removedCount, mergedCount };
|
|
2730
2811
|
}
|
|
2731
2812
|
function ensureScopesHelpersImport(rolesFilePath, project) {
|
|
2732
2813
|
const sourceFile = project.getSourceFile(rolesFilePath);
|
|
@@ -2861,7 +2942,7 @@ async function main11() {
|
|
|
2861
2942
|
return;
|
|
2862
2943
|
}
|
|
2863
2944
|
const importChanged = ensureScopesHelpersImport(rolesFilePath, project);
|
|
2864
|
-
const { migratedCount, removedCount } = migrateScopesArrays(
|
|
2945
|
+
const { migratedCount, removedCount, mergedCount } = migrateScopesArrays(
|
|
2865
2946
|
rolesFilePath,
|
|
2866
2947
|
project
|
|
2867
2948
|
);
|
|
@@ -2880,7 +2961,7 @@ async function main11() {
|
|
|
2880
2961
|
}
|
|
2881
2962
|
await sourceFile.save();
|
|
2882
2963
|
console.log(
|
|
2883
|
-
`Done. Migrated ${migratedCount} legacy scope(s), removed ${removedCount} unknown SCOPES reference(s), wrapped ${wrappedScopesCount} scope array(s) with defineScopes()${wrappedRoles ? ", wrapped roles with defineRoles()" : ""}${removedRoleType ? ", and removed Role type definition" : ""}${importChanged ? ". Updated toolkit/scopes imports." : "."}`
|
|
2964
|
+
`Done. Migrated ${migratedCount} legacy scope(s), merged ${mergedCount} AND-paired scope(s) into single v2 objects (privilege-escalation fix, see issue #12489), removed ${removedCount} unknown SCOPES reference(s), wrapped ${wrappedScopesCount} scope array(s) with defineScopes()${wrappedRoles ? ", wrapped roles with defineRoles()" : ""}${removedRoleType ? ", and removed Role type definition" : ""}${importChanged ? ". Updated toolkit/scopes imports." : "."}`
|
|
2884
2965
|
);
|
|
2885
2966
|
}
|
|
2886
2967
|
|
|
@@ -3686,6 +3767,10 @@ var ACTION_PROPERTY_NAME2 = "action";
|
|
|
3686
3767
|
var CONDITIONALS_PROPERTY_NAME = "conditionals";
|
|
3687
3768
|
var TYPE_PROPERTY_NAME7 = "type";
|
|
3688
3769
|
var SLUG_PROPERTY_NAME = "slug";
|
|
3770
|
+
var READ_ACTION_TYPE = "READ";
|
|
3771
|
+
var ACTION_TYPE_IMPORT_NAME = "ActionType";
|
|
3772
|
+
var TOOLKIT_EVENTS_MODULE2 = "@opencrvs/toolkit/events";
|
|
3773
|
+
var READ_ACTION_FALLBACK_INITIALIZER = `{ type: ${ACTION_TYPE_IMPORT_NAME}.${READ_ACTION_TYPE} }`;
|
|
3689
3774
|
var SUPPORTED_WORKQUEUE_ACTION_TYPES = /* @__PURE__ */ new Set([
|
|
3690
3775
|
"READ",
|
|
3691
3776
|
"DELETE",
|
|
@@ -3733,91 +3818,137 @@ function isUnsupportedActionType(action) {
|
|
|
3733
3818
|
}
|
|
3734
3819
|
return !SUPPORTED_WORKQUEUE_ACTION_TYPES.has(typeName);
|
|
3735
3820
|
}
|
|
3736
|
-
function
|
|
3737
|
-
const
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3821
|
+
function ensureValidAction(workqueue, relPath) {
|
|
3822
|
+
const workqueueLabel = getWorkqueueLabel(workqueue);
|
|
3823
|
+
const actionProperty = workqueue.getProperty(ACTION_PROPERTY_NAME2);
|
|
3824
|
+
if (actionProperty && import_ts_morph17.Node.isPropertyAssignment(actionProperty)) {
|
|
3825
|
+
const initializer = actionProperty.getInitializer();
|
|
3826
|
+
if (initializer && import_ts_morph17.Node.isObjectLiteralExpression(initializer)) {
|
|
3827
|
+
if (!isUnsupportedActionType(initializer)) {
|
|
3828
|
+
return { changed: false, usedReadFallback: false };
|
|
3829
|
+
}
|
|
3830
|
+
actionProperty.set({
|
|
3831
|
+
name: ACTION_PROPERTY_NAME2,
|
|
3832
|
+
initializer: READ_ACTION_FALLBACK_INITIALIZER
|
|
3833
|
+
});
|
|
3834
|
+
console.log(
|
|
3835
|
+
` [${relPath}] Replaced unsupported 'action' type with '${ACTION_TYPE_IMPORT_NAME}.${READ_ACTION_TYPE}' on workqueue '${workqueueLabel}'`
|
|
3836
|
+
);
|
|
3837
|
+
return { changed: true, usedReadFallback: true };
|
|
3838
|
+
}
|
|
3744
3839
|
}
|
|
3840
|
+
workqueue.addPropertyAssignment({
|
|
3841
|
+
name: ACTION_PROPERTY_NAME2,
|
|
3842
|
+
initializer: READ_ACTION_FALLBACK_INITIALIZER
|
|
3843
|
+
});
|
|
3844
|
+
console.log(
|
|
3845
|
+
` [${relPath}] Added default 'action: ${READ_ACTION_FALLBACK_INITIALIZER}' to workqueue '${workqueueLabel}'`
|
|
3846
|
+
);
|
|
3847
|
+
return { changed: true, usedReadFallback: true };
|
|
3848
|
+
}
|
|
3849
|
+
function migrateWorkqueueActions(workqueue, relPath) {
|
|
3745
3850
|
const workqueueLabel = getWorkqueueLabel(workqueue);
|
|
3746
|
-
const
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3851
|
+
const actionsProperty = workqueue.getProperty(ACTIONS_PROPERTY_NAME5);
|
|
3852
|
+
let actionsArrayMigrated = false;
|
|
3853
|
+
if (actionsProperty && import_ts_morph17.Node.isPropertyAssignment(actionsProperty)) {
|
|
3854
|
+
const actionsInitializer = actionsProperty.getInitializer();
|
|
3855
|
+
if (actionsInitializer && import_ts_morph17.Node.isArrayLiteralExpression(actionsInitializer)) {
|
|
3856
|
+
const existingActionProperty = workqueue.getProperty(ACTION_PROPERTY_NAME2);
|
|
3857
|
+
if (existingActionProperty) {
|
|
3858
|
+
if (import_ts_morph17.Node.isPropertyAssignment(existingActionProperty)) {
|
|
3859
|
+
const existingActionInitializer = existingActionProperty.getInitializer();
|
|
3860
|
+
if (existingActionInitializer && import_ts_morph17.Node.isObjectLiteralExpression(existingActionInitializer)) {
|
|
3861
|
+
const conditionalsProperty = existingActionInitializer.getProperty(
|
|
3862
|
+
CONDITIONALS_PROPERTY_NAME
|
|
3863
|
+
);
|
|
3864
|
+
if (conditionalsProperty) {
|
|
3865
|
+
conditionalsProperty.remove();
|
|
3866
|
+
console.log(
|
|
3867
|
+
` [${relPath}] Removed deprecated 'conditionals' from 'action' on workqueue '${workqueueLabel}'`
|
|
3868
|
+
);
|
|
3869
|
+
}
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
actionsProperty.remove();
|
|
3873
|
+
console.log(
|
|
3874
|
+
` [${relPath}] Removed deprecated 'actions' from workqueue '${workqueueLabel}' (existing 'action' kept)`
|
|
3875
|
+
);
|
|
3876
|
+
actionsArrayMigrated = true;
|
|
3877
|
+
} else {
|
|
3878
|
+
const actionCandidates = actionsInitializer.getElements().filter(
|
|
3879
|
+
(element) => import_ts_morph17.Node.isObjectLiteralExpression(element)
|
|
3753
3880
|
);
|
|
3754
|
-
if (
|
|
3755
|
-
|
|
3881
|
+
if (actionCandidates.length === 0) {
|
|
3882
|
+
actionsProperty.remove();
|
|
3756
3883
|
console.log(
|
|
3757
|
-
` [${relPath}] Removed
|
|
3884
|
+
` [${relPath}] Removed empty 'actions' from workqueue '${workqueueLabel}'`
|
|
3758
3885
|
);
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3886
|
+
actionsArrayMigrated = true;
|
|
3887
|
+
} else {
|
|
3888
|
+
if (actionCandidates.length > 1) {
|
|
3889
|
+
const droppedCount = actionCandidates.length - 1;
|
|
3890
|
+
console.warn(
|
|
3891
|
+
` [${relPath}] Workqueue '${workqueueLabel}' has ${actionCandidates.length} actions; keeping first as 'action' and dropping ${droppedCount} extra action(s)`
|
|
3892
|
+
);
|
|
3893
|
+
}
|
|
3894
|
+
const conditionalsProperty = actionCandidates[0].getProperty(
|
|
3895
|
+
CONDITIONALS_PROPERTY_NAME
|
|
3764
3896
|
);
|
|
3897
|
+
if (conditionalsProperty) {
|
|
3898
|
+
conditionalsProperty.remove();
|
|
3899
|
+
console.log(
|
|
3900
|
+
` [${relPath}] Removed deprecated 'conditionals' from migrated 'action' on workqueue '${workqueueLabel}'`
|
|
3901
|
+
);
|
|
3902
|
+
}
|
|
3903
|
+
if (isUnsupportedActionType(actionCandidates[0])) {
|
|
3904
|
+
actionsProperty.remove();
|
|
3905
|
+
console.log(
|
|
3906
|
+
` [${relPath}] Removed deprecated 'actions' from workqueue '${workqueueLabel}' because action type is unsupported`
|
|
3907
|
+
);
|
|
3908
|
+
actionsArrayMigrated = true;
|
|
3909
|
+
} else {
|
|
3910
|
+
const firstActionText = actionCandidates[0].getText();
|
|
3911
|
+
workqueue.addPropertyAssignment({
|
|
3912
|
+
name: ACTION_PROPERTY_NAME2,
|
|
3913
|
+
initializer: firstActionText
|
|
3914
|
+
});
|
|
3915
|
+
actionsProperty.remove();
|
|
3916
|
+
console.log(
|
|
3917
|
+
` [${relPath}] Replaced 'actions' with 'action' on workqueue '${workqueueLabel}'`
|
|
3918
|
+
);
|
|
3919
|
+
actionsArrayMigrated = true;
|
|
3920
|
+
}
|
|
3765
3921
|
}
|
|
3766
3922
|
}
|
|
3767
3923
|
}
|
|
3768
|
-
actionsProperty.remove();
|
|
3769
|
-
console.log(
|
|
3770
|
-
` [${relPath}] Removed deprecated 'actions' from workqueue '${workqueueLabel}' (existing 'action' kept)`
|
|
3771
|
-
);
|
|
3772
|
-
return 1;
|
|
3773
|
-
}
|
|
3774
|
-
const actionCandidates = actionsInitializer.getElements().filter(
|
|
3775
|
-
(element) => import_ts_morph17.Node.isObjectLiteralExpression(element)
|
|
3776
|
-
);
|
|
3777
|
-
if (actionCandidates.length === 0) {
|
|
3778
|
-
actionsProperty.remove();
|
|
3779
|
-
console.log(
|
|
3780
|
-
` [${relPath}] Removed empty 'actions' from workqueue '${workqueueLabel}'`
|
|
3781
|
-
);
|
|
3782
|
-
return 1;
|
|
3783
3924
|
}
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3925
|
+
const fallback = ensureValidAction(workqueue, relPath);
|
|
3926
|
+
return {
|
|
3927
|
+
changed: actionsArrayMigrated || fallback.changed,
|
|
3928
|
+
usedReadFallback: fallback.usedReadFallback
|
|
3929
|
+
};
|
|
3930
|
+
}
|
|
3931
|
+
function ensureActionTypeImport(sourceFile) {
|
|
3932
|
+
const existingImport = sourceFile.getImportDeclaration(
|
|
3933
|
+
(decl) => decl.getModuleSpecifierValue() === TOOLKIT_EVENTS_MODULE2
|
|
3792
3934
|
);
|
|
3793
|
-
if (
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
if (isUnsupportedActionType(actionCandidates[0])) {
|
|
3800
|
-
actionsProperty.remove();
|
|
3801
|
-
console.log(
|
|
3802
|
-
` [${relPath}] Removed deprecated 'actions' from workqueue '${workqueueLabel}' because action type is unsupported`
|
|
3803
|
-
);
|
|
3804
|
-
return 1;
|
|
3935
|
+
if (existingImport) {
|
|
3936
|
+
const alreadyImported = existingImport.getNamedImports().some((ni) => ni.getName() === ACTION_TYPE_IMPORT_NAME);
|
|
3937
|
+
if (!alreadyImported) {
|
|
3938
|
+
existingImport.addNamedImport(ACTION_TYPE_IMPORT_NAME);
|
|
3939
|
+
}
|
|
3940
|
+
return;
|
|
3805
3941
|
}
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
initializer: firstActionText
|
|
3942
|
+
sourceFile.addImportDeclaration({
|
|
3943
|
+
moduleSpecifier: TOOLKIT_EVENTS_MODULE2,
|
|
3944
|
+
namedImports: [ACTION_TYPE_IMPORT_NAME]
|
|
3810
3945
|
});
|
|
3811
|
-
actionsProperty.remove();
|
|
3812
|
-
console.log(
|
|
3813
|
-
` [${relPath}] Replaced 'actions' with 'action' on workqueue '${workqueueLabel}'`
|
|
3814
|
-
);
|
|
3815
|
-
return 1;
|
|
3816
3946
|
}
|
|
3817
3947
|
function processFile13(filePath, project) {
|
|
3818
3948
|
const sourceFile = project.getSourceFile(filePath);
|
|
3819
3949
|
if (!sourceFile) return 0;
|
|
3820
3950
|
let migratedWorkqueues = 0;
|
|
3951
|
+
let needsActionTypeImport = false;
|
|
3821
3952
|
const relPath = import_path18.default.relative(process.cwd(), filePath);
|
|
3822
3953
|
const callExpressions = sourceFile.getDescendantsOfKind(
|
|
3823
3954
|
import_ts_morph17.SyntaxKind.CallExpression
|
|
@@ -3833,9 +3964,14 @@ function processFile13(filePath, project) {
|
|
|
3833
3964
|
if (!import_ts_morph17.Node.isArrayLiteralExpression(workqueuesArg)) continue;
|
|
3834
3965
|
for (const element of workqueuesArg.getElements()) {
|
|
3835
3966
|
if (!import_ts_morph17.Node.isObjectLiteralExpression(element)) continue;
|
|
3836
|
-
|
|
3967
|
+
const result = migrateWorkqueueActions(element, relPath);
|
|
3968
|
+
if (result.changed) migratedWorkqueues++;
|
|
3969
|
+
if (result.usedReadFallback) needsActionTypeImport = true;
|
|
3837
3970
|
}
|
|
3838
3971
|
}
|
|
3972
|
+
if (needsActionTypeImport) {
|
|
3973
|
+
ensureActionTypeImport(sourceFile);
|
|
3974
|
+
}
|
|
3839
3975
|
return migratedWorkqueues;
|
|
3840
3976
|
}
|
|
3841
3977
|
async function main18() {
|
|
@@ -4170,7 +4306,7 @@ Saved ${handlerRelPath}.`);
|
|
|
4170
4306
|
// src/migrations/v2.0/checkout-upstream-files.ts
|
|
4171
4307
|
var import_child_process = require("child_process");
|
|
4172
4308
|
var UPSTREAM_URL = "https://github.com/opencrvs/opencrvs-countryconfig.git";
|
|
4173
|
-
var UPSTREAM_BRANCH = "
|
|
4309
|
+
var UPSTREAM_BRANCH = "release-v2.0.0";
|
|
4174
4310
|
var TEMP_REMOTE = "opencrvs-upgrade-v19-v20-codemod";
|
|
4175
4311
|
var FILES_TO_CHECKOUT = [
|
|
4176
4312
|
"src/analytics/analytics.ts",
|
|
@@ -4709,9 +4845,9 @@ var import_path24 = require("path");
|
|
|
4709
4845
|
var TEMP_REMOTE2 = "opencrvs-upgrade-v19-v20-codemod-merge-infra";
|
|
4710
4846
|
var INFRASTRUCTURE_DIR = "infrastructure";
|
|
4711
4847
|
var BASE_BRANCH = "release-v1.9";
|
|
4712
|
-
function gitShowBytes(ref,
|
|
4848
|
+
function gitShowBytes(ref, path24) {
|
|
4713
4849
|
try {
|
|
4714
|
-
const buf = (0, import_child_process2.execFileSync)("git", ["show", `${ref}:${
|
|
4850
|
+
const buf = (0, import_child_process2.execFileSync)("git", ["show", `${ref}:${path24}`], {
|
|
4715
4851
|
cwd: process.cwd(),
|
|
4716
4852
|
stdio: ["ignore", "pipe", "pipe"]
|
|
4717
4853
|
});
|
|
@@ -4720,9 +4856,13 @@ function gitShowBytes(ref, path23) {
|
|
|
4720
4856
|
return null;
|
|
4721
4857
|
}
|
|
4722
4858
|
}
|
|
4723
|
-
async function main25(
|
|
4859
|
+
async function main25({
|
|
4860
|
+
subdirs = []
|
|
4861
|
+
} = {}) {
|
|
4862
|
+
const pathspecs = subdirs.length > 0 ? subdirs.map((s) => `${INFRASTRUCTURE_DIR}/${s}/`) : [`${INFRASTRUCTURE_DIR}/`];
|
|
4863
|
+
const scopeLabel = pathspecs.map((p) => `'${p}'`).join(", ");
|
|
4724
4864
|
console.log(
|
|
4725
|
-
`Merging
|
|
4865
|
+
`Merging ${scopeLabel} from ${UPSTREAM_URL}@${UPSTREAM_BRANCH} (base: ${BASE_BRANCH})...
|
|
4726
4866
|
`
|
|
4727
4867
|
);
|
|
4728
4868
|
assertIsGitRepo();
|
|
@@ -4737,20 +4877,12 @@ async function main25() {
|
|
|
4737
4877
|
const ref = `${TEMP_REMOTE2}/${UPSTREAM_BRANCH}`;
|
|
4738
4878
|
const baseRef = `${TEMP_REMOTE2}/${BASE_BRANCH}`;
|
|
4739
4879
|
const upstreamFiles = runGit(
|
|
4740
|
-
[
|
|
4741
|
-
"ls-tree",
|
|
4742
|
-
"-r",
|
|
4743
|
-
"--name-only",
|
|
4744
|
-
"-z",
|
|
4745
|
-
ref,
|
|
4746
|
-
"--",
|
|
4747
|
-
`${INFRASTRUCTURE_DIR}/`
|
|
4748
|
-
],
|
|
4880
|
+
["ls-tree", "-r", "--name-only", "-z", ref, "--", ...pathspecs],
|
|
4749
4881
|
{ silent: true }
|
|
4750
4882
|
).split("\0").filter(Boolean);
|
|
4751
4883
|
if (upstreamFiles.length === 0) {
|
|
4752
4884
|
console.log(
|
|
4753
|
-
` No files found under
|
|
4885
|
+
` No files found under ${scopeLabel} on ${ref}. Nothing to merge.`
|
|
4754
4886
|
);
|
|
4755
4887
|
return;
|
|
4756
4888
|
}
|
|
@@ -4825,7 +4957,9 @@ async function main25() {
|
|
|
4825
4957
|
var import_fs6 = require("fs");
|
|
4826
4958
|
var import_path25 = require("path");
|
|
4827
4959
|
var INFRASTRUCTURE_DIR2 = "infrastructure";
|
|
4828
|
-
async function main26(
|
|
4960
|
+
async function main26({
|
|
4961
|
+
keep = []
|
|
4962
|
+
} = {}) {
|
|
4829
4963
|
const fullPath = (0, import_path25.join)(process.cwd(), INFRASTRUCTURE_DIR2);
|
|
4830
4964
|
if (!(0, import_fs6.existsSync)(fullPath)) {
|
|
4831
4965
|
console.log(
|
|
@@ -4833,24 +4967,152 @@ async function main26() {
|
|
|
4833
4967
|
);
|
|
4834
4968
|
return;
|
|
4835
4969
|
}
|
|
4836
|
-
console.log(`Deleting '${INFRASTRUCTURE_DIR2}/'...
|
|
4837
|
-
`);
|
|
4838
4970
|
assertIsGitRepo();
|
|
4839
|
-
|
|
4840
|
-
|
|
4971
|
+
if (keep.length === 0) {
|
|
4972
|
+
console.log(`Deleting '${INFRASTRUCTURE_DIR2}/'...
|
|
4973
|
+
`);
|
|
4974
|
+
runGit(["rm", "-rf", "--ignore-unmatch", "--", `${INFRASTRUCTURE_DIR2}/`], {
|
|
4975
|
+
silent: true
|
|
4976
|
+
});
|
|
4977
|
+
console.log(
|
|
4978
|
+
` Staged deletion of tracked files under '${INFRASTRUCTURE_DIR2}/'.`
|
|
4979
|
+
);
|
|
4980
|
+
if ((0, import_fs6.existsSync)(fullPath)) {
|
|
4981
|
+
(0, import_fs6.rmSync)(fullPath, { recursive: true, force: true });
|
|
4982
|
+
console.log(
|
|
4983
|
+
` Removed remaining untracked files under '${INFRASTRUCTURE_DIR2}/'.`
|
|
4984
|
+
);
|
|
4985
|
+
}
|
|
4986
|
+
console.log(
|
|
4987
|
+
`
|
|
4988
|
+
Done. Review the staged deletion with: git diff --cached -- '${INFRASTRUCTURE_DIR2}/'`
|
|
4989
|
+
);
|
|
4990
|
+
return;
|
|
4991
|
+
}
|
|
4992
|
+
const keepSet = new Set(keep);
|
|
4993
|
+
console.log(
|
|
4994
|
+
`Deleting contents of '${INFRASTRUCTURE_DIR2}/' except: ${[...keepSet].map((name) => `'${name}'`).join(", ")}
|
|
4995
|
+
`
|
|
4996
|
+
);
|
|
4997
|
+
const topLevelEntries = (0, import_fs6.readdirSync)(fullPath, { withFileTypes: true });
|
|
4998
|
+
let deleted = 0;
|
|
4999
|
+
for (const entry of topLevelEntries) {
|
|
5000
|
+
if (keepSet.has(entry.name)) {
|
|
5001
|
+
console.log(` Keeping '${INFRASTRUCTURE_DIR2}/${entry.name}'.`);
|
|
5002
|
+
continue;
|
|
5003
|
+
}
|
|
5004
|
+
const relPath = `${INFRASTRUCTURE_DIR2}/${entry.name}${entry.isDirectory() ? "/" : ""}`;
|
|
5005
|
+
runGit(["rm", "-rf", "--ignore-unmatch", "--", relPath], { silent: true });
|
|
5006
|
+
const fullEntryPath = (0, import_path25.join)(fullPath, entry.name);
|
|
5007
|
+
if ((0, import_fs6.existsSync)(fullEntryPath)) {
|
|
5008
|
+
(0, import_fs6.rmSync)(fullEntryPath, { recursive: true, force: true });
|
|
5009
|
+
}
|
|
5010
|
+
console.log(` Deleted '${relPath}'.`);
|
|
5011
|
+
deleted++;
|
|
5012
|
+
}
|
|
5013
|
+
const presentNames = new Set(topLevelEntries.map((e) => e.name));
|
|
5014
|
+
const missingKeeps = [...keepSet].filter((name) => !presentNames.has(name));
|
|
5015
|
+
if (missingKeeps.length > 0) {
|
|
5016
|
+
console.warn(
|
|
5017
|
+
` [warn] Requested to keep ${missingKeeps.map((n) => `'${n}'`).join(", ")} but they don't exist under '${INFRASTRUCTURE_DIR2}/'.`
|
|
5018
|
+
);
|
|
5019
|
+
}
|
|
5020
|
+
console.log(
|
|
5021
|
+
`
|
|
5022
|
+
Done. Deleted ${deleted} top-level entr${deleted === 1 ? "y" : "ies"}. Review the staged deletions with: git diff --cached -- '${INFRASTRUCTURE_DIR2}/'`
|
|
5023
|
+
);
|
|
5024
|
+
}
|
|
5025
|
+
|
|
5026
|
+
// src/migrations/v2.0/fix-accept-requested-registration-function-type.ts
|
|
5027
|
+
var import_ts_morph22 = require("ts-morph");
|
|
5028
|
+
var import_path26 = __toESM(require("path"));
|
|
5029
|
+
var TARGET_FUNCTION_NAME = "acceptRequestedRegistration";
|
|
5030
|
+
var ACTION_PARAMETER_NAME = "action";
|
|
5031
|
+
var OLD_TYPE = "ActionInput";
|
|
5032
|
+
var NEW_TYPE = "Extract<ActionInput, { type?: 'REGISTER' }>";
|
|
5033
|
+
function isAcceptRequestedRegistrationParameter(parameter) {
|
|
5034
|
+
const functionDeclaration = parameter.getFirstAncestorByKind(
|
|
5035
|
+
import_ts_morph22.SyntaxKind.FunctionDeclaration
|
|
5036
|
+
);
|
|
5037
|
+
if (functionDeclaration?.getName() === TARGET_FUNCTION_NAME) {
|
|
5038
|
+
return true;
|
|
5039
|
+
}
|
|
5040
|
+
const arrowFunction = parameter.getFirstAncestorByKind(
|
|
5041
|
+
import_ts_morph22.SyntaxKind.ArrowFunction
|
|
5042
|
+
);
|
|
5043
|
+
const variableDeclaration = arrowFunction?.getFirstAncestorByKind(
|
|
5044
|
+
import_ts_morph22.SyntaxKind.VariableDeclaration
|
|
5045
|
+
);
|
|
5046
|
+
return variableDeclaration?.getName() === TARGET_FUNCTION_NAME;
|
|
5047
|
+
}
|
|
5048
|
+
function processFile14(filePath, project) {
|
|
5049
|
+
const sourceFile = project.getSourceFile(filePath);
|
|
5050
|
+
if (!sourceFile) return 0;
|
|
5051
|
+
let updatedCount = 0;
|
|
5052
|
+
for (const parameter of sourceFile.getDescendantsOfKind(
|
|
5053
|
+
import_ts_morph22.SyntaxKind.Parameter
|
|
5054
|
+
)) {
|
|
5055
|
+
if (parameter.getName() !== ACTION_PARAMETER_NAME) {
|
|
5056
|
+
continue;
|
|
5057
|
+
}
|
|
5058
|
+
if (!isAcceptRequestedRegistrationParameter(parameter)) {
|
|
5059
|
+
continue;
|
|
5060
|
+
}
|
|
5061
|
+
const typeNode = parameter.getTypeNode();
|
|
5062
|
+
if (!typeNode || typeNode.getText() !== OLD_TYPE) {
|
|
5063
|
+
continue;
|
|
5064
|
+
}
|
|
5065
|
+
parameter.setType(NEW_TYPE);
|
|
5066
|
+
updatedCount++;
|
|
5067
|
+
console.log(
|
|
5068
|
+
` [${import_path26.default.relative(process.cwd(), filePath)}] Updated '${ACTION_PARAMETER_NAME}' in ${TARGET_FUNCTION_NAME} to ${NEW_TYPE}`
|
|
5069
|
+
);
|
|
5070
|
+
}
|
|
5071
|
+
return updatedCount;
|
|
5072
|
+
}
|
|
5073
|
+
async function main27() {
|
|
5074
|
+
const srcDir = import_path26.default.join(process.cwd(), "src");
|
|
5075
|
+
console.log(`Scanning for ${TARGET_FUNCTION_NAME} in: ${srcDir}
|
|
5076
|
+
`);
|
|
5077
|
+
const project = new import_ts_morph22.Project({
|
|
5078
|
+
tsConfigFilePath: import_path26.default.resolve(srcDir, "../tsconfig.json"),
|
|
5079
|
+
skipAddingFilesFromTsConfig: false
|
|
4841
5080
|
});
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
5081
|
+
const sourceFiles = project.getSourceFiles().filter((sf) => {
|
|
5082
|
+
const filePath = sf.getFilePath();
|
|
5083
|
+
return filePath.includes("/src/") && !filePath.includes("/node_modules/");
|
|
5084
|
+
});
|
|
5085
|
+
let totalUpdated = 0;
|
|
5086
|
+
const modifiedFiles = [];
|
|
5087
|
+
for (const sourceFile of sourceFiles) {
|
|
5088
|
+
const filePath = sourceFile.getFilePath();
|
|
5089
|
+
const updated = processFile14(filePath, project);
|
|
5090
|
+
if (updated > 0) {
|
|
5091
|
+
totalUpdated += updated;
|
|
5092
|
+
modifiedFiles.push(filePath);
|
|
5093
|
+
}
|
|
5094
|
+
}
|
|
5095
|
+
if (modifiedFiles.length === 0) {
|
|
5096
|
+
console.log(
|
|
5097
|
+
`No '${ACTION_PARAMETER_NAME}: ${OLD_TYPE}' parameter in ${TARGET_FUNCTION_NAME} found. Nothing to do.`
|
|
5098
|
+
);
|
|
5099
|
+
return;
|
|
5100
|
+
}
|
|
5101
|
+
console.log(`
|
|
5102
|
+
Saving ${modifiedFiles.length} modified file(s)...`);
|
|
5103
|
+
for (const filePath of modifiedFiles) {
|
|
5104
|
+
const sourceFile = project.getSourceFileOrThrow(filePath);
|
|
5105
|
+
await sourceFile.save();
|
|
5106
|
+
console.log(` Saved: ${import_path26.default.relative(process.cwd(), filePath)}`);
|
|
4846
5107
|
}
|
|
4847
5108
|
console.log(
|
|
4848
5109
|
`
|
|
4849
|
-
|
|
5110
|
+
Done. Updated ${totalUpdated} parameter type annotation(s) in ${TARGET_FUNCTION_NAME}.`
|
|
4850
5111
|
);
|
|
4851
5112
|
}
|
|
4852
5113
|
|
|
4853
5114
|
// src/migrations/v2.0/index.ts
|
|
5115
|
+
var NON_SWARM_INFRA_SUBDIRS = ["postgres", "metabase"];
|
|
4854
5116
|
async function runUpgrade(dockerSwarm) {
|
|
4855
5117
|
await main18();
|
|
4856
5118
|
await main();
|
|
@@ -4875,10 +5137,12 @@ async function runUpgrade(dockerSwarm) {
|
|
|
4875
5137
|
await main22();
|
|
4876
5138
|
await main23();
|
|
4877
5139
|
await main24();
|
|
5140
|
+
await main27();
|
|
4878
5141
|
await main17();
|
|
4879
5142
|
if (dockerSwarm) {
|
|
4880
5143
|
await main25();
|
|
4881
5144
|
} else {
|
|
4882
|
-
await main26();
|
|
5145
|
+
await main26({ keep: NON_SWARM_INFRA_SUBDIRS });
|
|
5146
|
+
await main25({ subdirs: NON_SWARM_INFRA_SUBDIRS });
|
|
4883
5147
|
}
|
|
4884
5148
|
}
|