Releases: leafo/lapis
v1.17.0
Postgres Update
This version contains the first rewrite of the database modules to allow for running multiple connection configurations in parallel instead of relying on a global configuration. This refactor will eventually make it to the other database modules in future versions.
- The
lapis.db.postgresmodule is now a proxy object for the"default"connection configuration - Add
configurefunction tolapis.db.postgresto define a new connection configuration. (Returns a compatibledbobject) - Add
loggerfield todbobject. Thedbobject will use that logger for any logging actions (queries, connections). Defaults to the modulelapis.logger - Add
db_connectionlogger function tolapis.logger. The default implementation is empty and is designed to be overridden. - Postgres connection now emits
logging.db_connection(db, pgmoon, success, err)so you can add metrics on connections as you see fit - Removed the
pgmoon_connperformance fields, they were unreliable given that multiple connections could be created in a single request - Add explicit
disconnectandconnectfunctions to thedbmodule. The connection configuration can automatically reconnect if the connection has been disconnected. - Note: The entire
lapis.db.postgresmodule has mostly been rewritten, if you were relying on undocumented exports for custom behavior you should review your code before deploying
Other additions
- Added
timer_attolapis.nginx, a safe wrapper aroundngx.timer.atthat runs callbacks underpcall, bubbles errors, and guaranteesafter_dispatchis called to clean up any database connections - After dispatch callbacks are removed after running to prevent double running if manually called
lapis.httpdefaults tosocket.httpunless the cqueues is explicitly running (previously it would try to load lua-http)params_shapeacceptslabel = false, letting you hide the automaticfield:prefix when you want bare error strings or custom labels.- Add support for dot syntax in default Nginx config template syntax to access fields of tables, eg.
${{postgres.host}}
Fixes
- Fix a bug where a nested preload could try to load relations on a basic value type that was returned by a relation
CLI
- Top level
lapiscommand supports a--dirflag (requiresluafilesystem), so you can runlapisfrom outside the project root - Add
lapis mcpshortcut for the lapis-mcp package - When using
lapis generate migrationthe name of the generated migration is now printed to stdout
v1.16.0
Install
luarocks install lapis
Additions
lapis.validate.types-- Addtypes.params_mapvalidation type, the params compatible variant oftypes.map_of
Changes
model:updatewill now only assign the update object to the model instance if the update completes successfullymodel:updatesupport thereturnsoption to control theRETURNINGclause of the generated querymodel:updatewhen timestamps are enabled, the generatedupdated_atvalue is assigned to the model instance
Fixes
lapis.validate.types-- Fix bug wheretypes.params_shapewould not return the state objectmodel:updatewill avoid storingdb.rawvalues on passed as update object to the model instance if the update does not complmete successfully
v1.15.0
Install
luarocks install lapis
Additions
Model:include_incan now use computed keys to dynamically calculate a foreign key value by applying a function to each passed in object to load. This can be done by specifying a function instead of a field name when defining the column mapping table- Relations can use compured keys where appropriate by passing a function instead of a field name when defining the column mapping table
lapis.validate.types-- addtypes.params_arrayfor validating an array of objects with a common shapelapis.validate.types-- addtypes.flatten_errorsfor error output compatibility with tableshapelapis.validate.types--types.params_shapecan now accept numerical names for fields for validating array like objects with a fixed number of entrieslapis generate-- Rockspec generator can now specify--moonscriptand--cqueuesto automatically append dependencieslapis migrate-- Add the--dry-runflag to to run all pending migrations in a transaction that is never commited. (Note: in some databases, there are queries that can not be rolled back)
Misc
- Various updates to documentation
- Fix error message for
types.truncated_text
v1.14.0
Install
luarocks install lapis
Additions
- Add
--rockspeccommand tolapis new - Add
lapis generate migrationcommand to either create blank migration file or append a new migration at the end of the existing migration file. Seelapis generate migration --helpfor more information- Can append to Lua and MoonScript migrations files. It may not be able to edit all types of migration files, ensure that you return a simple table.
- Support for appending either timestamp named migration or incrementing counter named migration
- Add
lapis generate rockspeccommand to create a new rockspec for managing app dependencies. Seelapis generate rockspec --helpfor more information- It will automatically detect the app name fro the current directory, if not specified with
--app-name - It will automatically detect the git source URL from the current directory if a git repository has been created and has a remote
- Additional initial dependencies can be included with flags like
--postgres,--sqlite,--moonscript, etc.
- It will automatically detect the app name fro the current directory, if not specified with
Fixes
- Fix code reloading for cqueues when changes to
package.path,package.cpath,package.searchers, andpackage.loadersis involved- These values will be reset to prevent infinitely growing module search path when reloading code
- Fix bug with
lapis simulatecommand where header output wouldn't be normalized correctly - Fix bug where
lapis.validate.typesparams_shapewas not correctly passing initial state object through the validation
Changes
-
Update custom sub-command runner to support running commands with
argparsespecification- Update built in support for lapis annotate and lapis sytemd to work with this new system. It is necessary to update both of those packages if you wish to use them with this version of Lapis
-
Rewrite all template files that
lapis newcreates as generator modules. All of these files can be independently created using thelapis generatecommand if necessary, eg.lapis generate applapis newwill now internally calllapis generateto create the necessary fileslapis generate {NAME} --helpcan now be used for every template generator to view configuration options- List of updated generators: (these can be called with
lapis generate {NAME})app– For creating initial lapis application file in (app.luaorapp.moon)config– For creatingconfig.luaorconfig.moonmodels– For creating autoloadermodules.luaormodules.moonmodulegitignore– For creating initial.gitignorewhen usinglapis new --gittupfile– For creating initial Tupfile and Tuprules.tup when usinglapis new --tupnginx.config– For creating initialnginx.confnginx.mime_types– For creatingmime.typesnginx configuration include
-
The default generated config for cqueues on MoonScript now longer includes fields for
code_cacheandnum_workers, and instead now matches the Lua version of the config. -
lapis.dbdb.clausesupports aprefixoption to optionally append something to the front of the encoded clause if it contains any fields. -
lapis.db.modelGenericpreloadcan take the a callback function with the name of a relation to execute a callback on the loaded objects. Eg. `preload(users, { profile = function(profiles) ... end }) -
Model:include_inaddskip_includedoption to do nothing on objects that already have the related field loaded -
Model:include_inaddloaded_results_callbackoption to provide a function callback to be called with with the list of objects that were fetched from the query -
Model:include_inwhen loading objects by a composite key, duplicate composite values will be stripped to reduce the size of the query generated (Singular keys already functioned this way) -
lapis.db.model.relationsmark_loaded_relationscan now take a third argument of a value to set for the relation (defaults totrue) -
lapis.utilsingularizefunction has been improved slightly with more cases (eg. vertex, child, index, status) and will work with all capital words. Note that this function will never be comprehensive, only suitable for calculating a quick default in scenarios where names aren't explicitly specified -
lapis.validate.typesAddmulti_paramsfor joining twoparams_shapeobjects together
Internal Changes
- Rewrite generic
preload - Add much more comprehensive test suite for generic
preload
Full Changelog: v1.13.1...v1.14.0
v1.13.0
Install
luarocks install lapis
Additions
- Add the
lapis simulatecommand to simulate a request to the application
without starting a server. This is useful for testing and debugging. See
lapis simulate --helpfor details about usage. - Add support for SQLite (See
lapis.db.sqlite,lapis.db.sqlite.model,
lapis.db.sqlite.schema`) - Add
request:get_request()method to get a reference to the request object.
(Note this just returnsself, but it is useful in cases where the request
object is being proxied through the helper chain of a widget)
Changes
- The default error page will now render a JSON response if the
accept
request header is set toapplication/json content_fornow stores content blocks directly on the request object
(prefixed with_content_for). This may solve a bug where widget helper
chain could have cached an outdated copy of thecontent_forstate.content_forwill now throw an error if attempted to be used in a context
without a request object- Layout content rendering has been simplified to avoid additional closure and
function scope created - The resolved layout is now written to
request.options(akaself.options)
so that the view can know if a layout will be rendered within the current
request. Note: actions that skip layout by default (eg.json,redirect_to)
will writefalsetooptions.layout. - Internal refactors to all of the database modules, removal of some
undocumented functions (removedset_backend,set_logger,get_logger,init_logger) - Updated generated SQL for MySQL in some places to output keywords in capitals
lapis.db.paginationPaginators now have a simple fallback for clause
generation when the database module lacks a clause parser. (Will work for
simple queries without aggregates instead of throwing an error when calling
total_itemsandhas_items)lapis.specRemove undocumented test helpers:use_db_connection,assert_no_queries.lapis.specuse_test_envanduse_test_serverno longer interact with
database connection insetupandteardown.lapis.spec.requestThe mockedngxobject now covers more fields to make
it suitable for more kinds of requests
Full Changelog: v1.12.0...v1.13.0
v1.12.0
Install
luarocks install lapis
Additions
- Add the
lapis.validate.typesmodule with tableshape compatible types for parameter validation:params_shape,assert_error,cleaned_text,valid_text,trimmed_text,truncated_text,limited_text,empty,file_upload,db_id,db_enum lapis.validateAdd thewith_paramshelper function for wrapping action function with parameter validationlapis.util.utf8Addstring_lengthfunction for counting the number of characters in a string- The
lapis newcommand will always write a config.lua/config.moon file. The default configuration's nginx specific variables will be phased out a future update - The
lapis generatesub commands now can generate both Lua and MoonScript files. Project type detection has been added, in addition to flags to directly specify the file type
Changes
- The
lapiscommand line tool's argument parsing has been rewritten using argparse. New help commands are available for every command, with full argument documentation. - The
lapis generatesubcommands now use argparse and have full command line documentation available - The
lapis newcommand will now fail if the requested server type is not available. The--forceoption can be used to bypass the error - The default nginx.conf file now include an
init_by_luablock as an example to suppress global variable warning - Command line third-party sub commands now are executed using the
_command. Seelapis help _ lapis.applicationyield_errornow has a default error message if one isn't providedlapis.validateassert_validcan take a tableshape object as the validation object. Will return transformed value and state on successlapis.dbencode_clausewill now generate query with capitalNOTwhen using false value
Misc
- Internal reorganization for command line commands and path library
- Revised documentation for input validation
Full Changelog: v1.11.1...v1.12.0
v1.11.1
Fixes
db.clausesupports having adb.listobject as the key of a field to represent composite tuple (matches behavior of bare table passed todb.encode_clause)- fixes regression where
where:clause could not be combined with composite key inmodel:include_indue to the refactored clause generation implemented in 1.10.0
- fixes regression where
Changes
preloadwill only try to process sub-relations if the value of the field is a string or table
Full Changelog: v1.11.0...v1.11.1
v1.11.0
Install
luarocks install lapis
Highlights
- Substantially improved performance for
url_forgeneration - Introduce
db.clause - Lua is now first class. Etlua improvements. Application class APIs match Lua & MoonScript. Documentation and APIs show Lua by default
- Homepage and documentation have been substantially updated
Additions
lapis.dbAdd thedb.clauseconstructor for safely building SQL fragments including clauses and conditionals- All db related methods can now take
db.clauseobjects when appropriate for configuring filtering (eg.Model:find, relationwhere:clause, etc.) lapis.dbThelapis.db.encode_clausefunction can be used to convert adb.clauseobject a fragment of SQL codelapis.applicationAddApplication:extend()method to create a sub-class ofApplicationwhen MoonScript is not availablelapis.applicationAll route related methods are now consistently available for both application instances and classes. This includesinclude,match,extend,find_action,before_filter,get,post,put,deletelapis.sessionTheget_sessionfunction can now take a string object as first argument, as an alternative to the request object, to decode a session from a cookie's string valuelapis.htmlAddWidget:extend()method for creating sublcass of theWidgetclass when MoonScript is not availablelapis.htmlTheclassnamesfunction will now recurisvely evaluate any tables in the argumentlapis.htmlAddis_mixins_classfunction to determine if a class is a dynamically generated mixin class created byWidget:includelapis.etluaTheelementfunction has been added to the template scope to allow rendering HTML elements programmatically (similar to the HTML builder syntax)lapis.etluaselfhas been added to the template scope to allow accessing the instance of theEtluaWidget- The
lapis migratecommand now supports a--transactionflag, can be set toglobalto apply a transaction across all migrations to be run, orindividualto apply a transaction to each migration run. lapis.flowAddFlow:extend()method for sublcassing theFlowclass
Changes
lapis.dbInternally, queries now usedb.clauseto generate SQL conditional statements . This means that order of certain fields may now be different when usingwhereclauses.lapis.dbIt is no longer possible to override fields configured by a relation when specifying awhere:option. This also applies to paginators generated for relationslapis.db.modelRelations can now be specified with a direct reference to a Model class, or a function that should resolve to a Model class (existing support for relation name has not changed)lapis.applicationInheritance of routes is now more well defined, allowing for route names and paths to be overidden by subclasses or instances during the creation of the router. If you aren't using application inheritance then this will not affect you.lapis.applicationLazy action loading is now supported for actions generated byincludeand actions built by the HTTP verbmatchhelpers (get,post, etc.). Previously, if provided an action name (ortrue), it would load the action module immediately. Now all named actions are consistently loaded on first request regardless of where they are usedlapis.applicationThefind_actionmethod now searches up inheritance hierarchy, and can be used on both app classes and instanceslapis.applicationTrying to callenableormatchdirectly on thelapis.Applicationclass reference will now throw an error to help prevent accidentally mutating the global objectlapis.htmlTheWidget:render()method will now return nothing instead ofnillapis.routerRouter URL creation (akaurl_for) has been rewritten to be substantially faster. Previously routes were re-parsed on calls tourl_forbut will not generate from a cached intermediate form that will allow the URL to be generated with little overhead.lapis.cqueuesAdd error capturing around the app boot process to provide better error message when attempting to load a faulty app, and prevent infinite loop processing bug fromlua-http- The environment variable
LAPIS_FORCE_LOGGINGcan not be set to0to force logging off - The
applicationfield is no longer present on thelapis.initmodule. This was never documented. Userequire("lapis.application")instead. - Many error messages have been rewritten to be prefixed with the module or method they originate from
Internal Changes
These changes should have no effect on the end user implementing an app, but
they are documented here in case you were depending on the undocumented
structure of lapis
lapis.applicationThe internal structure used by the HTTP verbmatchhelpers has been changed (get,post, etc.)lapis.routerParsed routes are now stored, and the arguments forfill_pathhave changedlapis.applicationThe way routes are internally managed and iterated has been rewritten to provide unified interface based on metatable inheritance. Thelapis.application.route_groupmodule has been added to work with this interface.
Misc
- Substantial updates to documentation, including rewrites for clarify and documenting fields that were previously not documented.
- Changes to the homepage to prioritize Lua syntax over MoonScript to reduce confusion about what & who the framework is for
Full Changelog: v1.10.0...v1.11.0
v1.10.0
Install
luarocks install lapis
Additions
Model:include_insupports a new{ load = false }option to disable the conversion of query results to model instances- You can now specify
{ order = false }when creating a paginator from a model relation to strip the default order that may have been specified in the relation definition lapis.util.utf8: Add a UTF8 aware trim LPeg pattern, calledtrim) (Note: the utility functiontrimlocatedlapis.utilstill only operates on ascii whitespace)
Postgres
model:updatemethod can take awhereclause to apply a conditional update- The return value of
model:updateis now well defined, and works similar tomodel:delete. Will return booleantrue/falsedepending on if the update was able complete, and the resulting object from the update query. (Warning: Previouslymodel:updatewould return the result object regardless of success as the first return value, but this functionality was undocumented.) db.insertcan now take options as a table, and supports receivingreturningcolumns as a option- Add the
{ on_conflict = "do_nothing" }option todb.insertto not throw an error if insertion is canceled due to a unique key constraint conflict (using theON CONFLICT DO NOTHINGquery syntax introduced in Postgres 9.5)
MySQL
model:updatewill returntrueif the number of affected rows is greater than 0, followed by the result object
Changes
lapis.html: All element helper methods (eg.div,b,span, etc.) now returnnilinstead of the previously undocumented behavior of returning the buffer object. This is to prevent accidentally leaking data when writing malformed syntax such asdiv div!(instead of the correct (div -> div!)lapis.util.utf8: whitespace pattern is aware of invalid use of direction markerslapis.db.postgres.model: On model creation, if areturning *clause is provided then unnecessary extra returning fields are not included in the querylapis.db.postgres: Nginx environment detection is more accurate to allow pgmoon connections to be created without error in more stages of the Nginx worker/request lifecyclelapis.db.postgres: OpenResty specific performance metrics about socket reuse are only written when an nginx socket is in uselapis.db.postgres: Add connection specific performance metric for when any socket type other than nginx is used
Bugs
lapis.validate: Fixed bug where the input options table passed into validate would get mutated, removing theoptionalfield
Misc
- Assorted updates to docs
- Expanded test suite, refactors to tests
- Documentation typo fixes by @tommy-mor in #734 #746
New Contributors
- @tommy-mor made their first contribution in #734
Full Changelog: v1.9.0...v1.10.0
v1.9.0
Changes
Widget\includeis now implemented completely different: A dynamic mixins class is generated and inserted into the class hierarchy of the widget whenincludeis first called. All fields and methods from any included classes are copied into this mixin class.- It's now possible to override a method that is provided by an included class. (The current class has higher precedence than the mixins class)
supercan be used to call the method provided by the included by the class when overriding- Some undocumented functionality regarding method merging was removed
- Only one mixin class will be inserted, and all included classes will copy their fields into that class. The most recently included classes will override anything that has the same time. (Note: there is no hierarchy for multiple includes, so you can't use
superto call through multiple included classes) - Methods from the class hierarchy of the included class are also copied into the mixin class. (Note: methods are copied, and the hierarchy is flattened, meaning methods that depend on super may not work as intended)
- Note: The "dynamic mixin class" approach is also used for models when relation methods are generated
lapis.spec.request.stub_requestno longer creates an anonymous app subclass, instead it will override the dispatch method on an instance of the class before stubbing the requestlapis.spec.request.mock_actionwill no longer push thetestenvironment on every call, but instead will use the current environment. (Note: v1.8.2 added autodetection of busted to ensure specs are always running the test environment, so it's not necessary to manually set the environment)
Additions
- Add support for
on_invalid_methodoption torespond_to fetchrelation can be set totrueto autogenerate aget_method based on the providedpreloadfunction- Added support for optional reloations with
db.preload. Relation names prefixed with?will be ignored if the object being preloaded does not contain a relation with that name.- For example, trying to preload the relation
hellowhen the model does not havehellowill result in an error, but preloading?hellowill do nothing. - Optional
?relations can have nested preloads, if the relation is not found then none of the nested preloads are loaded. This works best when combined with polymorphic relations where the objects may not all share the same relation interface.
- For example, trying to preload the relation
Fixes
- Lazy loaded actions work correctly when merged from sub applications
- Before filters work correctly with lazy loaded actions
- Lazy loaded actions work with Lua method responders
Misc
- Default error page has encoding set to UTF-8
- Simplify implmentation of
preload_relations, deprecate it - Optimize concatenations
db.encode_values - Improve error messages for some functions
db.encode_assigns,db.encode_clause,db.encode_valuesthrows error on empty table instead of generating invalid SQL from empty tablesorted_pairsspec helper- Additional specs (
respond_to, widget including, lazy loaded actions)