effect-dynamodb 0.1.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/LICENSE +21 -0
- package/README.md +69 -0
- package/dist/Aggregate.d.ts +210 -0
- package/dist/Aggregate.d.ts.map +1 -0
- package/dist/Aggregate.js +1169 -0
- package/dist/Aggregate.js.map +1 -0
- package/dist/Batch.d.ts +62 -0
- package/dist/Batch.d.ts.map +1 -0
- package/dist/Batch.js +218 -0
- package/dist/Batch.js.map +1 -0
- package/dist/Collection.d.ts +58 -0
- package/dist/Collection.d.ts.map +1 -0
- package/dist/Collection.js +195 -0
- package/dist/Collection.js.map +1 -0
- package/dist/Collections.d.ts +121 -0
- package/dist/Collections.d.ts.map +1 -0
- package/dist/Collections.js +121 -0
- package/dist/Collections.js.map +1 -0
- package/dist/DynamoClient.d.ts +317 -0
- package/dist/DynamoClient.d.ts.map +1 -0
- package/dist/DynamoClient.js +653 -0
- package/dist/DynamoClient.js.map +1 -0
- package/dist/DynamoModel.d.ts +278 -0
- package/dist/DynamoModel.d.ts.map +1 -0
- package/dist/DynamoModel.js +453 -0
- package/dist/DynamoModel.js.map +1 -0
- package/dist/DynamoSchema.d.ts +137 -0
- package/dist/DynamoSchema.d.ts.map +1 -0
- package/dist/DynamoSchema.js +188 -0
- package/dist/DynamoSchema.js.map +1 -0
- package/dist/Entity.d.ts +628 -0
- package/dist/Entity.d.ts.map +1 -0
- package/dist/Entity.js +2371 -0
- package/dist/Entity.js.map +1 -0
- package/dist/Errors.d.ts +227 -0
- package/dist/Errors.d.ts.map +1 -0
- package/dist/Errors.js +93 -0
- package/dist/Errors.js.map +1 -0
- package/dist/EventStore.d.ts +208 -0
- package/dist/EventStore.d.ts.map +1 -0
- package/dist/EventStore.js +333 -0
- package/dist/EventStore.js.map +1 -0
- package/dist/Expression.d.ts +50 -0
- package/dist/Expression.d.ts.map +1 -0
- package/dist/Expression.js +170 -0
- package/dist/Expression.js.map +1 -0
- package/dist/KeyComposer.d.ts +125 -0
- package/dist/KeyComposer.d.ts.map +1 -0
- package/dist/KeyComposer.js +257 -0
- package/dist/KeyComposer.js.map +1 -0
- package/dist/Marshaller.d.ts +30 -0
- package/dist/Marshaller.d.ts.map +1 -0
- package/dist/Marshaller.js +115 -0
- package/dist/Marshaller.js.map +1 -0
- package/dist/Projection.d.ts +28 -0
- package/dist/Projection.d.ts.map +1 -0
- package/dist/Projection.js +39 -0
- package/dist/Projection.js.map +1 -0
- package/dist/Query.d.ts +214 -0
- package/dist/Query.d.ts.map +1 -0
- package/dist/Query.js +397 -0
- package/dist/Query.js.map +1 -0
- package/dist/Table.d.ts +178 -0
- package/dist/Table.d.ts.map +1 -0
- package/dist/Table.js +211 -0
- package/dist/Table.js.map +1 -0
- package/dist/Transaction.d.ts +79 -0
- package/dist/Transaction.d.ts.map +1 -0
- package/dist/Transaction.js +215 -0
- package/dist/Transaction.js.map +1 -0
- package/dist/_AggregateCursor.d.ts +44 -0
- package/dist/_AggregateCursor.d.ts.map +1 -0
- package/dist/_AggregateCursor.js +18 -0
- package/dist/_AggregateCursor.js.map +1 -0
- package/dist/_AggregateEdges.d.ts +77 -0
- package/dist/_AggregateEdges.d.ts.map +1 -0
- package/dist/_AggregateEdges.js +41 -0
- package/dist/_AggregateEdges.js.map +1 -0
- package/dist/_AggregateSchemas.d.ts +69 -0
- package/dist/_AggregateSchemas.d.ts.map +1 -0
- package/dist/_AggregateSchemas.js +194 -0
- package/dist/_AggregateSchemas.js.map +1 -0
- package/dist/_AggregateTypes.d.ts +94 -0
- package/dist/_AggregateTypes.d.ts.map +1 -0
- package/dist/_AggregateTypes.js +7 -0
- package/dist/_AggregateTypes.js.map +1 -0
- package/dist/_EntityCombinators.d.ts +155 -0
- package/dist/_EntityCombinators.d.ts.map +1 -0
- package/dist/_EntityCombinators.js +158 -0
- package/dist/_EntityCombinators.js.map +1 -0
- package/dist/_EntityConfig.d.ts +100 -0
- package/dist/_EntityConfig.d.ts.map +1 -0
- package/dist/_EntityConfig.js +7 -0
- package/dist/_EntityConfig.js.map +1 -0
- package/dist/_EntityOps.d.ts +205 -0
- package/dist/_EntityOps.d.ts.map +1 -0
- package/dist/_EntityOps.js +137 -0
- package/dist/_EntityOps.js.map +1 -0
- package/dist/_EntitySchemas.d.ts +57 -0
- package/dist/_EntitySchemas.d.ts.map +1 -0
- package/dist/_EntitySchemas.js +298 -0
- package/dist/_EntitySchemas.js.map +1 -0
- package/dist/_EntityTypes.d.ts +81 -0
- package/dist/_EntityTypes.d.ts.map +1 -0
- package/dist/_EntityTypes.js +7 -0
- package/dist/_EntityTypes.js.map +1 -0
- package/dist/_sparse_check.d.ts +2 -0
- package/dist/_sparse_check.d.ts.map +1 -0
- package/dist/_sparse_check.js +193 -0
- package/dist/_sparse_check.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/AggregateCursor.d.ts +44 -0
- package/dist/internal/AggregateCursor.d.ts.map +1 -0
- package/dist/internal/AggregateCursor.js +18 -0
- package/dist/internal/AggregateCursor.js.map +1 -0
- package/dist/internal/AggregateEdges.d.ts +77 -0
- package/dist/internal/AggregateEdges.d.ts.map +1 -0
- package/dist/internal/AggregateEdges.js +41 -0
- package/dist/internal/AggregateEdges.js.map +1 -0
- package/dist/internal/AggregateSchemas.d.ts +69 -0
- package/dist/internal/AggregateSchemas.d.ts.map +1 -0
- package/dist/internal/AggregateSchemas.js +193 -0
- package/dist/internal/AggregateSchemas.js.map +1 -0
- package/dist/internal/AggregateTypes.d.ts +94 -0
- package/dist/internal/AggregateTypes.d.ts.map +1 -0
- package/dist/internal/AggregateTypes.js +7 -0
- package/dist/internal/AggregateTypes.js.map +1 -0
- package/dist/internal/BoundQuery.d.ts +107 -0
- package/dist/internal/BoundQuery.d.ts.map +1 -0
- package/dist/internal/BoundQuery.js +111 -0
- package/dist/internal/BoundQuery.js.map +1 -0
- package/dist/internal/EntityCombinators.d.ts +173 -0
- package/dist/internal/EntityCombinators.d.ts.map +1 -0
- package/dist/internal/EntityCombinators.js +183 -0
- package/dist/internal/EntityCombinators.js.map +1 -0
- package/dist/internal/EntityConfig.d.ts +100 -0
- package/dist/internal/EntityConfig.d.ts.map +1 -0
- package/dist/internal/EntityConfig.js +7 -0
- package/dist/internal/EntityConfig.js.map +1 -0
- package/dist/internal/EntityOps.d.ts +268 -0
- package/dist/internal/EntityOps.d.ts.map +1 -0
- package/dist/internal/EntityOps.js +153 -0
- package/dist/internal/EntityOps.js.map +1 -0
- package/dist/internal/EntitySchemas.d.ts +57 -0
- package/dist/internal/EntitySchemas.d.ts.map +1 -0
- package/dist/internal/EntitySchemas.js +299 -0
- package/dist/internal/EntitySchemas.js.map +1 -0
- package/dist/internal/EntityTypes.d.ts +128 -0
- package/dist/internal/EntityTypes.d.ts.map +1 -0
- package/dist/internal/EntityTypes.js +7 -0
- package/dist/internal/EntityTypes.js.map +1 -0
- package/dist/internal/Expr.d.ts +141 -0
- package/dist/internal/Expr.d.ts.map +1 -0
- package/dist/internal/Expr.js +332 -0
- package/dist/internal/Expr.js.map +1 -0
- package/dist/internal/PathBuilder.d.ts +88 -0
- package/dist/internal/PathBuilder.d.ts.map +1 -0
- package/dist/internal/PathBuilder.js +100 -0
- package/dist/internal/PathBuilder.js.map +1 -0
- package/dist/internal/TransactableOps.d.ts +25 -0
- package/dist/internal/TransactableOps.d.ts.map +1 -0
- package/dist/internal/TransactableOps.js +58 -0
- package/dist/internal/TransactableOps.js.map +1 -0
- package/dist/internal/sparse_check.d.ts +2 -0
- package/dist/internal/sparse_check.d.ts.map +1 -0
- package/dist/internal/sparse_check.js +196 -0
- package/dist/internal/sparse_check.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal Entity schema building — derived schemas and system field resolution.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from Entity.ts for decomposition. Not part of the public API.
|
|
5
|
+
*/
|
|
6
|
+
import { Schema, SchemaAST } from "effect";
|
|
7
|
+
import { getEncoding, isHidden, isImmutable } from "./DynamoModel.js";
|
|
8
|
+
/** Check if a value is a Schema (has .ast property) vs a plain config object */
|
|
9
|
+
const isSchema = (value) => typeof value === "object" && value !== null && "ast" in value;
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a single TimestampFieldConfig into field name + encoding.
|
|
12
|
+
* Returns [fieldName, encoding | null].
|
|
13
|
+
*/
|
|
14
|
+
const resolveTimestampField = (config, defaultName) => {
|
|
15
|
+
if (config === undefined)
|
|
16
|
+
return [defaultName, null];
|
|
17
|
+
if (typeof config === "string")
|
|
18
|
+
return [config, null];
|
|
19
|
+
if (isSchema(config)) {
|
|
20
|
+
const encoding = getEncoding(config);
|
|
21
|
+
return [defaultName, encoding ?? null];
|
|
22
|
+
}
|
|
23
|
+
// Object config: { field?, schema? }
|
|
24
|
+
const fieldName = config.field ?? defaultName;
|
|
25
|
+
const encoding = config.schema ? (getEncoding(config.schema) ?? null) : null;
|
|
26
|
+
return [fieldName, encoding];
|
|
27
|
+
};
|
|
28
|
+
export const resolveSystemFields = (timestamps, versioned) => {
|
|
29
|
+
let createdAt = null;
|
|
30
|
+
let createdAtEncoding = null;
|
|
31
|
+
let updatedAt = null;
|
|
32
|
+
let updatedAtEncoding = null;
|
|
33
|
+
let version = null;
|
|
34
|
+
if (timestamps === true) {
|
|
35
|
+
createdAt = "createdAt";
|
|
36
|
+
updatedAt = "updatedAt";
|
|
37
|
+
}
|
|
38
|
+
else if (typeof timestamps === "object" && timestamps !== null) {
|
|
39
|
+
;
|
|
40
|
+
[createdAt, createdAtEncoding] = resolveTimestampField(timestamps.created, "createdAt");
|
|
41
|
+
[updatedAt, updatedAtEncoding] = resolveTimestampField(timestamps.updated, "updatedAt");
|
|
42
|
+
}
|
|
43
|
+
if (versioned === true) {
|
|
44
|
+
version = "version";
|
|
45
|
+
}
|
|
46
|
+
else if (typeof versioned === "object" && versioned !== null) {
|
|
47
|
+
version = versioned.field ?? "version";
|
|
48
|
+
}
|
|
49
|
+
return { createdAt, createdAtEncoding, updatedAt, updatedAtEncoding, version };
|
|
50
|
+
};
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Helper: collect primary key composite attribute names
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
export const primaryKeyComposites = (indexes) => {
|
|
55
|
+
const primary = indexes.primary;
|
|
56
|
+
if (!primary)
|
|
57
|
+
return [];
|
|
58
|
+
const composites = new Set();
|
|
59
|
+
for (const attr of primary.pk.composite)
|
|
60
|
+
composites.add(attr);
|
|
61
|
+
for (const attr of primary.sk.composite)
|
|
62
|
+
composites.add(attr);
|
|
63
|
+
return Array.from(composites);
|
|
64
|
+
};
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Helper: collect all key field names across all indexes
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
export const allKeyFieldNames = (indexes) => {
|
|
69
|
+
const fields = new Set();
|
|
70
|
+
for (const key of Object.keys(indexes)) {
|
|
71
|
+
const index = indexes[key];
|
|
72
|
+
if (index) {
|
|
73
|
+
fields.add(index.pk.field);
|
|
74
|
+
fields.add(index.sk.field);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return Array.from(fields);
|
|
78
|
+
};
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Helper: collect all composite attribute names across all indexes
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
export const allCompositeAttributes = (indexes) => {
|
|
83
|
+
const attrs = new Set();
|
|
84
|
+
for (const key of Object.keys(indexes)) {
|
|
85
|
+
const index = indexes[key];
|
|
86
|
+
if (index) {
|
|
87
|
+
for (const attr of index.pk.composite)
|
|
88
|
+
attrs.add(attr);
|
|
89
|
+
for (const attr of index.sk.composite)
|
|
90
|
+
attrs.add(attr);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return Array.from(attrs);
|
|
94
|
+
};
|
|
95
|
+
const hasFields = (schema) => "fields" in schema && typeof schema.fields === "object";
|
|
96
|
+
export const getFields = (model) => {
|
|
97
|
+
if (hasFields(model))
|
|
98
|
+
return model.fields;
|
|
99
|
+
throw new Error("Entity model must be a Schema.Class or Schema.Struct with .fields");
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Infer a default DynamoEncoding for standard Effect date schemas that lack
|
|
103
|
+
* an explicit DynamoEncoding annotation. This enables Pattern B (pure model
|
|
104
|
+
* with Schema.DateTimeUtcFromString etc.) to work without explicit storedAs.
|
|
105
|
+
*
|
|
106
|
+
* Detection uses the typeConstructor annotation from Effect's schema AST.
|
|
107
|
+
*/
|
|
108
|
+
export const inferDefaultEncoding = (schema) => {
|
|
109
|
+
const resolved = SchemaAST.resolve(schema.ast);
|
|
110
|
+
if (!resolved)
|
|
111
|
+
return undefined;
|
|
112
|
+
const tc = resolved.typeConstructor;
|
|
113
|
+
if (tc?._tag === "effect/DateTime.Utc")
|
|
114
|
+
return { storage: "string", domain: "DateTime.Utc" };
|
|
115
|
+
if (tc?._tag === "effect/DateTime.Zoned")
|
|
116
|
+
return { storage: "string", domain: "DateTime.Zoned" };
|
|
117
|
+
// Check for native Date via meta annotation
|
|
118
|
+
const meta = resolved.meta;
|
|
119
|
+
if (meta?._tag === "isDateValid")
|
|
120
|
+
return { storage: "string", domain: "Date" };
|
|
121
|
+
return undefined;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Map a DynamoEncoding domain type to its "from self" Schema.
|
|
125
|
+
* Used in record/item schemas so Schema.decode accepts domain values
|
|
126
|
+
* directly (after deserializeDateFields has converted storage→domain).
|
|
127
|
+
*/
|
|
128
|
+
const dateFromSelfSchema = (encoding) => {
|
|
129
|
+
switch (encoding.domain) {
|
|
130
|
+
case "DateTime.Utc":
|
|
131
|
+
return Schema.DateTimeUtc;
|
|
132
|
+
case "DateTime.Zoned":
|
|
133
|
+
return Schema.DateTimeZoned;
|
|
134
|
+
case "Date":
|
|
135
|
+
return Schema.DateValid;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
export const buildDerivedSchemas = (modelFields, indexes, systemFields, resolvedRefs = []) => {
|
|
139
|
+
// --- Build fromSelf field map for date fields ---
|
|
140
|
+
// These replace transform schemas with their "from self" variants so
|
|
141
|
+
// Schema.decode accepts domain values after storage→domain conversion.
|
|
142
|
+
// Checks both explicit DynamoEncoding annotations AND inferred defaults
|
|
143
|
+
// from standard Effect date schemas (Pattern B: pure model).
|
|
144
|
+
const fromSelfFields = {};
|
|
145
|
+
for (const [fieldName, fieldSchema] of Object.entries(modelFields)) {
|
|
146
|
+
const encoding = getEncoding(fieldSchema) ?? inferDefaultEncoding(fieldSchema);
|
|
147
|
+
if (encoding) {
|
|
148
|
+
fromSelfFields[fieldName] = dateFromSelfSchema(encoding);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// --- Model Schema: pure model fields (accepts wire format for input decode) ---
|
|
152
|
+
const modelSchema = Schema.Struct(modelFields);
|
|
153
|
+
// --- Model Decode Schema: model fields with fromSelf for date-annotated fields ---
|
|
154
|
+
// Used in decodeAs after deserializeDateFields has converted storage→domain.
|
|
155
|
+
const modelDecodeSchema = Object.keys(fromSelfFields).length > 0
|
|
156
|
+
? Schema.Struct({ ...modelFields, ...fromSelfFields })
|
|
157
|
+
: modelSchema;
|
|
158
|
+
// --- Record Schema: model + system fields ---
|
|
159
|
+
// For date-annotated fields, use "from self" schemas (accept domain values directly)
|
|
160
|
+
const systemSchemaFields = {};
|
|
161
|
+
if (systemFields.createdAt) {
|
|
162
|
+
// Custom encoding → use fromSelf (deserializeDateFields handles storage→domain)
|
|
163
|
+
// Default → use DateTimeUtcFromString (ISO string → DateTime.Utc)
|
|
164
|
+
systemSchemaFields[systemFields.createdAt] = systemFields.createdAtEncoding
|
|
165
|
+
? Schema.DateTimeUtc
|
|
166
|
+
: Schema.DateTimeUtcFromString;
|
|
167
|
+
}
|
|
168
|
+
if (systemFields.updatedAt) {
|
|
169
|
+
systemSchemaFields[systemFields.updatedAt] = systemFields.updatedAtEncoding
|
|
170
|
+
? Schema.DateTimeUtc
|
|
171
|
+
: Schema.DateTimeUtcFromString;
|
|
172
|
+
}
|
|
173
|
+
if (systemFields.version) {
|
|
174
|
+
systemSchemaFields[systemFields.version] = Schema.Number;
|
|
175
|
+
}
|
|
176
|
+
const recordSchema = Schema.Struct({
|
|
177
|
+
...modelFields,
|
|
178
|
+
...fromSelfFields,
|
|
179
|
+
...systemSchemaFields,
|
|
180
|
+
});
|
|
181
|
+
// --- Input Schema: ref-aware (swap ref fields for ID fields when refs present) ---
|
|
182
|
+
const refFieldSet = new Set(resolvedRefs.map((r) => r.fieldName));
|
|
183
|
+
const inputSchema = resolvedRefs.length > 0
|
|
184
|
+
? (() => {
|
|
185
|
+
const inputFields = {};
|
|
186
|
+
for (const [key, field] of Object.entries(modelFields)) {
|
|
187
|
+
if (refFieldSet.has(key))
|
|
188
|
+
continue; // skip ref fields
|
|
189
|
+
inputFields[key] = field;
|
|
190
|
+
}
|
|
191
|
+
// Add ID fields for each ref (uses the ref entity's identifier schema for branded types)
|
|
192
|
+
for (const ref of resolvedRefs) {
|
|
193
|
+
inputFields[ref.idFieldName] = ref.identifierSchema;
|
|
194
|
+
}
|
|
195
|
+
return Schema.Struct(inputFields);
|
|
196
|
+
})()
|
|
197
|
+
: modelSchema;
|
|
198
|
+
// --- Create Schema: input fields minus primary key composites ---
|
|
199
|
+
const pkComposites = new Set(primaryKeyComposites(indexes));
|
|
200
|
+
const createFieldsAcc = {};
|
|
201
|
+
for (const [key, field] of Object.entries(modelFields)) {
|
|
202
|
+
if (pkComposites.has(key))
|
|
203
|
+
continue; // skip PK composites (auto-generated)
|
|
204
|
+
if (refFieldSet.has(key))
|
|
205
|
+
continue; // skip ref fields (replaced by ID fields)
|
|
206
|
+
createFieldsAcc[key] = field;
|
|
207
|
+
}
|
|
208
|
+
// Add ID fields for each ref (skip if the ref field IS a PK composite)
|
|
209
|
+
for (const ref of resolvedRefs) {
|
|
210
|
+
if (pkComposites.has(ref.fieldName))
|
|
211
|
+
continue;
|
|
212
|
+
createFieldsAcc[ref.idFieldName] = ref.identifierSchema;
|
|
213
|
+
}
|
|
214
|
+
const createSchema = Schema.Struct(createFieldsAcc);
|
|
215
|
+
// --- Update Schema: optional model fields minus key composites & immutable ---
|
|
216
|
+
const updateFieldsAcc = {};
|
|
217
|
+
for (const [key, field] of Object.entries(modelFields)) {
|
|
218
|
+
if (pkComposites.has(key))
|
|
219
|
+
continue;
|
|
220
|
+
if (isImmutable(field))
|
|
221
|
+
continue;
|
|
222
|
+
if (refFieldSet.has(key))
|
|
223
|
+
continue; // skip ref fields in update (replaced by ID fields)
|
|
224
|
+
updateFieldsAcc[key] = Schema.optional(field);
|
|
225
|
+
}
|
|
226
|
+
// Add optional ID fields for each ref in update (uses ref entity's identifier schema)
|
|
227
|
+
for (const ref of resolvedRefs) {
|
|
228
|
+
if (pkComposites.has(ref.fieldName))
|
|
229
|
+
continue; // ref on PK composite — skip
|
|
230
|
+
if (isImmutable(modelFields[ref.fieldName]))
|
|
231
|
+
continue; // immutable ref — skip
|
|
232
|
+
updateFieldsAcc[ref.idFieldName] = Schema.optional(ref.identifierSchema);
|
|
233
|
+
}
|
|
234
|
+
const updateSchema = Schema.Struct(updateFieldsAcc);
|
|
235
|
+
// --- Key Schema: primary key composite attributes only ---
|
|
236
|
+
const keyCompositeNames = primaryKeyComposites(indexes);
|
|
237
|
+
const keyFields = {};
|
|
238
|
+
for (const name of keyCompositeNames) {
|
|
239
|
+
const field = modelFields[name];
|
|
240
|
+
if (field)
|
|
241
|
+
keyFields[name] = field;
|
|
242
|
+
}
|
|
243
|
+
const keySchema = Schema.Struct(keyFields);
|
|
244
|
+
// --- Item Schema: record + key attrs (pk, sk, gsi*) + __edd_e__ ---
|
|
245
|
+
const keyAttrFields = {};
|
|
246
|
+
for (const fieldName of allKeyFieldNames(indexes)) {
|
|
247
|
+
keyAttrFields[fieldName] = Schema.String;
|
|
248
|
+
}
|
|
249
|
+
const itemSchema = Schema.Struct({
|
|
250
|
+
...modelFields,
|
|
251
|
+
...fromSelfFields,
|
|
252
|
+
...systemSchemaFields,
|
|
253
|
+
...keyAttrFields,
|
|
254
|
+
__edd_e__: Schema.String,
|
|
255
|
+
});
|
|
256
|
+
// --- Deleted Record Schema: record + deletedAt ---
|
|
257
|
+
const deletedRecordSchema = Schema.Struct({
|
|
258
|
+
...modelFields,
|
|
259
|
+
...fromSelfFields,
|
|
260
|
+
...systemSchemaFields,
|
|
261
|
+
deletedAt: Schema.String,
|
|
262
|
+
});
|
|
263
|
+
// --- Hidden-aware decode schemas: strip DynamoModel.Hidden fields from model/record ---
|
|
264
|
+
// These are used for "model" and "record" decode modes. Hidden fields are
|
|
265
|
+
// still present in "item" and "native" modes.
|
|
266
|
+
const hiddenFieldNames = new Set();
|
|
267
|
+
for (const [fieldName, fieldSchema] of Object.entries(modelFields)) {
|
|
268
|
+
if (isHidden(fieldSchema))
|
|
269
|
+
hiddenFieldNames.add(fieldName);
|
|
270
|
+
}
|
|
271
|
+
const hasHiddenFields = hiddenFieldNames.size > 0;
|
|
272
|
+
const modelDecodeVisibleSchema = hasHiddenFields
|
|
273
|
+
? Schema.Struct(Object.fromEntries(Object.entries({ ...modelFields, ...fromSelfFields }).filter(([k]) => !hiddenFieldNames.has(k))))
|
|
274
|
+
: modelDecodeSchema;
|
|
275
|
+
const recordVisibleSchema = hasHiddenFields
|
|
276
|
+
? Schema.Struct(Object.fromEntries(Object.entries({
|
|
277
|
+
...modelFields,
|
|
278
|
+
...fromSelfFields,
|
|
279
|
+
...systemSchemaFields,
|
|
280
|
+
}).filter(([k]) => !hiddenFieldNames.has(k))))
|
|
281
|
+
: recordSchema;
|
|
282
|
+
return {
|
|
283
|
+
modelSchema: modelSchema,
|
|
284
|
+
modelDecodeSchema: modelDecodeVisibleSchema,
|
|
285
|
+
recordSchema: recordVisibleSchema,
|
|
286
|
+
inputSchema: inputSchema,
|
|
287
|
+
createSchema: createSchema,
|
|
288
|
+
updateSchema: updateSchema,
|
|
289
|
+
keySchema: keySchema,
|
|
290
|
+
itemSchema: itemSchema,
|
|
291
|
+
deletedRecordSchema: deletedRecordSchema,
|
|
292
|
+
};
|
|
293
|
+
};
|
|
294
|
+
// ---------------------------------------------------------------------------
|
|
295
|
+
// Unique constraint field resolver
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
297
|
+
export const resolveUniqueFields = (def) => Array.isArray(def) ? def : def.fields;
|
|
298
|
+
//# sourceMappingURL=_EntitySchemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_EntitySchemas.js","sourceRoot":"","sources":["../src/_EntitySchemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal Entity type-level computations — derived types for Entity operations.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from Entity.ts for decomposition. Not part of the public API.
|
|
5
|
+
*/
|
|
6
|
+
import type { DateTime, Schema } from "effect";
|
|
7
|
+
import type { RefNotFound } from "./Errors.js";
|
|
8
|
+
/** Extract the model's Type directly — preserves Schema.Class name (e.g. `User`) */
|
|
9
|
+
export type ModelType<TModel extends Schema.Top> = Schema.Schema.Type<TModel>;
|
|
10
|
+
/** Extract primary key composite attribute names as a string union */
|
|
11
|
+
export type PrimaryKeyComposites<TIndexes> = TIndexes extends {
|
|
12
|
+
readonly primary: {
|
|
13
|
+
readonly pk: {
|
|
14
|
+
readonly composite: infer PKC extends ReadonlyArray<string>;
|
|
15
|
+
};
|
|
16
|
+
readonly sk: {
|
|
17
|
+
readonly composite: infer SKC extends ReadonlyArray<string>;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
} ? PKC[number] | SKC[number] : string;
|
|
21
|
+
/** Compute system fields added by timestamps and versioned config */
|
|
22
|
+
export type SystemFieldsType<TTimestamps, TVersioned> = ([TTimestamps] extends [undefined] ? {} : [TTimestamps] extends [false] ? {} : {
|
|
23
|
+
readonly createdAt: DateTime.Utc;
|
|
24
|
+
readonly updatedAt: DateTime.Utc;
|
|
25
|
+
}) & ([TVersioned] extends [undefined] ? {} : [TVersioned] extends [false] ? {} : {
|
|
26
|
+
readonly version: number;
|
|
27
|
+
});
|
|
28
|
+
/** Entity key type: Pick model fields by primary key composites */
|
|
29
|
+
export type EntityKeyType<TModel extends Schema.Top, TIndexes> = Pick<ModelType<TModel>, PrimaryKeyComposites<TIndexes> & keyof ModelType<TModel>>;
|
|
30
|
+
/** Entity record type: model fields + system fields */
|
|
31
|
+
export type EntityRecordType<TModel extends Schema.Top, TTimestamps, TVersioned> = ModelType<TModel> & SystemFieldsType<TTimestamps, TVersioned>;
|
|
32
|
+
/** Entity input type: same as model fields (system fields auto-managed) */
|
|
33
|
+
export type EntityInputType<TModel extends Schema.Top> = ModelType<TModel>;
|
|
34
|
+
/** Entity update type: partial model fields minus primary key composites */
|
|
35
|
+
export type EntityUpdateType<TModel extends Schema.Top, TIndexes> = Partial<Omit<ModelType<TModel>, PrimaryKeyComposites<TIndexes>>>;
|
|
36
|
+
/** Extract PK-only composite attribute names (excludes SK) */
|
|
37
|
+
type PrimaryPkOnlyComposites<TIndexes> = TIndexes extends {
|
|
38
|
+
readonly primary: {
|
|
39
|
+
readonly pk: {
|
|
40
|
+
readonly composite: infer PKC extends ReadonlyArray<string>;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
} ? PKC[number] : never;
|
|
44
|
+
/** Extract the Entity from a ref value `{ entity: Entity, cascade?: ... }`. */
|
|
45
|
+
export type ExtractRefEntity<R> = R extends {
|
|
46
|
+
readonly entity: infer E;
|
|
47
|
+
} ? E : never;
|
|
48
|
+
/** Extract the identifier value type from a ref Entity's PK composites.
|
|
49
|
+
* For an entity with `pk: { composite: ["id"] }` and `id: TeamId`, yields `TeamId`. */
|
|
50
|
+
type EntityIdentifierValue<E> = ExtractRefEntity<E> extends {
|
|
51
|
+
readonly model: infer M extends Schema.Top;
|
|
52
|
+
readonly indexes: infer I;
|
|
53
|
+
} ? ModelType<M>[PrimaryPkOnlyComposites<I> & keyof ModelType<M>] : string;
|
|
54
|
+
/** Entity ref input type: when refs present, replace ref fields with branded ID fields */
|
|
55
|
+
export type EntityRefInputType<TModel extends Schema.Top, TRefs> = [TRefs] extends [undefined] ? ModelType<TModel> : Omit<ModelType<TModel>, keyof TRefs & string> & {
|
|
56
|
+
readonly [K in keyof TRefs & string as `${K}Id`]: EntityIdentifierValue<TRefs[K]>;
|
|
57
|
+
};
|
|
58
|
+
/** Entity ref update type: when refs present, swap ref fields for optional branded ID fields */
|
|
59
|
+
export type EntityRefUpdateType<TModel extends Schema.Top, TIndexes, TRefs> = [TRefs] extends [
|
|
60
|
+
undefined
|
|
61
|
+
] ? EntityUpdateType<TModel, TIndexes> : Partial<Omit<ModelType<TModel>, PrimaryKeyComposites<TIndexes> | (keyof TRefs & string)>> & {
|
|
62
|
+
readonly [K in keyof TRefs & string as `${K}Id`]?: EntityIdentifierValue<TRefs[K]>;
|
|
63
|
+
};
|
|
64
|
+
/** Error type contribution from refs — never when no refs, RefNotFound when refs present */
|
|
65
|
+
export type RefErrors<TRefs> = [TRefs] extends [undefined] ? never : RefNotFound;
|
|
66
|
+
/** Extract pk composite names for a specific index */
|
|
67
|
+
export type IndexPkComposites<TIndexes, K extends keyof TIndexes> = TIndexes[K] extends {
|
|
68
|
+
readonly pk: {
|
|
69
|
+
readonly composite: infer PKC extends ReadonlyArray<string>;
|
|
70
|
+
};
|
|
71
|
+
} ? PKC[number] : never;
|
|
72
|
+
/** Extract sk composite names for a specific index */
|
|
73
|
+
export type IndexSkComposites<TIndexes, K extends keyof TIndexes> = TIndexes[K] extends {
|
|
74
|
+
readonly sk: {
|
|
75
|
+
readonly composite: infer SKC extends ReadonlyArray<string>;
|
|
76
|
+
};
|
|
77
|
+
} ? SKC[number] : never;
|
|
78
|
+
/** Compute the typed query input for a specific index: PK composites required, SK composites optional */
|
|
79
|
+
export type IndexPkInput<TModel extends Schema.Top, TIndexes, K extends keyof TIndexes> = Pick<ModelType<TModel>, IndexPkComposites<TIndexes, K> & keyof ModelType<TModel>> & Partial<Pick<ModelType<TModel>, IndexSkComposites<TIndexes, K> & keyof ModelType<TModel>>>;
|
|
80
|
+
export {};
|
|
81
|
+
//# sourceMappingURL=_EntityTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_EntityTypes.d.ts","sourceRoot":"","sources":["../src/_EntityTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_EntityTypes.js","sourceRoot":"","sources":["../src/_EntityTypes.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_sparse_check.d.ts","sourceRoot":"","sources":["../src/_sparse_check.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-level verification for sparse GSI all-or-none constraints.
|
|
3
|
+
* This file is NOT shipped — it exists solely for `pnpm check` validation.
|
|
4
|
+
*
|
|
5
|
+
* Enforcement:
|
|
6
|
+
* - Data-first: Entity.set(self, updates) — type error at the call site (NoInfer<U>)
|
|
7
|
+
* - Data-last: .pipe(Entity.set(updates)) — clean types, runtime validation catches
|
|
8
|
+
* partial GSI composites. Runtime is always active on all code paths.
|
|
9
|
+
*
|
|
10
|
+
* § Why data-last loses the constraint (with core Effect comparison):
|
|
11
|
+
*
|
|
12
|
+
* Core Effect duals like Ref.set and HashMap.set use a SHARED type parameter
|
|
13
|
+
* across the outer and inner functions:
|
|
14
|
+
*
|
|
15
|
+
* Ref.set: <A>(value: A) → (self: Ref<A>) → Effect<void>
|
|
16
|
+
* HashMap.set: <K, V>(key: K, v: V) → (self: HashMap<K, V>) → HashMap<K, V>
|
|
17
|
+
*
|
|
18
|
+
* In data-last, A/V are inferred from the arguments. When piped, `self` is
|
|
19
|
+
* checked against that inferred type. Because Ref and HashMap are INVARIANT
|
|
20
|
+
* in their type parameter, a mismatch between the inferred A and self's A
|
|
21
|
+
* produces a type error on self.
|
|
22
|
+
*
|
|
23
|
+
* Entity.set is different. The update constraint U is an all-or-none union:
|
|
24
|
+
*
|
|
25
|
+
* U = { tenantId: string; region: string } | { tenantId?: never; region?: never }
|
|
26
|
+
*
|
|
27
|
+
* If we used the same shared-parameter pattern:
|
|
28
|
+
*
|
|
29
|
+
* <U>(updates: U) → (self: EntityUpdate<..., U, ...>) → EntityUpdate<..., U, ...>
|
|
30
|
+
*
|
|
31
|
+
* Then Entity.set({ tenantId: "t-3" }) infers U = { tenantId: string }. When
|
|
32
|
+
* piped, self's U (the all-or-none union above) would need to extend
|
|
33
|
+
* { tenantId: string }. But it doesn't — the NoneAllowed branch has
|
|
34
|
+
* tenantId?: never. So this WOULD error, but at the self position, producing
|
|
35
|
+
* a confusing "EntityUpdate<...> is not assignable to EntityUpdate<...>" message
|
|
36
|
+
* rather than the clear "missing property 'region'" error from data-first.
|
|
37
|
+
*
|
|
38
|
+
* Worse: for non-constrained fields the error is reversed. Entity.set({ name: "Alice" })
|
|
39
|
+
* infers U = { name: string }, then self's U (the all-or-none union) would need
|
|
40
|
+
* to extend { name: string } — but { tenantId?: never; region?: never } doesn't
|
|
41
|
+
* have name at all, so it would ALSO error, even though the update is perfectly valid.
|
|
42
|
+
*
|
|
43
|
+
* The module-level Entity.set uses `Updates extends Record<string, unknown>` in
|
|
44
|
+
* data-last to avoid these false positives, accepting that the constraint is
|
|
45
|
+
* enforced only at runtime. Data-first uses NoInfer<U> for precise type-level
|
|
46
|
+
* enforcement.
|
|
47
|
+
*
|
|
48
|
+
* § Entity-scoped set (the solution):
|
|
49
|
+
*
|
|
50
|
+
* Each Entity instance exposes a `.set` dual where U is pre-bound from the
|
|
51
|
+
* entity definition — following the schemaBodyJson(schema) factory pattern
|
|
52
|
+
* from Effect HTTP. Because U is resolved at entity creation (not inferred
|
|
53
|
+
* from the updates argument), both data-first and data-last paths are type-safe.
|
|
54
|
+
*/
|
|
55
|
+
import { Effect, HashMap, pipe, Ref, Schema } from "effect";
|
|
56
|
+
import * as DynamoSchema from "./DynamoSchema.js";
|
|
57
|
+
import * as Entity from "./Entity.js";
|
|
58
|
+
import * as Table from "./Table.js";
|
|
59
|
+
const AppSchema = DynamoSchema.make({ name: "test", version: 1 });
|
|
60
|
+
const MainTable = Table.make({ schema: AppSchema });
|
|
61
|
+
class Employee extends Schema.Class("Employee")({
|
|
62
|
+
employeeId: Schema.String,
|
|
63
|
+
name: Schema.NonEmptyString,
|
|
64
|
+
tenantId: Schema.String,
|
|
65
|
+
region: Schema.String,
|
|
66
|
+
}) {
|
|
67
|
+
}
|
|
68
|
+
const Employees = Entity.make({
|
|
69
|
+
model: Employee,
|
|
70
|
+
table: MainTable,
|
|
71
|
+
entityType: "Employee",
|
|
72
|
+
indexes: {
|
|
73
|
+
primary: {
|
|
74
|
+
pk: { field: "pk", composite: ["employeeId"] },
|
|
75
|
+
sk: { field: "sk", composite: [] },
|
|
76
|
+
},
|
|
77
|
+
byTenant: {
|
|
78
|
+
index: "gsi1",
|
|
79
|
+
pk: { field: "gsi1pk", composite: ["tenantId"] },
|
|
80
|
+
sk: { field: "gsi1sk", composite: ["region"] },
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
// -----------------------------------------------------------------------
|
|
85
|
+
// DATA-FIRST: Entity.set(self, updates) — runtime validated
|
|
86
|
+
// GSI all-or-none is no longer enforced at the type level (TS 25-member
|
|
87
|
+
// union assignability limit). These all compile; partial composites
|
|
88
|
+
// produce a ValidationError at runtime.
|
|
89
|
+
// -----------------------------------------------------------------------
|
|
90
|
+
// Partial GSI composites: tenantId without region — caught at runtime
|
|
91
|
+
Entity.set(Employees.update({ employeeId: "e-1" }), { tenantId: "t-3" });
|
|
92
|
+
// All GSI composites
|
|
93
|
+
Entity.set(Employees.update({ employeeId: "e-1" }), { tenantId: "t-3", region: "us-east-1" });
|
|
94
|
+
// No GSI composites
|
|
95
|
+
Entity.set(Employees.update({ employeeId: "e-1" }), { name: "Alice" });
|
|
96
|
+
// -----------------------------------------------------------------------
|
|
97
|
+
// PIPE PATH: .pipe(Entity.set({ ... })) — clean types, runtime-validated
|
|
98
|
+
// -----------------------------------------------------------------------
|
|
99
|
+
// Partial GSI composites: no type error in pipe path (runtime catches it)
|
|
100
|
+
const _pipeBadRuntime = Effect.gen(function* () {
|
|
101
|
+
yield* Employees.update({ employeeId: "e-1" }).pipe(Entity.set({ tenantId: "t-3" }));
|
|
102
|
+
});
|
|
103
|
+
// GOOD: all GSI composites in pipe
|
|
104
|
+
const _pipeGood1 = Effect.gen(function* () {
|
|
105
|
+
yield* Employees.update({ employeeId: "e-1" }).pipe(Entity.set({ tenantId: "t-3", region: "us-east-1" }));
|
|
106
|
+
});
|
|
107
|
+
// GOOD: no GSI composites in pipe
|
|
108
|
+
const _pipeGood2 = Effect.gen(function* () {
|
|
109
|
+
yield* Employees.update({ employeeId: "e-1" }).pipe(Entity.set({ name: "Alice" }));
|
|
110
|
+
});
|
|
111
|
+
// -----------------------------------------------------------------------
|
|
112
|
+
// PIPE CHAIN: Entity.set → Effect.map → Effect.catchTag composes cleanly
|
|
113
|
+
// -----------------------------------------------------------------------
|
|
114
|
+
// Partial GSI in pipe chain — no type error; runtime validation catches it.
|
|
115
|
+
// .asEffect() crosses the entity-op/Effect boundary before Effect combinators.
|
|
116
|
+
const _pipeChainPartial = Effect.gen(function* () {
|
|
117
|
+
const result = yield* Employees.update({ employeeId: "e-1" }).pipe(Entity.set({ tenantId: "t-3" }), (op) => op.asEffect(), Effect.map(() => "unexpected success"), Effect.catchTag("ValidationError", (e) => Effect.succeed(`Caught ValidationError: ${e.cause}`)));
|
|
118
|
+
return result;
|
|
119
|
+
});
|
|
120
|
+
// Full pipe chain with all GSI composites — .asEffect() at the boundary
|
|
121
|
+
const _pipeChainGood = Effect.gen(function* () {
|
|
122
|
+
const result = yield* Employees.update({ employeeId: "e-1" }).pipe(Entity.set({ tenantId: "t-3", region: "us-east-1" }), Entity.expectedVersion(1), (op) => op.asEffect(), Effect.map(() => "success"), Effect.catchTag("OptimisticLockError", () => Effect.succeed("lock failed")));
|
|
123
|
+
return result;
|
|
124
|
+
});
|
|
125
|
+
// -----------------------------------------------------------------------
|
|
126
|
+
// CORE EFFECT COMPARISON — why Ref.set / HashMap.set catch data-last
|
|
127
|
+
// mismatches but Entity.set cannot
|
|
128
|
+
// -----------------------------------------------------------------------
|
|
129
|
+
// Ref.set: shared type parameter A — invariant container catches mismatches
|
|
130
|
+
const _refExample = Effect.gen(function* () {
|
|
131
|
+
const ref = yield* Ref.make("red");
|
|
132
|
+
// Data-first: TYPE ERROR — "green" not in "red" | "blue"
|
|
133
|
+
// @ts-expect-error
|
|
134
|
+
yield* Ref.set(ref, "green");
|
|
135
|
+
// Data-last: ALSO TYPE ERROR — Ref<"red"|"blue"> not assignable to Ref<"green">
|
|
136
|
+
// The shared A is inferred as "green" from the argument, then self (Ref<"red"|"blue">)
|
|
137
|
+
// is checked — Ref is invariant, so the mismatch is caught.
|
|
138
|
+
// @ts-expect-error
|
|
139
|
+
yield* pipe(ref, Ref.set("green"));
|
|
140
|
+
});
|
|
141
|
+
// HashMap.set: shared type parameters K, V — invariant container catches mismatches
|
|
142
|
+
const _hashMapExample = Effect.gen(function* () {
|
|
143
|
+
const map = HashMap.make(["a", 1], ["b", 2]); // HashMap<string, number>
|
|
144
|
+
// Data-first: TYPE ERROR — "hello" is not number
|
|
145
|
+
// @ts-expect-error
|
|
146
|
+
HashMap.set(map, "c", "hello");
|
|
147
|
+
// Data-last: ALSO TYPE ERROR — HashMap<string, number> not assignable to HashMap<string, string>
|
|
148
|
+
// V is inferred as string from "hello", then self (HashMap<string, number>) is checked.
|
|
149
|
+
// @ts-expect-error
|
|
150
|
+
pipe(map, HashMap.set("c", "hello"));
|
|
151
|
+
});
|
|
152
|
+
// Entity.set: WHY it's different — the constraint is a union, not a simple type
|
|
153
|
+
//
|
|
154
|
+
// If Entity.set used the Ref/HashMap pattern (shared U parameter), then:
|
|
155
|
+
//
|
|
156
|
+
// Entity.set({ name: "Alice" }) // infers U = { name: string }
|
|
157
|
+
// // Returns: (self: EntityUpdate<..., { name: string }, ...>) => EntityUpdate<...>
|
|
158
|
+
//
|
|
159
|
+
// // When piped, self's U is the all-or-none union:
|
|
160
|
+
// // { tenantId: string; region: string } | { tenantId?: never; region?: never }
|
|
161
|
+
// // This union is NOT assignable to { name: string } — FALSE POSITIVE error.
|
|
162
|
+
// // A perfectly valid non-GSI update would be rejected.
|
|
163
|
+
//
|
|
164
|
+
// So the module-level Entity.set uses `Updates extends Record<string, unknown>`
|
|
165
|
+
// in data-last, accepting any record and deferring validation to runtime.
|
|
166
|
+
// -----------------------------------------------------------------------
|
|
167
|
+
// ENTITY-SCOPED SET: Employees.set() — runtime validated
|
|
168
|
+
// -----------------------------------------------------------------------
|
|
169
|
+
// Each Entity instance exposes a `.set` dual where U is pre-bound from the
|
|
170
|
+
// entity definition. GSI all-or-none is enforced at runtime.
|
|
171
|
+
// DATA-FIRST: partial GSI composites caught at runtime
|
|
172
|
+
Employees.set(Employees.update({ employeeId: "e-1" }), { tenantId: "t-3" });
|
|
173
|
+
// DATA-LAST: partial GSI composites caught at runtime
|
|
174
|
+
const _entityScopedBad = Effect.gen(function* () {
|
|
175
|
+
yield* Employees.update({ employeeId: "e-1" }).pipe(Employees.set({ tenantId: "t-3" }));
|
|
176
|
+
});
|
|
177
|
+
// GOOD: all GSI composites in entity-scoped pipe
|
|
178
|
+
const _entityScopedGood1 = Effect.gen(function* () {
|
|
179
|
+
yield* Employees.update({ employeeId: "e-1" }).pipe(Employees.set({ tenantId: "t-3", region: "us-east-1" }));
|
|
180
|
+
});
|
|
181
|
+
// GOOD: no GSI composites in entity-scoped pipe
|
|
182
|
+
const _entityScopedGood2 = Effect.gen(function* () {
|
|
183
|
+
yield* Employees.update({ employeeId: "e-1" }).pipe(Employees.set({ name: "Alice" }));
|
|
184
|
+
});
|
|
185
|
+
// PIPE CHAIN: Entity-scoped set composes with Effect.map/catchTag
|
|
186
|
+
const _entityScopedChain = Effect.gen(function* () {
|
|
187
|
+
const result = yield* Employees.update({ employeeId: "e-1" }).pipe(Employees.set({ tenantId: "t-3", region: "us-east-1" }), Employees.expectedVersion(1), (op) => op.asEffect(), Effect.map(() => "success"), Effect.catchTag("OptimisticLockError", () => Effect.succeed("lock failed")));
|
|
188
|
+
return result;
|
|
189
|
+
});
|
|
190
|
+
void _pipeBadRuntime, _pipeGood1, _pipeGood2, _pipeChainPartial, _pipeChainGood;
|
|
191
|
+
void _refExample, _hashMapExample;
|
|
192
|
+
void _entityScopedBad, _entityScopedGood1, _entityScopedGood2, _entityScopedChain;
|
|
193
|
+
//# sourceMappingURL=_sparse_check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_sparse_check.js","sourceRoot":"","sources":["../src/_sparse_check.ts"],"names":[],"mappings":"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"}
|