the documentation in this readme is work in progress, chaotic and incomplete
scrap your boilerplate by auto-generating dependencies!
quickly read and parse environment variables!
"env" ("Maybe")? ("String" | "Bool" | "Int" | "Float" | "Json") EnvVar
EnvVar
is converted from camelcase (example: BaseUrl
) to uppercase-underscored (example: BASE_URL
)
and looked up as property on the env
dependency.
envIntPort
parses int from envvarPORT
. throws if not present or not parseable.envBoolEnableEtags
parses bool from envvarENABLE_ETAGS
. throws if not present or not parseable.envStringDatabaseUrl
reads string from envvarDATABASE_URL
. throws if not present or blank.envFloatCommisionPercentage
parses float from envvarCOMMISSION_PERCENTAGE
. throws if not present or not parseable.envMaybeStringMandrillApikey
reads string from envvarMANDRILL_APIKEY
. returns null if not present or blank.envMaybeIntPoolSize
parses int from envvarPOOL_SIZE
. returns null if not present. throws if present and not parseable.envMaybeJsonPaymentConfig
parses json from envvarPAYMENT_CONFIG
. returns null if not present. throws if present and not parseable.- ...
serverside only
now you don't even need to define your mesa tables...
"table" Table
auto generate table:
userTable
will returnmesa.table('user')
orderReportTable
will returnmesa.table('order_report')
- ...
serverside only
mesa tables often need circular dependencies for associations. hinoki doesn't support circular dependencies. table object resolvers fix that.
"table" Table
Table
will be converted to start with a lowercase letter and
looked up as property on the table
dependency.
userTable
will returntable.user
orderReportTable
will returntable.orderReport
- ...
serverside only
("first" | "select") Table ("Where" Column)* ("OrderBy" Column ("Asc" | "Desc")?)* ("WithConnection")?
this code
selectPublicContentWhereIsActiveWhereViewCountOrderByViewCountOrderByIdDesc(
true,
{$lt: 100}
).then(function(rows) {
// ...
});
would execute a query similar to
SELECT *
FROM public_content
WHERE is_active = true
AND view_count < 100
ORDER BY view_count ASC, id DESC;
if it starts with first
it will limit the query by 1 and resolve to the first row or undefined if no rows were returned.
the optional suffix WithConnection
accepts an explicit connection as the last argument.
this is useful for transactions.
serverside only - for now
"insert" Table ("WithConnection")?
this code
insertUser({
email: 'test@example.com',
password: 'secret'
}).then(function(insertedUser) {
// ...
});
would execute a query similar to
INSERT INTO user (email, password)
VALUES ('test@example.com', 'secret');
the optional suffix WithConnection
accepts an explicit connection as the last argument.
this is useful for transactions.
in order to prevent a mass-assignment security vulnerability
the factory returned by "insert" Table
requires
a dependency named table "InsertableColumns"
(example: userInsertableColumns
) to be present!
serverside only - for now
"update" Table ("Where" Column)+ ("WithConnection")?
note the + at the end of the Where
: updates without conditions are not allowed for security reasons!
this code
updateUserWhereIdWhereName(
{email: 'test@example.com'},
100,
{$null: false}
).then(function(updatedUser) {
// ...
});
would execute a query similar to
UPDATE user
SET email = 'test@example.com'
WHERE id = 100
AND name IS NOT NULL;
the optional suffix WithConnection
accepts an explicit connection as the last argument.
this is useful for transactions.
in order to prevent a mass-assignment security vulnerability
the factory returned by "update" Table
requires
a dependency called table "UpdateableColumns"
(example: userUpdateableColumns
) to be present!
serverside only - for now
"delete" Table ("Where" Column)+ ("WithConnection")?
note the + at the end of the Where
: deletes without conditions are not allowed for security reasons!
this code
deleteUserWhereName('alice').then(function(deletedUser) {
// ...
});
would execute a query similar to
DELETE FROM user WHERE name = 'alice';
the optional suffix WithConnection
accepts an explicit connection as the last argument.
this is useful for transactions.
serverside only - for now
"String"
- static stringVariable
- user-provided, non-empty, camelcased string that is parsed from the pattern(a | b | c)
- a or b or c(a)*
- zero or many a(a)+
- one or many a(a)?
- optional a (zero or one)- spaces are used purely for readability
for example the pattern "env" ("Maybe")? ("String" | "Bool" | "Int" | "Float" | "Json") EnvVar
means the string env
followed by the optional string Maybe
followed by
either String
, Bool
, Int
, Float
, or Json
followed by any camelcased
string which will be bound to EnvVar
.
the string envMaybeStringDatabaseUrl
would satisfy that pattern with EnvVar = DatabaseUrl
.
you can not give arguments to the factories but through resolvers you can give some sort of arguments through the dependency names
insertMany
data loaders
select should take an optional last options argument which can contain limit, offset, orderBy, orderDir, orderAsc as well as a condition which can be any valid criterion for filtering and could be parsed from jsurl
$$firstPageWhereIdIsParamsId
$$pageWhereIsActive
$$pageOrderByCreatedAtDesc
$$pageByQuery
? scrap url boilerplate
this is heavy on conventions!!!
? make the conventions changeable
document that custom code with the same name takes precedence
its like rubys method missing.
fragments-forge is a resolver for hinoki containers that can autogenerate common data accessor functions, loaders, etc. according to some conventions and greatly reduce the amount of code needed.
- greatly reduces the amount of code needed
it allows you to ask for things that don't yet exist.
opinionated convention over configuration. entirely opt in. provides defaults which can all be explicitely overwritten.