@smartive/graphql-magic 19.3.0 → 19.3.1-next.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/CHANGELOG.md +3 -3
- package/dist/cjs/index.cjs +96 -98
- package/dist/esm/resolvers/mutations.d.ts +6 -6
- package/dist/esm/resolvers/mutations.js +49 -43
- package/dist/esm/resolvers/mutations.js.map +1 -1
- package/package.json +3 -3
- package/src/resolvers/mutations.ts +402 -392
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
## [19.3.1-next.2](https://github.com/smartive/graphql-magic/compare/v19.3.1-next.1...v19.3.1-next.2) (2025-07-02)
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
###
|
|
4
|
+
### Bug Fixes
|
|
5
5
|
|
|
6
|
-
*
|
|
6
|
+
* Sort results ([ed5f07f](https://github.com/smartive/graphql-magic/commit/ed5f07fd4ee9511ac7541370b1b1ba076a6ea960))
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -2682,62 +2682,60 @@ var applySubQueries = async (node, entries, parentVerifiedPermissionStacks) => {
|
|
|
2682
2682
|
};
|
|
2683
2683
|
|
|
2684
2684
|
// src/resolvers/mutations.ts
|
|
2685
|
-
var
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
return id;
|
|
2706
|
-
}
|
|
2707
|
-
case "restore": {
|
|
2708
|
-
const id = args2.where.id;
|
|
2709
|
-
await restoreEntity(modelName, id, ctx, "mutation");
|
|
2710
|
-
return id;
|
|
2711
|
-
}
|
|
2685
|
+
var withTransaction = async (ctx, fn) => await ctx.knex.transaction(async (knex) => fn({ ...ctx, knex }));
|
|
2686
|
+
var mutationResolver = async (_parent, args2, partialCtx, info) => withTransaction({ ...partialCtx, info, aliases: new AliasGenerator() }, async (ctx) => {
|
|
2687
|
+
const [, mutation, modelName] = it(info.fieldName.match(/^(create|update|delete|restore)(.+)$/));
|
|
2688
|
+
switch (mutation) {
|
|
2689
|
+
case "create": {
|
|
2690
|
+
const id = await createEntity(modelName, args2.data, ctx, "mutation");
|
|
2691
|
+
return await resolve(ctx, id);
|
|
2692
|
+
}
|
|
2693
|
+
case "update": {
|
|
2694
|
+
const id = args2.where.id;
|
|
2695
|
+
await updateEntity(modelName, id, args2.data, ctx, "mutation");
|
|
2696
|
+
return await resolve(ctx, id);
|
|
2697
|
+
}
|
|
2698
|
+
case "delete": {
|
|
2699
|
+
const id = args2.where.id;
|
|
2700
|
+
await deleteEntity(modelName, id, ctx, {
|
|
2701
|
+
dryRun: args2.dryRun,
|
|
2702
|
+
trigger: "mutation"
|
|
2703
|
+
});
|
|
2704
|
+
return id;
|
|
2712
2705
|
}
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2706
|
+
case "restore": {
|
|
2707
|
+
const id = args2.where.id;
|
|
2708
|
+
await restoreEntity(modelName, id, ctx, "mutation");
|
|
2709
|
+
return id;
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
});
|
|
2713
|
+
var createEntity = async (modelName, input2, ctx, trigger = "direct-call") => withTransaction(ctx, async (ctx2) => {
|
|
2714
|
+
const model = ctx2.models.getModel(modelName, "entity");
|
|
2717
2715
|
const normalizedInput = { ...input2 };
|
|
2718
2716
|
if (!normalizedInput.id) {
|
|
2719
2717
|
normalizedInput.id = (0, import_uuid.v4)();
|
|
2720
2718
|
}
|
|
2721
2719
|
const id = normalizedInput.id;
|
|
2722
2720
|
if (!normalizedInput.createdAt) {
|
|
2723
|
-
normalizedInput.createdAt =
|
|
2721
|
+
normalizedInput.createdAt = ctx2.now;
|
|
2724
2722
|
}
|
|
2725
2723
|
if (!normalizedInput.createdById) {
|
|
2726
|
-
normalizedInput.createdById =
|
|
2724
|
+
normalizedInput.createdById = ctx2.user?.id;
|
|
2727
2725
|
}
|
|
2728
2726
|
if (model.parent) {
|
|
2729
2727
|
normalizedInput.type = model.name;
|
|
2730
2728
|
}
|
|
2731
|
-
sanitize(
|
|
2732
|
-
await checkCanWrite(
|
|
2733
|
-
await
|
|
2734
|
-
await
|
|
2729
|
+
sanitize(ctx2, model, normalizedInput);
|
|
2730
|
+
await checkCanWrite(ctx2, model, normalizedInput, "CREATE");
|
|
2731
|
+
await ctx2.handleUploads?.(normalizedInput);
|
|
2732
|
+
await ctx2.mutationHook?.({
|
|
2735
2733
|
model,
|
|
2736
2734
|
action: "create",
|
|
2737
2735
|
trigger,
|
|
2738
2736
|
when: "before",
|
|
2739
2737
|
data: { prev: {}, input: input2, normalizedInput, next: normalizedInput },
|
|
2740
|
-
ctx
|
|
2738
|
+
ctx: ctx2
|
|
2741
2739
|
});
|
|
2742
2740
|
if (model.parent) {
|
|
2743
2741
|
const rootInput = {};
|
|
@@ -2752,75 +2750,75 @@ var createEntity = async (modelName, input2, ctx, trigger = "direct-call") => {
|
|
|
2752
2750
|
}
|
|
2753
2751
|
}
|
|
2754
2752
|
}
|
|
2755
|
-
await
|
|
2756
|
-
await
|
|
2753
|
+
await ctx2.knex(model.parent).insert(rootInput);
|
|
2754
|
+
await ctx2.knex(model.name).insert(childInput);
|
|
2757
2755
|
} else {
|
|
2758
|
-
await
|
|
2756
|
+
await ctx2.knex(model.name).insert(normalizedInput);
|
|
2759
2757
|
}
|
|
2760
|
-
await createRevision(model, normalizedInput,
|
|
2761
|
-
await
|
|
2758
|
+
await createRevision(model, normalizedInput, ctx2);
|
|
2759
|
+
await ctx2.mutationHook?.({
|
|
2762
2760
|
model,
|
|
2763
2761
|
action: "create",
|
|
2764
2762
|
trigger,
|
|
2765
2763
|
when: "after",
|
|
2766
2764
|
data: { prev: {}, input: input2, normalizedInput, next: normalizedInput },
|
|
2767
|
-
ctx
|
|
2765
|
+
ctx: ctx2
|
|
2768
2766
|
});
|
|
2769
2767
|
return normalizedInput.id;
|
|
2770
|
-
};
|
|
2771
|
-
var updateEntities = async (modelName, where, updateFields, ctx) => {
|
|
2772
|
-
const entities = await
|
|
2768
|
+
});
|
|
2769
|
+
var updateEntities = async (modelName, where, updateFields, ctx) => withTransaction(ctx, async (ctx2) => {
|
|
2770
|
+
const entities = await ctx2.knex(modelName).where(where).select("id");
|
|
2773
2771
|
for (const entity of entities) {
|
|
2774
|
-
await updateEntity(modelName, entity.id, updateFields,
|
|
2772
|
+
await updateEntity(modelName, entity.id, updateFields, ctx2);
|
|
2775
2773
|
}
|
|
2776
|
-
};
|
|
2777
|
-
var updateEntity = async (modelName, id, input2, ctx, trigger = "direct-call") => {
|
|
2778
|
-
const model =
|
|
2774
|
+
});
|
|
2775
|
+
var updateEntity = async (modelName, id, input2, ctx, trigger = "direct-call") => withTransaction(ctx, async (ctx2) => {
|
|
2776
|
+
const model = ctx2.models.getModel(modelName, "entity");
|
|
2779
2777
|
const normalizedInput = { ...input2 };
|
|
2780
|
-
sanitize(
|
|
2781
|
-
const currentEntity = await getEntityToMutate(
|
|
2778
|
+
sanitize(ctx2, model, normalizedInput);
|
|
2779
|
+
const currentEntity = await getEntityToMutate(ctx2, model, { id }, "UPDATE");
|
|
2782
2780
|
for (const key of Object.keys(normalizedInput)) {
|
|
2783
2781
|
if (normalizedInput[key] === currentEntity[key]) {
|
|
2784
2782
|
delete normalizedInput[key];
|
|
2785
2783
|
}
|
|
2786
2784
|
}
|
|
2787
2785
|
if (Object.keys(normalizedInput).length > 0) {
|
|
2788
|
-
await checkCanWrite(
|
|
2789
|
-
await
|
|
2790
|
-
await
|
|
2786
|
+
await checkCanWrite(ctx2, model, normalizedInput, "UPDATE");
|
|
2787
|
+
await ctx2.handleUploads?.(normalizedInput);
|
|
2788
|
+
await ctx2.mutationHook?.({
|
|
2791
2789
|
model,
|
|
2792
2790
|
action: "update",
|
|
2793
2791
|
trigger,
|
|
2794
2792
|
when: "before",
|
|
2795
2793
|
data: { prev: currentEntity, input: input2, normalizedInput, next: { ...currentEntity, ...normalizedInput } },
|
|
2796
|
-
ctx
|
|
2794
|
+
ctx: ctx2
|
|
2797
2795
|
});
|
|
2798
|
-
await doUpdate(model, currentEntity, normalizedInput,
|
|
2799
|
-
await
|
|
2796
|
+
await doUpdate(model, currentEntity, normalizedInput, ctx2);
|
|
2797
|
+
await ctx2.mutationHook?.({
|
|
2800
2798
|
model,
|
|
2801
2799
|
action: "update",
|
|
2802
2800
|
trigger,
|
|
2803
2801
|
when: "after",
|
|
2804
2802
|
data: { prev: currentEntity, input: input2, normalizedInput, next: { ...currentEntity, ...normalizedInput } },
|
|
2805
|
-
ctx
|
|
2803
|
+
ctx: ctx2
|
|
2806
2804
|
});
|
|
2807
2805
|
}
|
|
2808
|
-
};
|
|
2809
|
-
var deleteEntities = async (modelName, where, ctx) => {
|
|
2810
|
-
const entities = await
|
|
2806
|
+
});
|
|
2807
|
+
var deleteEntities = async (modelName, where, ctx) => withTransaction(ctx, async (ctx2) => {
|
|
2808
|
+
const entities = await ctx2.knex(modelName).where(where).select("id");
|
|
2811
2809
|
for (const entity of entities) {
|
|
2812
|
-
await deleteEntity(modelName, entity.id,
|
|
2810
|
+
await deleteEntity(modelName, entity.id, ctx2, {
|
|
2813
2811
|
trigger: "direct-call"
|
|
2814
2812
|
});
|
|
2815
2813
|
}
|
|
2816
|
-
};
|
|
2814
|
+
});
|
|
2817
2815
|
var deleteEntity = async (modelName, id, ctx, {
|
|
2818
2816
|
dryRun = false,
|
|
2819
2817
|
trigger = "direct-call"
|
|
2820
|
-
} = {}) => {
|
|
2821
|
-
const model =
|
|
2818
|
+
} = {}) => withTransaction(ctx, async (ctx2) => {
|
|
2819
|
+
const model = ctx2.models.getModel(modelName, "entity");
|
|
2822
2820
|
const rootModel = model.rootModel;
|
|
2823
|
-
const entity = await getEntityToMutate(
|
|
2821
|
+
const entity = await getEntityToMutate(ctx2, rootModel, { id }, "DELETE");
|
|
2824
2822
|
if (entity.deleted) {
|
|
2825
2823
|
throw new ForbiddenError(`${getTechnicalDisplay(model, entity)} is already deleted.`);
|
|
2826
2824
|
}
|
|
@@ -2830,7 +2828,7 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2830
2828
|
const beforeHooks = [];
|
|
2831
2829
|
const mutations = [];
|
|
2832
2830
|
const afterHooks = [];
|
|
2833
|
-
const mutationHook =
|
|
2831
|
+
const mutationHook = ctx2.mutationHook;
|
|
2834
2832
|
const deleteCascade = async (currentModel, currentEntity, currentTrigger) => {
|
|
2835
2833
|
if (!(currentModel.name in toDelete)) {
|
|
2836
2834
|
toDelete[currentModel.name] = {};
|
|
@@ -2838,12 +2836,12 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2838
2836
|
if (currentEntity.id in toDelete[currentModel.name]) {
|
|
2839
2837
|
return;
|
|
2840
2838
|
}
|
|
2841
|
-
toDelete[currentModel.name][currentEntity.id] = await fetchDisplay(
|
|
2839
|
+
toDelete[currentModel.name][currentEntity.id] = await fetchDisplay(ctx2.knex, currentModel, currentEntity);
|
|
2842
2840
|
if (!dryRun) {
|
|
2843
2841
|
const normalizedInput = {
|
|
2844
2842
|
deleted: true,
|
|
2845
|
-
deletedAt:
|
|
2846
|
-
deletedById:
|
|
2843
|
+
deletedAt: ctx2.now,
|
|
2844
|
+
deletedById: ctx2.user?.id,
|
|
2847
2845
|
deleteRootType: rootModel.name,
|
|
2848
2846
|
deleteRootId: entity.id
|
|
2849
2847
|
};
|
|
@@ -2855,12 +2853,12 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2855
2853
|
trigger: currentTrigger,
|
|
2856
2854
|
when: "before",
|
|
2857
2855
|
data: { prev: currentEntity, input: {}, normalizedInput, next: { ...currentEntity, ...normalizedInput } },
|
|
2858
|
-
ctx
|
|
2856
|
+
ctx: ctx2
|
|
2859
2857
|
});
|
|
2860
2858
|
});
|
|
2861
2859
|
}
|
|
2862
2860
|
mutations.push(async () => {
|
|
2863
|
-
await doUpdate(currentModel, currentEntity, normalizedInput,
|
|
2861
|
+
await doUpdate(currentModel, currentEntity, normalizedInput, ctx2);
|
|
2864
2862
|
});
|
|
2865
2863
|
if (mutationHook) {
|
|
2866
2864
|
afterHooks.push(async () => {
|
|
@@ -2870,7 +2868,7 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2870
2868
|
trigger: currentTrigger,
|
|
2871
2869
|
when: "after",
|
|
2872
2870
|
data: { prev: currentEntity, input: {}, normalizedInput, next: { ...currentEntity, ...normalizedInput } },
|
|
2873
|
-
ctx
|
|
2871
|
+
ctx: ctx2
|
|
2874
2872
|
});
|
|
2875
2873
|
});
|
|
2876
2874
|
}
|
|
@@ -2879,7 +2877,7 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2879
2877
|
targetModel: descendantModel,
|
|
2880
2878
|
field: { name: name2, foreignKey, onDelete }
|
|
2881
2879
|
} of currentModel.reverseRelations.filter((reverseRelation) => !reverseRelation.field.inherited)) {
|
|
2882
|
-
const query =
|
|
2880
|
+
const query = ctx2.knex(descendantModel.name).where({ [foreignKey]: currentEntity.id, deleted: false }).orderBy("createdAt", "asc").orderBy("id", "asc");
|
|
2883
2881
|
const descendants = await query;
|
|
2884
2882
|
if (descendants.length) {
|
|
2885
2883
|
switch (onDelete) {
|
|
@@ -2891,7 +2889,7 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2891
2889
|
}
|
|
2892
2890
|
if (!toUnlink[descendantModel.name][descendant.id]) {
|
|
2893
2891
|
toUnlink[descendantModel.name][descendant.id] = {
|
|
2894
|
-
display: await fetchDisplay(
|
|
2892
|
+
display: await fetchDisplay(ctx2.knex, descendantModel, descendant),
|
|
2895
2893
|
fields: []
|
|
2896
2894
|
};
|
|
2897
2895
|
}
|
|
@@ -2906,12 +2904,12 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2906
2904
|
trigger: "set-null",
|
|
2907
2905
|
when: "before",
|
|
2908
2906
|
data: { prev: descendant, input: {}, normalizedInput, next: { ...descendant, ...normalizedInput } },
|
|
2909
|
-
ctx
|
|
2907
|
+
ctx: ctx2
|
|
2910
2908
|
});
|
|
2911
2909
|
});
|
|
2912
2910
|
}
|
|
2913
2911
|
mutations.push(async () => {
|
|
2914
|
-
await doUpdate(descendantModel, descendant, normalizedInput,
|
|
2912
|
+
await doUpdate(descendantModel, descendant, normalizedInput, ctx2);
|
|
2915
2913
|
});
|
|
2916
2914
|
if (mutationHook) {
|
|
2917
2915
|
afterHooks.push(async () => {
|
|
@@ -2921,7 +2919,7 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2921
2919
|
trigger: "set-null",
|
|
2922
2920
|
when: "after",
|
|
2923
2921
|
data: { prev: descendant, input: {}, normalizedInput, next: { ...descendant, ...normalizedInput } },
|
|
2924
|
-
ctx
|
|
2922
|
+
ctx: ctx2
|
|
2925
2923
|
});
|
|
2926
2924
|
});
|
|
2927
2925
|
}
|
|
@@ -2936,7 +2934,7 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2936
2934
|
for (const descendant of descendants) {
|
|
2937
2935
|
if (!restricted[descendantModel.name][descendant.id]) {
|
|
2938
2936
|
restricted[descendantModel.name][descendant.id] = {
|
|
2939
|
-
display: await fetchDisplay(
|
|
2937
|
+
display: await fetchDisplay(ctx2.knex, descendantModel, descendant),
|
|
2940
2938
|
fields: [name2]
|
|
2941
2939
|
};
|
|
2942
2940
|
}
|
|
@@ -2955,7 +2953,7 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2955
2953
|
`${getTechnicalDisplay(model, entity)} depends on ${getTechnicalDisplay(descendantModel, descendants[0])}${descendants.length > 1 ? ` (among others)` : ""} which cannot be deleted.`
|
|
2956
2954
|
);
|
|
2957
2955
|
}
|
|
2958
|
-
applyPermissions(
|
|
2956
|
+
applyPermissions(ctx2, descendantModel.name, descendantModel.name, query, "DELETE");
|
|
2959
2957
|
const deletableDescendants = await query;
|
|
2960
2958
|
const notDeletableDescendants = descendants.filter(
|
|
2961
2959
|
(descendant) => !deletableDescendants.some((d) => d.id === descendant.id)
|
|
@@ -2986,11 +2984,11 @@ var deleteEntity = async (modelName, id, ctx, {
|
|
|
2986
2984
|
restricted
|
|
2987
2985
|
});
|
|
2988
2986
|
}
|
|
2989
|
-
};
|
|
2990
|
-
var restoreEntity = async (modelName, id, ctx, trigger = "direct-call") => {
|
|
2991
|
-
const model =
|
|
2987
|
+
});
|
|
2988
|
+
var restoreEntity = async (modelName, id, ctx, trigger = "direct-call") => withTransaction(ctx, async (ctx2) => {
|
|
2989
|
+
const model = ctx2.models.getModel(modelName, "entity");
|
|
2992
2990
|
const rootModel = model.rootModel;
|
|
2993
|
-
const entity = await getEntityToMutate(
|
|
2991
|
+
const entity = await getEntityToMutate(ctx2, rootModel, { id }, "RESTORE");
|
|
2994
2992
|
if (!entity.deleted) {
|
|
2995
2993
|
throw new ForbiddenError(`${getTechnicalDisplay(model, entity)} is not deleted.`);
|
|
2996
2994
|
}
|
|
@@ -3010,7 +3008,7 @@ var restoreEntity = async (modelName, id, ctx, trigger = "direct-call") => {
|
|
|
3010
3008
|
if (!(currentEntity.deleteRootType === model.name && currentEntity.deleteRootId === entity.id)) {
|
|
3011
3009
|
return;
|
|
3012
3010
|
}
|
|
3013
|
-
} else if (!anyDateToLuxon(currentEntity.deletedAt,
|
|
3011
|
+
} else if (!anyDateToLuxon(currentEntity.deletedAt, ctx2.timeZone).equals(anyDateToLuxon(entity.deletedAt, ctx2.timeZone))) {
|
|
3014
3012
|
return;
|
|
3015
3013
|
}
|
|
3016
3014
|
if (!(currentModel.name in toRestore)) {
|
|
@@ -3024,15 +3022,15 @@ var restoreEntity = async (modelName, id, ctx, trigger = "direct-call") => {
|
|
|
3024
3022
|
deleteRootType: null,
|
|
3025
3023
|
deleteRootId: null
|
|
3026
3024
|
};
|
|
3027
|
-
if (
|
|
3025
|
+
if (ctx2.mutationHook) {
|
|
3028
3026
|
beforeHooks.push(async () => {
|
|
3029
|
-
await
|
|
3027
|
+
await ctx2.mutationHook({
|
|
3030
3028
|
model: currentModel,
|
|
3031
3029
|
action: "restore",
|
|
3032
3030
|
trigger: currentTrigger,
|
|
3033
3031
|
when: "before",
|
|
3034
3032
|
data: { prev: currentEntity, input: {}, normalizedInput, next: { ...currentEntity, ...normalizedInput } },
|
|
3035
|
-
ctx
|
|
3033
|
+
ctx: ctx2
|
|
3036
3034
|
});
|
|
3037
3035
|
});
|
|
3038
3036
|
}
|
|
@@ -3045,24 +3043,24 @@ var restoreEntity = async (modelName, id, ctx, trigger = "direct-call") => {
|
|
|
3045
3043
|
if (toRestore[relation.targetModel.name]?.has(parentId)) {
|
|
3046
3044
|
continue;
|
|
3047
3045
|
}
|
|
3048
|
-
const parent = await
|
|
3046
|
+
const parent = await ctx2.knex(relation.targetModel.name).where({ id: parentId }).first();
|
|
3049
3047
|
if (parent?.deleted) {
|
|
3050
3048
|
throw new ForbiddenError(
|
|
3051
3049
|
`Can't restore ${getTechnicalDisplay(model, entity)} because it depends on deleted ${relation.targetModel.name} ${parentId}.`
|
|
3052
3050
|
);
|
|
3053
3051
|
}
|
|
3054
3052
|
}
|
|
3055
|
-
await doUpdate(currentModel, currentEntity, normalizedInput,
|
|
3053
|
+
await doUpdate(currentModel, currentEntity, normalizedInput, ctx2);
|
|
3056
3054
|
});
|
|
3057
|
-
if (
|
|
3055
|
+
if (ctx2.mutationHook) {
|
|
3058
3056
|
afterHooks.push(async () => {
|
|
3059
|
-
await
|
|
3057
|
+
await ctx2.mutationHook({
|
|
3060
3058
|
model: currentModel,
|
|
3061
3059
|
action: "restore",
|
|
3062
3060
|
trigger: currentTrigger,
|
|
3063
3061
|
when: "after",
|
|
3064
3062
|
data: { prev: currentEntity, input: {}, normalizedInput, next: { ...currentEntity, ...normalizedInput } },
|
|
3065
|
-
ctx
|
|
3063
|
+
ctx: ctx2
|
|
3066
3064
|
});
|
|
3067
3065
|
});
|
|
3068
3066
|
}
|
|
@@ -3070,14 +3068,14 @@ var restoreEntity = async (modelName, id, ctx, trigger = "direct-call") => {
|
|
|
3070
3068
|
targetModel: descendantModel,
|
|
3071
3069
|
field: { foreignKey }
|
|
3072
3070
|
} of currentModel.reverseRelations.filter((reverseRelation) => !reverseRelation.field.inherited).filter(({ targetModel: { deletable } }) => deletable)) {
|
|
3073
|
-
const query =
|
|
3071
|
+
const query = ctx2.knex(descendantModel.name).where({ [foreignKey]: currentEntity.id, deleted: true }).orderBy("createdAt", "asc").orderBy("id", "asc");
|
|
3074
3072
|
if (currentEntity.deleteRootId) {
|
|
3075
3073
|
query.where({ deleteRootType: currentEntity.deleteRootType, deleteRootId: currentEntity.deleteRootId });
|
|
3076
3074
|
} else {
|
|
3077
3075
|
query.where({ deletedAt: currentEntity.deletedAt });
|
|
3078
3076
|
}
|
|
3079
3077
|
const descendantsToRestore = await query;
|
|
3080
|
-
applyPermissions(
|
|
3078
|
+
applyPermissions(ctx2, descendantModel.name, descendantModel.name, query, "RESTORE");
|
|
3081
3079
|
const restorableDescendants = await query;
|
|
3082
3080
|
const notRestorableDescendants = descendantsToRestore.filter(
|
|
3083
3081
|
(descendant) => !restorableDescendants.some((d) => d.id === descendant.id)
|
|
@@ -3096,7 +3094,7 @@ var restoreEntity = async (modelName, id, ctx, trigger = "direct-call") => {
|
|
|
3096
3094
|
for (const callback of [...beforeHooks, ...mutations, ...afterHooks]) {
|
|
3097
3095
|
await callback();
|
|
3098
3096
|
}
|
|
3099
|
-
};
|
|
3097
|
+
});
|
|
3100
3098
|
var createRevision = async (model, data, ctx) => {
|
|
3101
3099
|
if (model.updatable) {
|
|
3102
3100
|
const revisionId = (0, import_uuid.v4)();
|
|
@@ -3,13 +3,13 @@ import { Context } from '../context';
|
|
|
3
3
|
import { EntityModel } from '../models/models';
|
|
4
4
|
import { Entity, MutationContext, Trigger } from '../models/mutation-hook';
|
|
5
5
|
export declare const mutationResolver: (_parent: any, args: any, partialCtx: Context, info: GraphQLResolveInfo) => Promise<any>;
|
|
6
|
-
export declare const createEntity: (modelName: string, input: Entity, ctx: MutationContext, trigger?: Trigger) => Promise<
|
|
7
|
-
export declare const updateEntities: (modelName: string, where: Record<string, unknown>, updateFields: Entity, ctx: MutationContext) => Promise<
|
|
8
|
-
export declare const updateEntity: (modelName: string, id: string, input: Entity, ctx: MutationContext, trigger?: Trigger) => Promise<
|
|
9
|
-
export declare const deleteEntities: (modelName: string, where: Record<string, unknown>, ctx: MutationContext) => Promise<
|
|
6
|
+
export declare const createEntity: (modelName: string, input: Entity, ctx: MutationContext, trigger?: Trigger) => Promise<any>;
|
|
7
|
+
export declare const updateEntities: (modelName: string, where: Record<string, unknown>, updateFields: Entity, ctx: MutationContext) => Promise<any>;
|
|
8
|
+
export declare const updateEntity: (modelName: string, id: string, input: Entity, ctx: MutationContext, trigger?: Trigger) => Promise<any>;
|
|
9
|
+
export declare const deleteEntities: (modelName: string, where: Record<string, unknown>, ctx: MutationContext) => Promise<any>;
|
|
10
10
|
export declare const deleteEntity: (modelName: string, id: string, ctx: MutationContext, { dryRun, trigger, }?: {
|
|
11
11
|
dryRun?: boolean;
|
|
12
12
|
trigger?: Trigger;
|
|
13
|
-
}) => Promise<
|
|
14
|
-
export declare const restoreEntity: (modelName: string, id: string, ctx: MutationContext, trigger?: Trigger) => Promise<
|
|
13
|
+
}) => Promise<any>;
|
|
14
|
+
export declare const restoreEntity: (modelName: string, id: string, ctx: MutationContext, trigger?: Trigger) => Promise<any>;
|
|
15
15
|
export declare const createRevision: (model: EntityModel, data: Entity, ctx: MutationContext) => Promise<void>;
|
|
@@ -5,37 +5,35 @@ import { applyPermissions, checkCanWrite, getEntityToMutate } from '../permissio
|
|
|
5
5
|
import { anyDateToLuxon } from '../utils';
|
|
6
6
|
import { resolve } from './resolver';
|
|
7
7
|
import { AliasGenerator, fetchDisplay, getTechnicalDisplay } from './utils';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return await resolve(ctx, id);
|
|
16
|
-
}
|
|
17
|
-
case 'update': {
|
|
18
|
-
const id = args.where.id;
|
|
19
|
-
await updateEntity(modelName, id, args.data, ctx, 'mutation');
|
|
20
|
-
return await resolve(ctx, id);
|
|
21
|
-
}
|
|
22
|
-
case 'delete': {
|
|
23
|
-
const id = args.where.id;
|
|
24
|
-
await deleteEntity(modelName, id, ctx, {
|
|
25
|
-
dryRun: args.dryRun,
|
|
26
|
-
trigger: 'mutation',
|
|
27
|
-
});
|
|
28
|
-
return id;
|
|
29
|
-
}
|
|
30
|
-
case 'restore': {
|
|
31
|
-
const id = args.where.id;
|
|
32
|
-
await restoreEntity(modelName, id, ctx, 'mutation');
|
|
33
|
-
return id;
|
|
34
|
-
}
|
|
8
|
+
const withTransaction = async (ctx, fn) => await ctx.knex.transaction(async (knex) => fn({ ...ctx, knex }));
|
|
9
|
+
export const mutationResolver = async (_parent, args, partialCtx, info) => withTransaction({ ...partialCtx, info, aliases: new AliasGenerator() }, async (ctx) => {
|
|
10
|
+
const [, mutation, modelName] = it(info.fieldName.match(/^(create|update|delete|restore)(.+)$/));
|
|
11
|
+
switch (mutation) {
|
|
12
|
+
case 'create': {
|
|
13
|
+
const id = await createEntity(modelName, args.data, ctx, 'mutation');
|
|
14
|
+
return await resolve(ctx, id);
|
|
35
15
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
16
|
+
case 'update': {
|
|
17
|
+
const id = args.where.id;
|
|
18
|
+
await updateEntity(modelName, id, args.data, ctx, 'mutation');
|
|
19
|
+
return await resolve(ctx, id);
|
|
20
|
+
}
|
|
21
|
+
case 'delete': {
|
|
22
|
+
const id = args.where.id;
|
|
23
|
+
await deleteEntity(modelName, id, ctx, {
|
|
24
|
+
dryRun: args.dryRun,
|
|
25
|
+
trigger: 'mutation',
|
|
26
|
+
});
|
|
27
|
+
return id;
|
|
28
|
+
}
|
|
29
|
+
case 'restore': {
|
|
30
|
+
const id = args.where.id;
|
|
31
|
+
await restoreEntity(modelName, id, ctx, 'mutation');
|
|
32
|
+
return id;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
export const createEntity = async (modelName, input, ctx, trigger = 'direct-call') => withTransaction(ctx, async (ctx) => {
|
|
39
37
|
const model = ctx.models.getModel(modelName, 'entity');
|
|
40
38
|
const normalizedInput = { ...input };
|
|
41
39
|
if (!normalizedInput.id) {
|
|
@@ -92,14 +90,14 @@ export const createEntity = async (modelName, input, ctx, trigger = 'direct-call
|
|
|
92
90
|
ctx,
|
|
93
91
|
});
|
|
94
92
|
return normalizedInput.id;
|
|
95
|
-
};
|
|
96
|
-
export const updateEntities = async (modelName, where, updateFields, ctx) => {
|
|
93
|
+
});
|
|
94
|
+
export const updateEntities = async (modelName, where, updateFields, ctx) => withTransaction(ctx, async (ctx) => {
|
|
97
95
|
const entities = await ctx.knex(modelName).where(where).select('id');
|
|
98
96
|
for (const entity of entities) {
|
|
99
97
|
await updateEntity(modelName, entity.id, updateFields, ctx);
|
|
100
98
|
}
|
|
101
|
-
};
|
|
102
|
-
export const updateEntity = async (modelName, id, input, ctx, trigger = 'direct-call') => {
|
|
99
|
+
});
|
|
100
|
+
export const updateEntity = async (modelName, id, input, ctx, trigger = 'direct-call') => withTransaction(ctx, async (ctx) => {
|
|
103
101
|
const model = ctx.models.getModel(modelName, 'entity');
|
|
104
102
|
const normalizedInput = { ...input };
|
|
105
103
|
sanitize(ctx, model, normalizedInput);
|
|
@@ -131,16 +129,16 @@ export const updateEntity = async (modelName, id, input, ctx, trigger = 'direct-
|
|
|
131
129
|
ctx,
|
|
132
130
|
});
|
|
133
131
|
}
|
|
134
|
-
};
|
|
135
|
-
export const deleteEntities = async (modelName, where, ctx) => {
|
|
132
|
+
});
|
|
133
|
+
export const deleteEntities = async (modelName, where, ctx) => withTransaction(ctx, async (ctx) => {
|
|
136
134
|
const entities = await ctx.knex(modelName).where(where).select('id');
|
|
137
135
|
for (const entity of entities) {
|
|
138
136
|
await deleteEntity(modelName, entity.id, ctx, {
|
|
139
137
|
trigger: 'direct-call',
|
|
140
138
|
});
|
|
141
139
|
}
|
|
142
|
-
};
|
|
143
|
-
export const deleteEntity = async (modelName, id, ctx, { dryRun = false, trigger = 'direct-call', } = {}) => {
|
|
140
|
+
});
|
|
141
|
+
export const deleteEntity = async (modelName, id, ctx, { dryRun = false, trigger = 'direct-call', } = {}) => withTransaction(ctx, async (ctx) => {
|
|
144
142
|
const model = ctx.models.getModel(modelName, 'entity');
|
|
145
143
|
const rootModel = model.rootModel;
|
|
146
144
|
const entity = await getEntityToMutate(ctx, rootModel, { id }, 'DELETE');
|
|
@@ -199,7 +197,11 @@ export const deleteEntity = async (modelName, id, ctx, { dryRun = false, trigger
|
|
|
199
197
|
}
|
|
200
198
|
}
|
|
201
199
|
for (const { targetModel: descendantModel, field: { name, foreignKey, onDelete }, } of currentModel.reverseRelations.filter((reverseRelation) => !reverseRelation.field.inherited)) {
|
|
202
|
-
const query = ctx
|
|
200
|
+
const query = ctx
|
|
201
|
+
.knex(descendantModel.name)
|
|
202
|
+
.where({ [foreignKey]: currentEntity.id, deleted: false })
|
|
203
|
+
.orderBy('createdAt', 'asc')
|
|
204
|
+
.orderBy('id', 'asc');
|
|
203
205
|
const descendants = await query;
|
|
204
206
|
if (descendants.length) {
|
|
205
207
|
switch (onDelete) {
|
|
@@ -300,8 +302,8 @@ export const deleteEntity = async (modelName, id, ctx, { dryRun = false, trigger
|
|
|
300
302
|
restricted,
|
|
301
303
|
});
|
|
302
304
|
}
|
|
303
|
-
};
|
|
304
|
-
export const restoreEntity = async (modelName, id, ctx, trigger = 'direct-call') => {
|
|
305
|
+
});
|
|
306
|
+
export const restoreEntity = async (modelName, id, ctx, trigger = 'direct-call') => withTransaction(ctx, async (ctx) => {
|
|
305
307
|
const model = ctx.models.getModel(modelName, 'entity');
|
|
306
308
|
const rootModel = model.rootModel;
|
|
307
309
|
const entity = await getEntityToMutate(ctx, rootModel, { id }, 'RESTORE');
|
|
@@ -381,7 +383,11 @@ export const restoreEntity = async (modelName, id, ctx, trigger = 'direct-call')
|
|
|
381
383
|
for (const { targetModel: descendantModel, field: { foreignKey }, } of currentModel.reverseRelations
|
|
382
384
|
.filter((reverseRelation) => !reverseRelation.field.inherited)
|
|
383
385
|
.filter(({ targetModel: { deletable } }) => deletable)) {
|
|
384
|
-
const query = ctx
|
|
386
|
+
const query = ctx
|
|
387
|
+
.knex(descendantModel.name)
|
|
388
|
+
.where({ [foreignKey]: currentEntity.id, deleted: true })
|
|
389
|
+
.orderBy('createdAt', 'asc')
|
|
390
|
+
.orderBy('id', 'asc');
|
|
385
391
|
if (currentEntity.deleteRootId) {
|
|
386
392
|
query.where({ deleteRootType: currentEntity.deleteRootType, deleteRootId: currentEntity.deleteRootId });
|
|
387
393
|
}
|
|
@@ -405,7 +411,7 @@ export const restoreEntity = async (modelName, id, ctx, trigger = 'direct-call')
|
|
|
405
411
|
for (const callback of [...beforeHooks, ...mutations, ...afterHooks]) {
|
|
406
412
|
await callback();
|
|
407
413
|
}
|
|
408
|
-
};
|
|
414
|
+
});
|
|
409
415
|
export const createRevision = async (model, data, ctx) => {
|
|
410
416
|
if (model.updatable) {
|
|
411
417
|
const revisionId = uuid();
|