fragments-forge
the documentation in this readme is work in progress, chaotic and incomplete
scrap your boilerplate by auto-generating dependencies!
env
quickly read and parse environment variables!
pattern:
"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 envvar PORT
. throws if not present or not parseable.envBoolEnableEtags
parses bool from envvar ENABLE_ETAGS
. throws if not present or not parseable.envStringDatabaseUrl
reads string from envvar DATABASE_URL
. throws if not present or blank.envFloatCommisionPercentage
parses float from envvar COMMISSION_PERCENTAGE
. throws if not present or not parseable.envMaybeStringMandrillApikey
reads string from envvar MANDRILL_APIKEY
. returns null if not present or blank.envMaybeIntPoolSize
parses int from envvar POOL_SIZE
. returns null if not present. throws if present and not parseable.envMaybeJsonPaymentConfig
parses json from envvar PAYMENT_CONFIG
. returns null if not present. throws if present and not parseable.- ...
serverside only
table
now you don't even need to define your mesa tables...
pattern:
"table" Table
auto generate table:
userTable
will return mesa.table('user')
orderReportTable
will return mesa.table('order_report')
- ...
serverside only
table object
mesa tables often need circular dependencies for associations.
hinoki doesn't support circular dependencies.
table object resolvers fix that.
pattern:
"table" Table
Table
will be converted to start with a lowercase letter and
looked up as property on the table
dependency.
userTable
will return table.user
orderReportTable
will return table.orderReport
- ...
serverside only
select
pattern:
("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
pattern:
"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.
WARNING!
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
pattern:
"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.
WARNING!
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
pattern:
"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
simple regex-like pattern language used in this document
"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
.
todos, ideas and raw thoughts
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.