@suss/contract-wrangler 0.9.0 → 0.11.0
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/README.md +5 -1
- package/dist/index.cjs +56 -9
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +56 -9
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -25,10 +25,14 @@ queue = "greeting-events"
|
|
|
25
25
|
| --- | --- |
|
|
26
26
|
| `name`, `main` | the deployable unit and the code it runs |
|
|
27
27
|
| `[vars]` | the Worker's runtime configuration, names and values |
|
|
28
|
-
| `[[kv_namespaces]]`, `[[r2_buckets]]`, `[[d1_databases]]` | one store each |
|
|
28
|
+
| `[[kv_namespaces]]`, `[[r2_buckets]]`, `[[d1_databases]]` | one store each, under the binding name the code spells |
|
|
29
29
|
| `[[queues.producers]]`, `[[queues.consumers]]` | one channel each, on `cloudflare-queues` |
|
|
30
30
|
| `[env.<name>]` | the same Worker deployed again, with the top-level document as its default |
|
|
31
31
|
|
|
32
|
+
A store's container is the binding name, `SESSIONS`, because that is what an access in the Worker spells (`env.SESSIONS.get(...)`), and `@suss/framework-cloudflare-workers` records the same name on the code side, so the storage check pairs the two. The resource's own name, the KV namespace id or the bucket name, goes on the summary as `physicalTable`, the same split a Prisma model has between the model and the table it maps to.
|
|
33
|
+
|
|
34
|
+
Binding names are also listed on the runtime-config contract, beside the `[vars]` names: a binding is a property of the same `env` object, so a Worker that reads `env.AUDIT_KV` without a binding block for it gets the same finding as a read of a variable nobody set.
|
|
35
|
+
|
|
32
36
|
## The values, not only the names
|
|
33
37
|
|
|
34
38
|
A runtime-config contract usually records which variables a runtime supplies, and that is enough to say whether code reads one nobody set. A Worker needs more, because it addresses its stores through a variable:
|
package/dist/index.cjs
CHANGED
|
@@ -79,9 +79,9 @@ function storeSummaries(document, context) {
|
|
|
79
79
|
return summaries;
|
|
80
80
|
}
|
|
81
81
|
function storeSummary(store, entry, context) {
|
|
82
|
-
const
|
|
82
|
+
const resourceName = stringOf(entry[store.nameKey]);
|
|
83
83
|
const boundAs = stringOf(entry.binding);
|
|
84
|
-
if (
|
|
84
|
+
if (resourceName === null) {
|
|
85
85
|
return null;
|
|
86
86
|
}
|
|
87
87
|
return {
|
|
@@ -92,13 +92,15 @@ function storeSummary(store, entry, context) {
|
|
|
92
92
|
exportName: null
|
|
93
93
|
},
|
|
94
94
|
identity: {
|
|
95
|
-
name: `${store.block}.${boundAs ??
|
|
95
|
+
name: `${store.block}.${boundAs ?? resourceName}`,
|
|
96
96
|
exportPath: null,
|
|
97
97
|
boundaryBinding: (0, import_behavioral_ir.storageBinding)({
|
|
98
98
|
recognition: RECOGNITION,
|
|
99
99
|
storageSystem: store.storageSystem,
|
|
100
100
|
scope: "default",
|
|
101
|
-
|
|
101
|
+
// The binding name is what an access in the Worker spells, so
|
|
102
|
+
// it is the name the storage check pairs on.
|
|
103
|
+
container: boundAs ?? resourceName,
|
|
102
104
|
accessPath: null
|
|
103
105
|
})
|
|
104
106
|
},
|
|
@@ -107,11 +109,42 @@ function storeSummary(store, entry, context) {
|
|
|
107
109
|
gaps: [],
|
|
108
110
|
confidence: { source: "declared", level: "high" },
|
|
109
111
|
metadata: {
|
|
110
|
-
storageContract: {
|
|
112
|
+
storageContract: {
|
|
113
|
+
fieldSet: store.fieldSet,
|
|
114
|
+
physicalTable: resourceName
|
|
115
|
+
},
|
|
111
116
|
...boundAs === null ? {} : { wrangler: { binding: boundAs } }
|
|
112
117
|
}
|
|
113
118
|
};
|
|
114
119
|
}
|
|
120
|
+
var BINDING_BLOCKS = [
|
|
121
|
+
"kv_namespaces",
|
|
122
|
+
"r2_buckets",
|
|
123
|
+
"d1_databases",
|
|
124
|
+
"queues"
|
|
125
|
+
];
|
|
126
|
+
function bindingNames(document) {
|
|
127
|
+
const names = [];
|
|
128
|
+
for (const store of STORES) {
|
|
129
|
+
for (const entry of blockEntries(document[store.block])) {
|
|
130
|
+
const boundAs = stringOf(entry.binding);
|
|
131
|
+
if (boundAs !== null) {
|
|
132
|
+
names.push(boundAs);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const queues = asRecord(document.queues);
|
|
137
|
+
for (const entry of blockEntries(queues?.producers)) {
|
|
138
|
+
const boundAs = stringOf(entry.binding);
|
|
139
|
+
if (boundAs !== null) {
|
|
140
|
+
names.push(boundAs);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return names;
|
|
144
|
+
}
|
|
145
|
+
function asRecord(raw) {
|
|
146
|
+
return raw !== null && typeof raw === "object" && !Array.isArray(raw) ? raw : null;
|
|
147
|
+
}
|
|
115
148
|
function queueSummaries(document, context) {
|
|
116
149
|
const queues = document.queues;
|
|
117
150
|
if (queues === null || typeof queues !== "object") {
|
|
@@ -248,10 +281,22 @@ function environmentDocuments(document) {
|
|
|
248
281
|
return deployments;
|
|
249
282
|
}
|
|
250
283
|
function inheritedNames(document, overrides) {
|
|
251
|
-
|
|
252
|
-
|
|
284
|
+
const names = /* @__PURE__ */ new Set();
|
|
285
|
+
if (overrides.vars === void 0) {
|
|
286
|
+
for (const name of Object.keys(varsOf(document))) {
|
|
287
|
+
names.add(name);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const kept = {};
|
|
291
|
+
for (const block of BINDING_BLOCKS) {
|
|
292
|
+
if (overrides[block] === void 0) {
|
|
293
|
+
kept[block] = document[block];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
for (const name of bindingNames(kept)) {
|
|
297
|
+
names.add(name);
|
|
253
298
|
}
|
|
254
|
-
return
|
|
299
|
+
return names;
|
|
255
300
|
}
|
|
256
301
|
function nameOf(document) {
|
|
257
302
|
return typeof document.name === "string" && document.name.length > 0 ? document.name : null;
|
|
@@ -262,7 +307,9 @@ function varsOf(document) {
|
|
|
262
307
|
}
|
|
263
308
|
function runtimeConfigSummary(deployment, context) {
|
|
264
309
|
const vars = varsOf(deployment.merged);
|
|
265
|
-
const names =
|
|
310
|
+
const names = [
|
|
311
|
+
.../* @__PURE__ */ new Set([...Object.keys(vars), ...bindingNames(deployment.merged)])
|
|
312
|
+
].sort();
|
|
266
313
|
const sources = {};
|
|
267
314
|
const values = {};
|
|
268
315
|
for (const name of names) {
|
package/dist/index.d.cts
CHANGED
|
@@ -57,10 +57,11 @@ declare function loadConfigurationDocument(file: string): WranglerDocument;
|
|
|
57
57
|
*
|
|
58
58
|
* Every binding block in a Wrangler document has the same two halves:
|
|
59
59
|
* `binding`, the name the code reads it under, and a key giving the
|
|
60
|
-
* resource's own name. The code says the first, the deployment declares
|
|
61
|
-
* second, so a summary keeps both: the container is the
|
|
62
|
-
* name, which is what
|
|
63
|
-
* and `physicalTable`
|
|
60
|
+
* resource's own name. The code says the first, the deployment declares
|
|
61
|
+
* the second, so a summary keeps both: the container is the binding
|
|
62
|
+
* name, which is what an access in the Worker spells (`env.SESSIONS`),
|
|
63
|
+
* and `physicalTable` is the resource's own name, the same split a
|
|
64
|
+
* Prisma model has between the model and the table it maps to.
|
|
64
65
|
*/
|
|
65
66
|
|
|
66
67
|
/** The manifest language recorded on every binding this reader writes. */
|
package/dist/index.d.ts
CHANGED
|
@@ -57,10 +57,11 @@ declare function loadConfigurationDocument(file: string): WranglerDocument;
|
|
|
57
57
|
*
|
|
58
58
|
* Every binding block in a Wrangler document has the same two halves:
|
|
59
59
|
* `binding`, the name the code reads it under, and a key giving the
|
|
60
|
-
* resource's own name. The code says the first, the deployment declares
|
|
61
|
-
* second, so a summary keeps both: the container is the
|
|
62
|
-
* name, which is what
|
|
63
|
-
* and `physicalTable`
|
|
60
|
+
* resource's own name. The code says the first, the deployment declares
|
|
61
|
+
* the second, so a summary keeps both: the container is the binding
|
|
62
|
+
* name, which is what an access in the Worker spells (`env.SESSIONS`),
|
|
63
|
+
* and `physicalTable` is the resource's own name, the same split a
|
|
64
|
+
* Prisma model has between the model and the table it maps to.
|
|
64
65
|
*/
|
|
65
66
|
|
|
66
67
|
/** The manifest language recorded on every binding this reader writes. */
|
package/dist/index.js
CHANGED
|
@@ -38,9 +38,9 @@ function storeSummaries(document, context) {
|
|
|
38
38
|
return summaries;
|
|
39
39
|
}
|
|
40
40
|
function storeSummary(store, entry, context) {
|
|
41
|
-
const
|
|
41
|
+
const resourceName = stringOf(entry[store.nameKey]);
|
|
42
42
|
const boundAs = stringOf(entry.binding);
|
|
43
|
-
if (
|
|
43
|
+
if (resourceName === null) {
|
|
44
44
|
return null;
|
|
45
45
|
}
|
|
46
46
|
return {
|
|
@@ -51,13 +51,15 @@ function storeSummary(store, entry, context) {
|
|
|
51
51
|
exportName: null
|
|
52
52
|
},
|
|
53
53
|
identity: {
|
|
54
|
-
name: `${store.block}.${boundAs ??
|
|
54
|
+
name: `${store.block}.${boundAs ?? resourceName}`,
|
|
55
55
|
exportPath: null,
|
|
56
56
|
boundaryBinding: storageBinding({
|
|
57
57
|
recognition: RECOGNITION,
|
|
58
58
|
storageSystem: store.storageSystem,
|
|
59
59
|
scope: "default",
|
|
60
|
-
|
|
60
|
+
// The binding name is what an access in the Worker spells, so
|
|
61
|
+
// it is the name the storage check pairs on.
|
|
62
|
+
container: boundAs ?? resourceName,
|
|
61
63
|
accessPath: null
|
|
62
64
|
})
|
|
63
65
|
},
|
|
@@ -66,11 +68,42 @@ function storeSummary(store, entry, context) {
|
|
|
66
68
|
gaps: [],
|
|
67
69
|
confidence: { source: "declared", level: "high" },
|
|
68
70
|
metadata: {
|
|
69
|
-
storageContract: {
|
|
71
|
+
storageContract: {
|
|
72
|
+
fieldSet: store.fieldSet,
|
|
73
|
+
physicalTable: resourceName
|
|
74
|
+
},
|
|
70
75
|
...boundAs === null ? {} : { wrangler: { binding: boundAs } }
|
|
71
76
|
}
|
|
72
77
|
};
|
|
73
78
|
}
|
|
79
|
+
var BINDING_BLOCKS = [
|
|
80
|
+
"kv_namespaces",
|
|
81
|
+
"r2_buckets",
|
|
82
|
+
"d1_databases",
|
|
83
|
+
"queues"
|
|
84
|
+
];
|
|
85
|
+
function bindingNames(document) {
|
|
86
|
+
const names = [];
|
|
87
|
+
for (const store of STORES) {
|
|
88
|
+
for (const entry of blockEntries(document[store.block])) {
|
|
89
|
+
const boundAs = stringOf(entry.binding);
|
|
90
|
+
if (boundAs !== null) {
|
|
91
|
+
names.push(boundAs);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const queues = asRecord(document.queues);
|
|
96
|
+
for (const entry of blockEntries(queues?.producers)) {
|
|
97
|
+
const boundAs = stringOf(entry.binding);
|
|
98
|
+
if (boundAs !== null) {
|
|
99
|
+
names.push(boundAs);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return names;
|
|
103
|
+
}
|
|
104
|
+
function asRecord(raw) {
|
|
105
|
+
return raw !== null && typeof raw === "object" && !Array.isArray(raw) ? raw : null;
|
|
106
|
+
}
|
|
74
107
|
function queueSummaries(document, context) {
|
|
75
108
|
const queues = document.queues;
|
|
76
109
|
if (queues === null || typeof queues !== "object") {
|
|
@@ -207,10 +240,22 @@ function environmentDocuments(document) {
|
|
|
207
240
|
return deployments;
|
|
208
241
|
}
|
|
209
242
|
function inheritedNames(document, overrides) {
|
|
210
|
-
|
|
211
|
-
|
|
243
|
+
const names = /* @__PURE__ */ new Set();
|
|
244
|
+
if (overrides.vars === void 0) {
|
|
245
|
+
for (const name of Object.keys(varsOf(document))) {
|
|
246
|
+
names.add(name);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const kept = {};
|
|
250
|
+
for (const block of BINDING_BLOCKS) {
|
|
251
|
+
if (overrides[block] === void 0) {
|
|
252
|
+
kept[block] = document[block];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
for (const name of bindingNames(kept)) {
|
|
256
|
+
names.add(name);
|
|
212
257
|
}
|
|
213
|
-
return
|
|
258
|
+
return names;
|
|
214
259
|
}
|
|
215
260
|
function nameOf(document) {
|
|
216
261
|
return typeof document.name === "string" && document.name.length > 0 ? document.name : null;
|
|
@@ -221,7 +266,9 @@ function varsOf(document) {
|
|
|
221
266
|
}
|
|
222
267
|
function runtimeConfigSummary(deployment, context) {
|
|
223
268
|
const vars = varsOf(deployment.merged);
|
|
224
|
-
const names =
|
|
269
|
+
const names = [
|
|
270
|
+
.../* @__PURE__ */ new Set([...Object.keys(vars), ...bindingNames(deployment.merged)])
|
|
271
|
+
].sort();
|
|
225
272
|
const sources = {};
|
|
226
273
|
const values = {};
|
|
227
274
|
for (const name of names) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/contract-wrangler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Generate suss behavioral summaries from a Cloudflare wrangler.toml or wrangler.jsonc.",
|
|
6
6
|
"keywords": [
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"typecheck": "tsc --noEmit"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@suss/behavioral-ir": "0.
|
|
49
|
-
"@suss/ir-core": "0.
|
|
48
|
+
"@suss/behavioral-ir": "0.11.0",
|
|
49
|
+
"@suss/ir-core": "0.11.0",
|
|
50
50
|
"jsonc-parser": "^3.3.1",
|
|
51
51
|
"smol-toml": "^1.4.2"
|
|
52
52
|
},
|