======= 2.9.4 (HOTFIX) - fixed: mail attachments - fixed: comparing `origin` header in WebSocket - fixed: unit-testing ======= 2.9.3 (HOTFIX) - added: `String.arg(obj)` for a simple templating `Hello {variable}!` - added: new event `ON('@controllername', function() {})` -> is executed if the controller is evaluated - updated: RESTBuilder default headers are lower-case - updated: `content-disposition` header by adding `utf-8` according to [RFC 5987](https://tools.ietf.org/html/rfc5987#section-3.2.2) - fixed: a missing property `controller.params` in WebSocket controller - fixed: `$ASYNC()` execution in some cases - fixed: `SCRIPT()` code with comments - fixed: a callback reference in `OPERATION()` - fixed: cache after route is removed - fixed: `409` system route - fixed: requests with `range` header and bad values - fixed: `clearSchedule()` - fixed: `Date.extend()` problem with months - fixed: NoSQL counter reading stats ======= 2.9.2 - added: `controller.html(body, [headers])` - added: `F.cluster.master(name, [data])` - for child processes, this method emits an event in master process - added: `F.cluster.on(name, callback(data))` - master event listener - added: `LOGMAIL()` global alias for `F.logmail()` - added: `MAIL()` global alias for `F.mail()` - added: own implementation of `onFinished` - added: `RESTBuilder.cookies(obj)` can set cookies as raw object - added: `RESTBuilder.cook([true/false])` enables persistent cookies - added: `SchemaOptions.params` which returns dynamic params from the controller's action - added: `SchemaOptions.done([arg])` as a callback (contains wrapped SUCCESS()) - added: `SchemaOptions.DB()` which returns `DB(this.error)` instance (for SQL Agent) - added: `OperationOptions.done([arg])` as a callback (contains wrapped SUCCESS()) - added: `OperationOptions.DB()` which returns `DB(this.error)` instance (for SQL Agent) - added: static method `Image.measure(type, buffer)` for measuring width/height of image - added: `EACHOPERATION(function(name) {})` for obtaining all registered operations - added: `controller.params` which returns dynamic params from the action - updated: `F.load()`, now supports `string` for `debug` or `release` mode - updated: `F.cluster.request()` can be executed from master process - updated: `Image.miniature()` change a default filter from `Box` to `Hamming` - updated: `U.request()` supports a new flag `cookies` which enables a parsing cookies from response - fixed: schema validation (problem with Arrays) - fixed: determines `x-forwarded-proto` - fixed: nested schema validation - fixed: themes static routing - fixed: NoSQL reader - fixed: NoSQL counter (sorting while reading stats) - fixed: loading dependencies - fixed: uninstalling middleware - fixed: reading/updating sitemap in controller - removed: max. sort `string` length - removed: `auto` appending `.css` and `.js` extension in view engine - removed: experimental `defer` feature - improved: GZIP compression - improved: code ======= 2.9.1 (HOTFIX) - added: `controller.throw409()`, `req.throw409()` - added: new view aliases: `@{R.something}` for `repository`, `@{M.something}` for `model` and `@{G.something}` for `global` - updated: `ErrorBuilder.push()` supports `.push(name, status_code)` or `.push(name, error, status_code)` - fixed: sitemap language auto-setting - fixed: NoSQL: `builder.paginate()` a problem with zero limit (default limit will be `maxlimit`) - fixed: NoSQL number filtering - fixed: localization of ErrorBuilder in controllers ======= 2.9.0 - added: `WebSocketClient` - added: `$ASYNC(schema, callback, [index], [controlller])` alias to `SchemaBuilderEntity.$async()` - added: `ArrayBuffer.prototype.toBuffer()` - added: `AUTH(fn)` is an alias to `F.onAuthorize = fn` - added: `controller.success()` alias to `controller.json(SUCCESS(value))` - added: `CORS()` alias to `F.cors()` - added: `DatabaseBuilder.paginate(page, limit)` - added: `F.config['allow-compile']` can disable the whole compilation of static files - added: `F.config['default-dependency-timeout']` it's a timeout for module dependencies - added: `F.path.rmdir(directory/directories, callback)` - added: `F.path.unlink(file/files, callback)` - added: `LOCALIZE()` a new global alias to `F.localize()` - added: `MAP()` a new global alias to `F.map()` - added: `MERGE()` a new global alias to `F.merge()` - added: `MIDDLEWARE()` a new global alias to `F.middleware()` - added: `NOSQL('users').backups([filter(doc)], callback(err, response))` returns all backups - added: `SchemaOptions.invalid(name, [value], [path], [index])` alias to `$.errors.push() + callback()` - added: `SchemaOptions.success()` alias to `callback(SUCCESS(value))` - added: `controller.sitemapid` contains a sitemap identificator - added: `controller.sitemap_add(parent, name, url)` appends a new item into the sitemap per request - added: `@{sitemap_add(parent, name, url)}` appends a new item into the sitemap per request - added: `SchemaEntity.required('fieldname', boolean/function(model))` which can disable/enable validation for this field - updated: `sitemap` routing can contain an additional path, e.g. `#sitemapid/path/` - updated: `F.localize()` supports sitemap routing - updated: `F.merge()` supports sitemap routing - updated: `F.map()` supports sitemap routing - updated: `F.http(mode, [options], [middleware(listen)])` added a new argument `middleware` - updated: `debug.js` now reads directories according to the config (author: @luoage) - updated: config parser supports `config` sub-type - updated: `controller.$exec()` --> `callback` is by default `controller.callback()` - updated: `F.localize()` has enabled `compression` by default - updated: HTTP server is listening after the framework is completely loaded - updated: (IMPORTANT) HTTP cache in dynamic content and static files - updated: `F.prototypes()` by adding `OperationOptions` - updated: ErrorHandling in schemas (supports inline validation and advanced conditions) - updated: `F.noCache()` is obsolete - renamed: `allow-handle-static-files` to `allow-static-files` - fixed: (IMPORTANT) `DatabaseBuilder.in()` - fixed: (IMPORTANT) `U.ls2()` - fixed: (IMPORTANT) `WebSocket` implementation (author: @jozefgula) - fixed: `ArrayBuffer` in webosocket - fixed: `F.path.mkdir()` on Windows (author: @molda) - fixed: `F.restore()` on Windows (author: @molda) - fixed: `F.rmdir` removes all files and directories - fixed: `JSON` type in Total.js schemas - fixed: `MODEL()`, `MODULE()`, `INCLUDE()` now are direct aliases - fixed: a check for maximum length of request data - fixed: Date formatting with `a` value - fixed: empty localization in view engine e.g. `@()` - fixed: external static routing in view engine on Windows - fixed: NoSQL filtering with `or` - fixed: NoSQL multiple updates - fixed: NoSQL sorting of boolean values in larger dataset - fixed: responding on `range` header - fixed: unit testing (author: @ckpiggy) - fixed: `schema.setPrefix()` in nested schemas - fixed: sitemap localization - fixed: CORS custom headers - fixed: NoSQL date filtering - improved: performance and security ======= 2.8.0 - added: `NOSQL().restore()` restores a database (its package) - added: Mail options support a new property `xoauth2` (it needs to contain a `BASE64` value) for sending emails via OAuth 2.0 tokens (more in docs) - added: `F.path.mkdir(path)` creates all directories according to the path - added: `MailMessage.send2([callback])` sends a message according to the framework configuration - added: a new filter for NoSQL embedded `DatabaseBuilder.contains(name)` - added: a new filter for NoSQL embedded `DatabaseBuilder.empty(name)` - added: (IMPORTANT) NoSQL counter supports daily stats (NoSQL counter files will be upgraded automatically and backwards incompatible) - added: (IMPORTANT) NoSQL database and counter can read data from URL - added: NoSQL counter `db.counter.daily_sum([id], callback)` for reading stats - added: NoSQL counter `db.counter.daily_max([id], callback)` for reading stats - added: NoSQL counter `db.counter.daily_min([id], callback)` for reading stats - added: NoSQL counter `db.counter.monthly_sum([id], callback)` for reading stats - added: NoSQL counter `db.counter.monthly_max([id], callback)` for reading stats - added: NoSQL counter `db.counter.monthly_min([id], callback)` for reading stats - added: NoSQL counter `db.counter.yearly_sum([id], callback)` for reading stats - added: NoSQL counter `db.counter.yearly_max([id], callback)` for reading stats - added: NoSQL counter `db.counter.yearly_min([id], callback)` for reading stats - added: NoSQL counter `db.counter.stats_sum(top, [year], [month], [day], callback)` for reading stats - added: NoSQL counter `db.counter.stats_max(top, [year], [month], [day], callback)` for reading stats - added: NoSQL counter `db.counter.stats_min(top, [year], [month], [day], callback)` for reading stats - added: NoSQL counter `db.counter.minimum([id], callback)` for reading stats - added: NoSQL counter `db.counter.maximum([id], callback)` for reading stats - added: NoSQL counter `db.counter.min(id, value)` for writing stats - added: NoSQL counter `db.counter.max(id, value)` for writing stats - added: NoSQL counter `db.counter.sum(id, value)` for writing stats (alias for `db.counter.hit()`) - added: NoSQL counter: a new event `stats` when the stats are changed - added: NoSQL logging in `DatabaseBuilder.log(msg, [user])` - added: NoSQL backuping documents while they are updating/removing in `DatabaseBuilder.backup([user])` - added: `CLONE(obj)` alias for `U.clone()` - added: `GROUP(flags, fn)` alias for `F.group()` - added: `F.cache.set2()` it creates a persistent cache (persistent items are stored in a file) - added: new View Engine command `@{'%config'}` which reads a value from config directly - added: `F.config['allow-filter-errors']` for filtering network unhandled errors - added: `REDIRECT()` alias for `F.redirect()` - updated: (IMPORTANT) packages compress/decompress function supports streaming data - updated: (IMPORTANT) `NOSQL().backup()` !!! was changed !!!! - updated: `controller.view(name/url, [model], [headers], [partial])` can render a view from URL address - updated: `F.backup()` argument `path` can contain `String Array` file list - updated: `controller.viewCompile(body, model, [headers], [partial], [cacheKey])` add a cache key - updated: `image.command(arg, value, [priority], [escape])` a `priority` argument can be `escape` when it contains `boolean` value - updated: `U.getExtension()` returns lower-case extensions - updated: `total.js/debug` watchs `/workflows` file - updated: file `/workflows` supports custom `options`, more in docs - updated: `Array.random()` algorithm (+70% faster than older) - updated: `RESTBuilder.file(name, filetarget, [filename])` can contain `filename` instead of buffer - updated: `U.streamer(beg, [end], onItem(item, index), [skip], [stream])` added a new argument `stream` for flushing buffer - updated: `ErrorBuilder.addTransform(name, callback(isResponse))` by adding new argument `isresponse` - updated: `sorting` (framework + NoSQL embedded), now supports `internationalization` - updated: `total.js/debugger` by adding a new option `options.watch = ['directory']` - updated: `U.streamer()` supports "cancelation", just return `false` - updated: CSS auto-prefixer, added: `repeating-linear-gradient`, `radial-gradient`, `repeating-radial-gradient` and removed `-o` prefix - fixed: (IMPORTANT) long messages in WebSocket - fixed: (IMPORTANT) `controller` param in schemas - fixed: moved executing of `MailMessage.callback()` to better place - fixed: mail auth when `options.user` and `options.password` are blank - fixed: JS/CSS/HTML blocks - fixed: `F.prototypes()` - fixed: `F.decrypt()` a problem with parsing JSON and date formats - fided: `debug.js` sometimes was created a problem with output informations - improved: Date formatting (+50%) - improved: NoSQL performance (around 60% in some cases) ======= 2.7.0 - added: __IMPORTANT__ new unit-testing mechanism - added: __IMPORTANT__ `F.prototypes(function(proto) {})` for extending all internal prototypes - added: `HttpFile` is set in `global` for extending of prototype - added: `file.move()` a new alias for `file.rename()` - added: `SchemaBuilderEntity.$controller(new_controller)` - added: `EMPTYCONTROLLER` is a global variable - added: new alias `NOSQL.set()` and `NOSQL.get()` for `NOSQL.meta()` - added: `RESTBuilder.file(name, filename, [buffer])` supports uploading files - added: `RESTBuilder.mobile()` adds `iPhone` phrase into the `User-Agent` header - added: `RESTBuilder.robot()` adds `Bot` phrase into the `User-Agent` header - added: a small protection for multipart data - added: a new global aliases `ROUTE()` --> `F.route()`, `FILE()` --> `F.file()` and `WEBSOCKET()` --> `F.websocket()` - updated: __IMPORTANT__ components (framework can render css/js from specific group) - updated: `F.cluster` each operation checks whether cluster is activated - updated: default IP to `0.0.0.0` - updated: `Date.prototype.format()` with `ddd` renders name of day with 2 capital letters - fixed: new schemas with defined callback `function($)` - fixed: loading of `config-test` file (added rewriting of existing values) - fixed: Total.js version in `debug.js` - fixed: cluster initialization - improved: `cors` in `F.restful()` and `F.restful2()` - improved: `auto-vendor-prefixes` - improved: parsing files from multipart data ======= 2.6.2 (HOTFIX) - fixed: a critical bug with `debug.js` - fixed: `try/catch` block from parsing of WebSocket message ======= 2.6.1 (HOTFIX) - fixed: timeout in `RESTBuilder` and `U.request()` - fixed: `F.merge()` a problem with `.js` or `.css` extension in some directory ======= 2.6.0 - added: `F.config['default-errorbuilder-status']` a default HTTP status for all error builders default `200` - added: `F.config['default-listenpath']` starts a UNIX socket server listening for connections on the given path - added: `F.listenpath` contains `default-listenpath` location - added: `F.custom(mode, http, request_prototype, response_prototype, options)` a new mode for overwriting default HTTP server - added: `schema.inherit([group], name)` can inherit all values from another schema - added: NoSQL synchronization for cluster (more in docs) - added: cache synchronization for cluster (more in docs) - added: `F.cluster` (more in docs) - added: Total.js `debug` script `require('total.js/debug')` instead of `debug.js` file - added: a support for `async` attribute when `