@reventlessdev/reventless-local 3.0.0-alpha.187 → 3.0.0-alpha.188
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 +20 -0
- package/package.json +10 -10
- package/src/Platform.res +34 -0
- package/src/Platform.res.mjs +17 -0
- package/tests/components/task/TaskTest.res +6 -3
- package/tests/components/task/TaskTest.res.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 3.0.0-alpha.188 (2026-08-01)
|
|
7
|
+
|
|
8
|
+
* feat(aws,core,spec)!: qualify store prefixes by plugin and refuse name collisions ([da39405](https://github.com/ReventlessDev/reventless-core/commit/da394059d9f8f981bf7adc79e2c1ce2b429e0267))
|
|
9
|
+
* feat(core,aws)!: name task buckets for their plugin and task ([05203cb](https://github.com/ReventlessDev/reventless-core/commit/05203cb3b0b019401a6f32cf78109f397b6799d5))
|
|
10
|
+
|
|
11
|
+
### BREAKING CHANGES
|
|
12
|
+
|
|
13
|
+
* objects minted under the old bare prefix are orphaned and their
|
|
14
|
+
refs unresolvable. The migration is `seed:reset` for the owning plugin, then
|
|
15
|
+
re-seed. Legacy-prefix grandfathering was considered and deliberately dropped —
|
|
16
|
+
it would have added a permanent prefix SET across the deploy argument, both store
|
|
17
|
+
configs, the presign IAM fan-out, the release scope check and the stack output,
|
|
18
|
+
to spare a disposable stack one wipe.
|
|
19
|
+
* a bucket name change is a replace. TaskBucket_S3 now sets
|
|
20
|
+
forceDestroy on disposable stacks (Util_StoreLayout.protectionFor), so pr-*
|
|
21
|
+
stacks recreate cleanly; protected stacks must have the task bucket drained by
|
|
22
|
+
hand before the first deploy after this, or the replace fails BucketNotEmpty.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
6
26
|
# 3.0.0-alpha.187 (2026-08-01)
|
|
7
27
|
|
|
8
28
|
### Features
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-local",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.188",
|
|
4
4
|
"description": "Local platform for Reventless (in-memory or SQLite backend, for development and testing without AWS)",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": {
|
|
@@ -34,18 +34,18 @@
|
|
|
34
34
|
"graphql-yoga": "^5.21.0",
|
|
35
35
|
"sury": "11.0.0-alpha.4",
|
|
36
36
|
"ws": "^8.18.0",
|
|
37
|
-
"@reventlessdev/rescript-effect": "0.1.0-alpha.32",
|
|
38
|
-
"@reventlessdev/rescript-graphql-yoga": "1.0.0-alpha.26",
|
|
39
37
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
40
|
-
"@reventlessdev/rescript-
|
|
38
|
+
"@reventlessdev/rescript-graphql-yoga": "1.0.0-alpha.26",
|
|
39
|
+
"@reventlessdev/rescript-effect": "0.1.0-alpha.32",
|
|
41
40
|
"@reventlessdev/rescript-node": "2.0.0-alpha.0",
|
|
41
|
+
"@reventlessdev/rescript-mcp-sdk": "1.0.0-alpha.21",
|
|
42
42
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.18",
|
|
43
|
-
"@reventlessdev/reventless-core": "3.0.0-alpha.
|
|
44
|
-
"@reventlessdev/reventless-graphql-server": "1.0.0-alpha.
|
|
45
|
-
"@reventlessdev/reventless-
|
|
46
|
-
"@reventlessdev/reventless-postgres": "3.0.0-alpha.
|
|
47
|
-
"@reventlessdev/reventless-
|
|
48
|
-
"@reventlessdev/reventless-
|
|
43
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.200",
|
|
44
|
+
"@reventlessdev/reventless-graphql-server": "1.0.0-alpha.48",
|
|
45
|
+
"@reventlessdev/reventless-gwt": "1.0.0-alpha.147",
|
|
46
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.64",
|
|
47
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.92",
|
|
48
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.117"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"rescript": "12.3.0",
|
package/src/Platform.res
CHANGED
|
@@ -865,6 +865,40 @@ module MakeWithConfig = (
|
|
|
865
865
|
}
|
|
866
866
|
})
|
|
867
867
|
})
|
|
868
|
+
|
|
869
|
+
// Two plugins declaring one store name is refused by the deployed platform
|
|
870
|
+
// before it provisions anything. Local provisions no stores, so nothing here
|
|
871
|
+
// breaks — but this is the only place a developer meets the rule while the
|
|
872
|
+
// fix is still free: once a store has deployed, its minted refs are in an
|
|
873
|
+
// append-only event log and renaming it strands them. Hence a warning at
|
|
874
|
+
// composition, and the authoritative refusal at deploy.
|
|
875
|
+
let declared =
|
|
876
|
+
pluginStructuresStore.contents
|
|
877
|
+
->Dict.valuesToArray
|
|
878
|
+
->Array.flatMap(structure =>
|
|
879
|
+
structure.requiredStores
|
|
880
|
+
->Option.getOr([])
|
|
881
|
+
->Array.map(qualified => {
|
|
882
|
+
ReventlessCore.StorePrefixCollision.qualified,
|
|
883
|
+
// Local provisions no stores, so it has no prefix of its own — it
|
|
884
|
+
// restates the deployed rule (`{plugin}/{store}`) so the warning it
|
|
885
|
+
// gives matches the refusal a deploy would give. Reporting a collision
|
|
886
|
+
// the deployed platform does not have would be worse than silence.
|
|
887
|
+
prefix: switch qualified->String.indexOfOpt(".") {
|
|
888
|
+
| Some(i) =>
|
|
889
|
+
qualified->String.slice(~start=0, ~end=i) ++
|
|
890
|
+
"/" ++
|
|
891
|
+
qualified->String.slice(~start=i + 1, ~end=qualified->String.length)
|
|
892
|
+
| None => qualified
|
|
893
|
+
},
|
|
894
|
+
})
|
|
895
|
+
)
|
|
896
|
+
ReventlessCore.StorePrefixCollision.collisionsFor(~stores=declared)->Array.forEach(c =>
|
|
897
|
+
log.warn(
|
|
898
|
+
~comp="Platform:plugins",
|
|
899
|
+
ReventlessCore.StorePrefixCollision.collisionMessage(c),
|
|
900
|
+
)
|
|
901
|
+
)
|
|
868
902
|
}
|
|
869
903
|
|
|
870
904
|
// Bus keys for the admin Plugin aggregate (name-keyed). ComponentType.toName maps
|
package/src/Platform.res.mjs
CHANGED
|
@@ -55,6 +55,7 @@ import * as PlatformMCP_Server$ReventlessLocal from "./adapter/PlatformMCP_Serve
|
|
|
55
55
|
import * as Auth_GraphqlContext$ReventlessLocal from "./adapter/Auth/Auth_GraphqlContext.res.mjs";
|
|
56
56
|
import * as PgProjectionCatchup$ReventlessLocal from "./adapter/PgProjectionCatchup.res.mjs";
|
|
57
57
|
import * as PluginsReadModelSpec$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs";
|
|
58
|
+
import * as StorePrefixCollision$ReventlessCore from "@reventlessdev/reventless-core/src/util/StorePrefixCollision.res.mjs";
|
|
58
59
|
import * as DomainGraphQL_Server$ReventlessLocal from "./adapter/DomainGraphQL_Server.res.mjs";
|
|
59
60
|
import * as EventPublish_Callback$ReventlessCore from "@reventlessdev/reventless-core/src/components/EventLog/EventPublish_Callback.res.mjs";
|
|
60
61
|
import * as LocalUploadResolvers$ReventlessLocal from "./adapter/LocalUploadResolvers.res.mjs";
|
|
@@ -824,6 +825,14 @@ function MakeWithConfig(Config) {
|
|
|
824
825
|
}
|
|
825
826
|
});
|
|
826
827
|
});
|
|
828
|
+
let declared = Object.values(pluginStructuresStore.contents).flatMap(structure => Stdlib_Option.getOr(structure.requiredStores, []).map(qualified => {
|
|
829
|
+
let i = Stdlib_String.indexOfOpt(qualified, ".");
|
|
830
|
+
return {
|
|
831
|
+
qualified: qualified,
|
|
832
|
+
prefix: i !== undefined ? qualified.slice(0, i) + "/" + qualified.slice(i + 1 | 0, qualified.length) : qualified
|
|
833
|
+
};
|
|
834
|
+
}));
|
|
835
|
+
StorePrefixCollision$ReventlessCore.collisionsFor(declared).forEach(c => log.warn("Platform:plugins", undefined, StorePrefixCollision$ReventlessCore.collisionMessage(c)));
|
|
827
836
|
};
|
|
828
837
|
let pluginCmdTopicKey = PluginSpec$ReventlessCore.name + "AggrCmdTopic";
|
|
829
838
|
let pluginEventTopicKey = PluginSpec$ReventlessCore.name + "AggrEventTopic";
|
|
@@ -2500,6 +2509,14 @@ function Make($star) {
|
|
|
2500
2509
|
}
|
|
2501
2510
|
});
|
|
2502
2511
|
});
|
|
2512
|
+
let declared = Object.values(pluginStructuresStore.contents).flatMap(structure => Stdlib_Option.getOr(structure.requiredStores, []).map(qualified => {
|
|
2513
|
+
let i = Stdlib_String.indexOfOpt(qualified, ".");
|
|
2514
|
+
return {
|
|
2515
|
+
qualified: qualified,
|
|
2516
|
+
prefix: i !== undefined ? qualified.slice(0, i) + "/" + qualified.slice(i + 1 | 0, qualified.length) : qualified
|
|
2517
|
+
};
|
|
2518
|
+
}));
|
|
2519
|
+
StorePrefixCollision$ReventlessCore.collisionsFor(declared).forEach(c => log.warn("Platform:plugins", undefined, StorePrefixCollision$ReventlessCore.collisionMessage(c)));
|
|
2503
2520
|
};
|
|
2504
2521
|
let pluginCmdTopicKey = PluginSpec$ReventlessCore.name + "AggrCmdTopic";
|
|
2505
2522
|
let pluginEventTopicKey = PluginSpec$ReventlessCore.name + "AggrEventTopic";
|
|
@@ -90,9 +90,12 @@ describe("Task_Builder.Make:", () => {
|
|
|
90
90
|
let bucketNames = outputs.bucketNames->Option.getUnsafe
|
|
91
91
|
let idOutput = bucketNames->Dict.get("Reports")->Option.getUnsafe
|
|
92
92
|
let id = await idOutput->TestRunner.resolve
|
|
93
|
-
// In-memory bucket id = resource name
|
|
94
|
-
//
|
|
95
|
-
|
|
93
|
+
// In-memory bucket id = the bucket's resource name, which is kebab-cased
|
|
94
|
+
// and plugin-qualified because S3 lowercases a bucket name and a PascalCase
|
|
95
|
+
// one collapses into a run-on. No plugin segment here: the task is built
|
|
96
|
+
// outside any plugin, so there is no ambient plugin to qualify with.
|
|
97
|
+
// The runtime lookup key is a separate string and stays "Reports".
|
|
98
|
+
expect(id)->toBe("one-bucket-task-reports")
|
|
96
99
|
})
|
|
97
100
|
})
|
|
98
101
|
})
|
|
@@ -38,7 +38,7 @@ globalThis.describe("Task_Builder.Make:", () => {
|
|
|
38
38
|
let bucketNames = outputs.bucketNames;
|
|
39
39
|
let idOutput = bucketNames["Reports"];
|
|
40
40
|
let id = await TestRunner$ReventlessLocal.resolve(idOutput);
|
|
41
|
-
globalThis.expect(id).toBe("
|
|
41
|
+
globalThis.expect(id).toBe("one-bucket-task-reports");
|
|
42
42
|
});
|
|
43
43
|
});
|
|
44
44
|
});
|