exports.aws_canon_request_hash = aws_canon_request_hash
local aws_authorization_hdr_args_schema = T.table({
- date = T.transform(
- T.one_of({T.string(), T.literal(nil)}),
- function(v) return v or today_canonical() end
- ),
+ date = T.string():with_default(today_canonical),
secret_key = T.string(),
- method = T.transform(
- T.one_of({T.string(), T.literal(nil)}),
- function(v) return v or 'GET' end
- ),
+ method = T.string():with_default('GET'),
uri = T.string(),
region = T.string(),
- service = T.transform(
- T.one_of({T.string(), T.literal(nil)}),
- function(v) return v or 's3' end
- ),
- req_type = T.transform(
- T.one_of({T.string(), T.literal(nil)}),
- function(v) return v or 'aws4_request' end
- ),
+ service = T.string():with_default('s3'),
+ req_type = T.string():with_default('aws4_request'),
-- headers is a table with string keys and string values (map_of equivalent)
headers = T.table({}, { open = true, extra = T.string() }),
key_id = T.string(),
### Composition
- `schema:optional()` - Make schema optional
-- `schema:with_default(value)` - Add default value
+- `schema:with_default(value)` - Add default value (can be a function for dynamic defaults)
- `schema:doc(doc_table)` - Add documentation
- `schema:transform_with(fn)` - Apply transformation
- `T.transform(schema, fn)` - Transform wrapper
end)
```
+### Callable Defaults
+
+Defaults can be functions that are called each time a default is needed:
+
+```lua
+local function get_current_timestamp()
+ return os.time()
+end
+
+local event_schema = T.table({
+ name = T.string(),
+ timestamp = T.number():with_default(get_current_timestamp), -- Function called each time
+ priority = T.integer():with_default(0) -- Static default
+})
+
+-- Each transform gets a fresh timestamp
+local ok, event1 = event_schema:transform({ name = "login" })
+-- event1.timestamp will be the current time when transform was called
+```
+
### Schema Registry
```lua
if field_spec.optional then
-- Apply default in transform mode
if ctx.mode == "transform" and field_spec.default ~= nil then
- result[field_name] = field_spec.default
+ local default_val = field_spec.default
+ -- Support callable defaults: if default is a function, call it
+ if type(default_val) == "function" then
+ default_val = default_val()
+ end
+ result[field_name] = default_val
end
else
has_errors = true
local function check_optional(node, value, ctx)
if value == nil then
if ctx.mode == "transform" and node.default ~= nil then
- return true, node.default
+ local default_val = node.default
+ -- Support callable defaults: if default is a function, call it
+ if type(default_val) == "function" then
+ default_val = default_val()
+ end
+ return true, default_val
end
return true, nil
end