gina 0.3.11-alpha.1 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/CONVENTIONS.md +32 -0
- package/README.md +15 -2
- package/ROADMAP.md +6 -5
- package/bin/cli +1 -0
- package/framework/v0.3.11/VERSION +1 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/js/gina.js +26 -5
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/js/gina.min.js +5 -5
- package/framework/v0.3.11/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
- package/framework/v0.3.11/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js +1 -1
- package/framework/v0.3.11/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.br +0 -0
- package/framework/v0.3.11/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.gz +0 -0
- package/framework/v0.3.11/core/connectors/mongodb/index.js +463 -0
- package/framework/v0.3.11/core/connectors/mongodb/lib/connector.js +158 -0
- package/framework/v0.3.11/core/connectors/mongodb/lib/pipeline-loader.js +186 -0
- package/framework/v0.3.11/core/connectors/mongodb/lib/session-store.js +392 -0
- package/framework/v0.3.11/core/connectors/scylladb/index.js +367 -0
- package/framework/v0.3.11/core/connectors/scylladb/lib/connector.js +145 -0
- package/framework/v0.3.11/core/connectors/scylladb/lib/session-store.js +338 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/controller/controller.js +146 -10
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/gna.js +91 -4
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/server.isaac.js +106 -16
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/server.js +79 -0
- package/framework/v0.3.11/core/template/boilerplate/bundle/locales/en.json +10 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/conf/settings.json +20 -0
- package/framework/v0.3.11/helpers/text.js +45 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/connector/add.js +1 -1
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/connector/help.txt +2 -2
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/connector/migrate.js +1 -1
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/connector/remove.js +2 -2
- package/framework/v0.3.11/lib/cmd/i18n/add.js +372 -0
- package/framework/v0.3.11/lib/cmd/i18n/arguments.json +9 -0
- package/framework/v0.3.11/lib/cmd/i18n/export.js +649 -0
- package/framework/v0.3.11/lib/cmd/i18n/help.js +46 -0
- package/framework/v0.3.11/lib/cmd/i18n/help.txt +94 -0
- package/framework/v0.3.11/lib/cmd/i18n/import.js +1023 -0
- package/framework/v0.3.11/lib/cmd/i18n/scan.js +622 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/connector-registry/src/main.js +14 -11
- package/framework/v0.3.11/lib/i18n/package.json +19 -0
- package/framework/v0.3.11/lib/i18n/src/main.js +1072 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/index.js +13 -0
- package/framework/v0.3.11/lib/metrics/package.json +19 -0
- package/framework/v0.3.11/lib/metrics/src/main.js +421 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/nunjucks-filters/src/main.js +73 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/routing/src/main.js +7 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/swig-filters/src/main.js +73 -0
- package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/swig-resolver/src/main.js +2 -2
- package/framework/v0.3.11/package.json +9 -0
- package/gna.js +4 -4
- package/llms.txt +16 -80
- package/package.json +2 -2
- package/schema/app.json +33 -0
- package/schema/connectors.json +40 -2
- package/schema/locales.json +38 -0
- package/script/check_def_framework_consistency.js +239 -0
- package/script/post_install.js +28 -1
- package/script/version_compare.js +124 -0
- package/framework/v0.3.11-alpha.1/VERSION +0 -1
- package/framework/v0.3.11-alpha.1/core/asset/plugin/dist/vendor/gina/js/gina.min.js.br +0 -0
- package/framework/v0.3.11-alpha.1/core/asset/plugin/dist/vendor/gina/js/gina.min.js.gz +0 -0
- package/framework/v0.3.11-alpha.1/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.br +0 -0
- package/framework/v0.3.11-alpha.1/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.gz +0 -0
- package/framework/v0.3.11-alpha.1/helpers/text.js +0 -71
- package/framework/v0.3.11-alpha.1/package.json +0 -8
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/AUTHORS +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/LICENSE +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/html/nolayout.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/html/static.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/img/android-chrome-192x192.png +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/img/android-chrome-512x512.png +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/img/apple-touch-icon.png +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/img/favicon-16x16.png +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/img/favicon-32x32.png +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/img/favicon.ico +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.css +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/beemaster/beemaster.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/beemaster/index.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/css/gina.min.css +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.br +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/css/gina.min.css.gz +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/html/statusbar.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/html/statusbar.html.br +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/html/statusbar.html.gz +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/inspector/have_heart_one-webfont.woff2 +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/inspector/index.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/inspector/inspector.css +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/inspector/inspector.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/inspector/logo.svg +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/config.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/ai/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/ai/lib/connector.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/lib/connector.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/lib/connector.v2.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/lib/connector.v3.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/lib/connector.v4.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/lib/n1ql.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/lib/session-store.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/lib/session-store.v2.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/lib/session-store.v3.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/couchbase/lib/session-store.v4.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/mysql/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/mysql/lib/connector.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/postgresql/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/postgresql/lib/connector.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/redis/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/redis/lib/session-store.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/sql-parser.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/sqlite/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/sqlite/lib/connector.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/connectors/sqlite/lib/session-store.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/content.encoding +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/controller/controller.framework.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/controller/controller.render-json.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/controller/controller.render-nunjucks.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/controller/controller.render-stream.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/controller/controller.render-swig.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/controller/controller.render-v1.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/controller/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/busboy-1.6.0/LICENSE +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/busboy-1.6.0/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/busboy-1.6.0/lib/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/busboy-1.6.0/lib/types/multipart.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/busboy-1.6.0/lib/types/urlencoded.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/busboy-1.6.0/lib/utils.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/busboy-1.6.0/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/streamsearch-1.1.0/LICENSE +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/streamsearch-1.1.0/lib/sbmh.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/deps/streamsearch-1.1.0/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/dev/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/dev/lib/class.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/dev/lib/factory.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/dev/lib/tools.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/locales/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/locales/currency.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/locales/dist/language/en.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/locales/dist/language/fr.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/locales/dist/region/en.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/locales/dist/region/fr.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/locales/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/mime.types +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/model/entity.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/model/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/model/template/entityFactory.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/model/template/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/csrf/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/csrf/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/csrf/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/file/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/file/build.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/file/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/intl/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/intl/build.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/intl/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/intl/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/session/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/session/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/session/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/storage/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/storage/build.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/storage/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/storage/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/validator/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/validator/build.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/validator/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/validator/src/form-validator.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/plugins/lib/validator/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/router.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/server.express.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/status.codes +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/_gitignore +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/config/app.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/config/connectors.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/config/routing.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/config/settings.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/config/settings.server.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/config/templates.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/config/watchers.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/controllers/controller.content.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/controllers/controller.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/controllers/setup.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_namespace/controllers/controller.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_public/css/default.css +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_public/css/home.css +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_public/css/vendor/readme.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_public/favicon.ico +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_public/js/vendor/readme.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_public/readme.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_templates/handlers/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_templates/html/content/homepage.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_templates/html/includes/error-msg-noscript.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_templates/html/includes/error-msg-outdated-browser.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/boilerplate/bundle_templates/html/layouts/main.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/command/gina.bat.tpl +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/command/gina.tpl +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/conf/env.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/conf/manifest.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/conf/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/conf/statics.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/conf/templates.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/error/client/json/401.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/error/client/json/403.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/error/client/json/404.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/error/server/html/50x.html +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/error/server/json/500.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/error/server/json/503.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/template/extensions/logger/config.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/console.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/context.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/data/LICENSE +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/data/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/data/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/data/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/dateFormat.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/json/LICENSE +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/json/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/json/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/json/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/path.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/plugins/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/plugins/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/plugins/src/api-error.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/plugins/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/prototypes.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/helpers/task.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/archiver/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/archiver/build.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/archiver/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/archiver/src/dep/jszip.min.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/archiver/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/async/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/async/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cache/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cache/build.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cache/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cache/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/aliases.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/add.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/arguments.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/build.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/copy.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/cp.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/list.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/mcp-start.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/mcp.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/oas.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/openapi.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/remove.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/rename.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/restart.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/rm.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/start.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/status.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/bundle/stop.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/cache/stats.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/connector/arguments.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/connector/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/connector/list.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/connector/rm.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/add.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/get.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/link-dev.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/list.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/remove.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/rm.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/set.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/unset.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/env/use.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/arguments.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/build.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/dot.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/get.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/init.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/link-node-modules.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/link.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/msg.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/open.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/restart.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/set.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/start.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/status.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/stop.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/tail.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/update.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/framework/version.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/gina-dev.1.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/gina-framework.1.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/gina.1.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/helper.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/inspector/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/inspector/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/inspector/open.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/minion/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/minion/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/msg.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/port/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/port/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/port/inc/scan.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/port/list.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/port/reset.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/port/set.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/add.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/arguments.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/build.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/import.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/list.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/move.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/remove.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/rename.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/restart.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/rm.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/start.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/status.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/project/stop.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/protocol/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/protocol/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/protocol/list.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/protocol/set.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/scope/add.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/scope/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/scope/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/scope/link-local.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/scope/link-production.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/scope/list.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/scope/remove.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/scope/rm.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/scope/use.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/service/help.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/service/help.txt +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/service/list.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cmd/view/add.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/collection/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/collection/build.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/collection/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/collection/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/config.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/connector-registry/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cron/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cron/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/cron/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/domain/LICENSE +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/domain/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/domain/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/domain/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/generator/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/inherits/LICENSE +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/inherits/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/inherits/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/inherits/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/inspector-redact/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/inspector-redact/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/src/containers/default/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/src/containers/file/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/src/containers/file/lib/logrotator/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/src/containers/file/lib/logrotator/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/src/containers/mq/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/src/containers/mq/listener.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/src/containers/mq/speaker.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/src/helper.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/logger/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/math/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/mcp-dispatch/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/mcp-dispatch/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/mcp-http/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/mcp-http/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/mcp-server/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/mcp-server/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/merge/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/merge/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/merge/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/model.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/nunjucks-filters/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/nunjucks-filters/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/nunjucks-resolver/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/nunjucks-resolver/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/proc.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/routing/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/routing/build.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/routing/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/routing/src/radix.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/routing-introspect/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/routing-introspect/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/session-store.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/shell.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/state.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/swig-filters/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/swig-filters/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/swig-resolver/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/url/README.md +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/url/index.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/url/routing.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/uuid/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/uuid/src/main.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/validator.js +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/watcher/package.json +0 -0
- /package/framework/{v0.3.11-alpha.1 → v0.3.11}/lib/watcher/src/main.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,31 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
|
|
|
6
6
|
and is generated by [Changie](https://github.com/miniscruff/changie).
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
## 0.3.11 - 2026-05-10
|
|
10
|
+
### Added
|
|
11
|
+
* Added pre-publish gate `checkDefFrameworkConsistency` (`script/check_def_framework_consistency.js` + wired into `script/prepare_version.js`). Asserts `~/.gina/main.json`'s `def_framework` field points to a framework directory that exists on disk; aborts with an actionable diagnostic listing the drifted scalar, the missing framework dir, the actual present framework dirs, and a step-by-step recovery recipe. Catches the silent state-store drift that surfaced as a deep `MODULE_NOT_FOUND` from inside `getSelectedVersion` during the v0.3.10 stable publish (2026-05-06), where main.json's def_framework had drifted to `0.3.9` while the framework dir on disk was at `v0.3.10-alpha.2`. Skips silently when main.json itself is absent (first install / fresh state). The drift root cause (a writer other than `bumpVersion` updating the scalar inconsistently — distinct from the `34115799` gina.db drift fix) is queued as a separate follow-up; this gate is the safety net so future drift surfaces with an actionable error before npm publish proceeds. 18 unit tests with an injected fs driver cover the happy path, drift detection, fresh state, malformed JSON, missing/non-string field, and the `presentDirs` diagnostic helper.
|
|
12
|
+
* Added `gina.t(key, params, culture, options)` global translation helper backed by per-bundle JSON catalogs at `bundle/locales/<culture>.json` (e.g. `en.json`, `en_US.json`, `fr.json`). Catalogs are eager-loaded at bundle start; lookup walks a fallback chain (specific culture → base language → `settings.region.culture` → `GINA_CULTURE` → `'en'`), applies CLDR plural rules via Node's built-in `Intl.PluralRules` when `params.count` is supplied and the resolved value is a CLDR plural-form object, then runs `{name}`-style parameter interpolation (with `{{name}}` escape for a literal). Controller actions get an auto-binding `self.t(key, params)` helper that reads the request culture from `req.culture` (formalised by slice 3) and the bundle name from `local.options.conf.bundle`. The legacy `__()` placeholder (helpers/text.js) is rewired as a one-arg alias of `t()` — existing callers keep working with no behaviour change when no catalog is loaded. Settings template gains an `i18n.*` block (`cookieName`, `devMissingKey`, `fallbackChain`, `cultures`) for runtime knobs. Bundle scaffold ships a minimal `bundle/locales/en.json` stub. New JSON Schema at `https://gina.io/schema/locales.json` (Draft-07, recursive value-or-pluralForm shape). Slice 1 of 5 from #I18N1; slices 2-5 add the swig/nunjucks `t` filter, `req.culture` formalisation with URL-prefix routing + cookie negotiation, and the `gina i18n:scan/add/export/import` CLI group.
|
|
13
|
+
* Added swig and nunjucks `t` template filter (#I18N1 slice 2). Translate strings directly in templates via `{{ "common.welcome" | t }}`, `{{ "common.greeting" | t({ name: user.name }) }}`, or `{{ "common.items" | t({ count: 5 }) }}` (CLDR plural). Both engines share the same surface so templates port between swig and nunjucks unchanged. The filter is auto-registered on every request (no setup.js wiring needed) and consumes the `lib/i18n` primitives — no plural / interpolation / fallback logic is duplicated locally. Auto-binds the request culture via `req.culture` (the slice 3 hook) with a fallback to `process.env.GINA_CULTURE` (the bundle's process default). Bundle name is taken from the per-request `options.conf.bundle` slot. Templates work today against the process-default culture; slice 3 upgrades to per-request URL-prefix / cookie / Accept-Language negotiation. Tests at `test/lib/i18n-filters.test.js` lock in the requires, the (key, params) signatures, the culture and bundleName resolution chains, the i18n.t pass-through shape, the singleton context access pattern, surface parity between swig and nunjucks, and negative invariants (no Intl.PluralRules / interpolation regex / _i18nCatalogs duplication inside the filter bodies). Full local suite green: 4197 tests, zero regressions.
|
|
14
|
+
* Added locale negotiation primitives + request-pipeline hook (#I18N1 slice 3). `req.culture` is now a first-class per-request field, set in the routing pipeline before middlewares drain. Negotiation order (highest priority first): URL prefix (`routing.json > culturePrefix: true` flag — captures `req.routing.param.culture` from a route URL like `/:culture/dashboard`) → cookie (defaults to `gina_culture`) → `Accept-Language` parsed and best-matched against the bundle's loaded catalogs with q-value ordering respected → `settings.region.culture` → `process.env.GINA_CULTURE` → `'en'`. New helpers exported on `lib.i18n`: `parseAcceptLanguage(header)`, `matchAvailable(requested, available)`, `readCookie(header, name)`, `negotiateCulture(req, opts)`. Controller `self.t()` and the swig/nunjucks `t` filter pick up `req.culture` automatically (the slice-1 hook is now wired). The controller's existing region-data lookup (`controller.js`) bridges to `req.culture` so the URL-prefix / cookie sources flow through to the legacy `page.view.lang` template scope. Per-route flag propagation mirrors the `#CSRF2 csrfExempt` pattern: `lib/routing/src/main.js` extracts `routeObject.culturePrefix` into `params.culturePrefix`; `core/server.js` hoists into the request-lifecycle params block as a sibling of `csrfExempt`. The negotiator is wrapped in try/catch so an i18n failure never blocks routing. Tests at `test/lib/i18n-negotiation.test.js` — 42 tests covering parseAcceptLanguage (q-value ordering / wildcards / whitespace / clamping), matchAvailable (exact / base-language / multi-priority), readCookie (extract / decode / fallback), negotiateCulture (full chain priority matrix), and source-inspection guards on the lib/routing + core/server wiring. Full local suite green: 4239 tests, zero regressions. Known limitation in slice 3: cookie name is hardcoded to `gina_culture` and bundle defaultCulture lookup is deferred — slice 4 or a follow-up wires bundle-settings access at the request-pipeline boundary.
|
|
15
|
+
* Added `gina i18n:scan` CLI command (#I18N1 slice 4 part 1). Walks every bundle in a project and reports translation coverage per culture against the keys used in source — `t("key")` / `self.t("key")` / `__("key")` / `{{ "key" | t }}` patterns are detected across `controllers/`, `middleware/`, `models/`, `lib/`, `src/`, `views/`, `public/`, plus top-level `.js` (excluding `node_modules`, `dist`, `.git`, `locales/`, and dotfiles). For each culture the command prints translated / missing-key counts and a percent score, then lists the missing keys themselves (capped at 50 in text output; no cap in JSON output). Three positional shapes: `gina i18n:scan` (every registered project), `gina i18n:scan @<project>` (every bundle in one project), `gina i18n:scan <bundle> @<project>` (one bundle). `--format=json` emits a CI-friendly machine-readable shape. Adds `'i18n:'` to `bin/cli`'s `allowedOffline` whitelist so the command runs without a framework socket (consistent with `connector:`, `bundle:`, `env:`, and the rest). Coverage walks `lib.i18n.resolveKey` so dotted-path keys (`common.welcome`) resolve through nested catalogs correctly. Tests at `test/lib/i18n-scan.test.js` — 57 source-inspection assertions covering module shape + CmdHelper wiring, argv parsing + dispatch, file walker constants, key-extraction regex behaviour (positive + negative), pure-logic coverage replica, JSON / text output structure, help.txt + arguments.json, and bin/cli wiring. The companion `gina i18n:add` command (slice 4 part 2) and `gina i18n:export` / `gina i18n:import` (slice 5) follow.
|
|
16
|
+
* Added `gina i18n:add <culture>` CLI command (#I18N1 slice 4 part 2). Seeds a new culture catalog at `<bundle>/locales/<culture>.json` by copying the structure of an existing source culture and prefixing every string value with `[TODO] ` so translators can grep / search-replace through the file. Three positional shapes: `gina i18n:add <culture> @<project>` (every bundle in the project), `gina i18n:add <culture> <bundle> @<project>` (single bundle), `gina i18n:add <culture> <bundle> @<project> --from=<src>` (explicit source culture). Source-culture resolution order per bundle: `--from=<culture>` → `<bundle>/config/settings.json > region.culture` → `process.env.GINA_CULTURE` → `'en'`. Refuses to overwrite an existing target catalog unless `--force` is passed; `--dry-run` prints what would be written and exits without touching the disk. Creates `<bundle>/locales/` recursively when missing. Recursion preserves nested catalogs and CLDR plural-form objects (every `zero` / `one` / `two` / `few` / `many` / `other` form gets the `[TODO] ` prefix); arrays / numbers / booleans / null pass through unchanged. Refuses when source culture equals target culture (caller would seed onto itself). Writes via `lib.generator.createFileFromDataSync` for parity with the rest of the framework's file emitters; serialises with 4-space indent + trailing newline. For project-wide invocations, iterates the `manifest.json` bundle list in sorted order and reports per-bundle ok / skipped counts at the end. Tests at `test/lib/i18n-add.test.js` — 51 source-inspection + pure-logic + sandbox-write assertions covering module shape, argv parsing, source-culture resolution priority chain, `seedCatalog` transformation (string / nested / plural / non-string leaves / array passthrough / key-order preservation), guarded write path (source-equals-target / missing source / malformed source / target exists / dry-run / mkdir), multi-bundle iteration, and a sandbox round-trip that asserts the on-disk output JSON.parses back with the `[TODO] ` prefix in place. Full local suite green: 4347 / 4347. Slice 5 (`gina i18n:export` / `gina i18n:import` for PO / CSV / JSON translator round-trip) follows.
|
|
17
|
+
* Added `gina i18n:export <culture>` CLI command (#I18N1 slice 5 part 1). Exports a culture's catalog from a project's bundle(s) into JSON / PO / CSV format on stdout or a file. Three positional shapes mirror `i18n:add`: `gina i18n:export <culture> @<project>` (every bundle, single combined output), `gina i18n:export <culture> <bundle> @<project>` (single bundle), with `--format=<json|po|csv>` and `--output=<path>` flags. When `--format` is omitted, the format is auto-detected from the `--output` file extension (`.po`, `.csv`, `.json`); when both are omitted, defaults to JSON on stdout. Single-bundle JSON matches the on-disk catalog shape verbatim — drop the file straight back into `<bundle>/locales/` and round-trip via `gina i18n:import`. Multi-bundle JSON nests under bundle keys at the top level. PO output is translator-friendly: standard header block (`Project-Id-Version`, `Content-Type`, `Language`, `Plural-Forms`) with a per-culture plural formula (English / Romance / Slavic / Asian / Arabic table; Romance/Germanic 2-form fallback for unknown cultures), `msgctxt` for multi-bundle disambiguation, and native `msgid_plural` + `msgstr[N]` syntax for plural forms. Each plural entry carries a `#. cldr-keys: <list>` extracted comment recording the present CLDR plural keys in canonical order (`zero` / `one` / `two` / `few` / `many` / `other`) so `i18n:import` reconstructs the catalog shape unambiguously across cultures with differing plural categories. PO escape sequences cover backslash / double-quote / newline / tab / CR. CSV output follows RFC 4180: header row `key,value` (single-bundle) or `bundle,key,value` (multi-bundle); cells containing `,` / `"` / `\n` / `\r` / leading-or-trailing whitespace are wrapped and embedded quotes are doubled; plural forms flatten to dotted-suffix rows (`items.one`, `items.other`). Bundles without a catalog for the requested culture are skipped with a warning in project-wide mode; single-bundle scope errors hard. Output to disk goes through `lib.generator.createFileFromDataSync` for parity with `i18n:add`; the parent directory must exist. Tests at `test/lib/i18n-export.test.js` — 75 source-inspection + pure-logic + sandbox-write assertions covering module shape, argv parsing, `detectFormatFromPath`, `flattenCatalog` (nested / plural-grouped / non-string-leaf-drop / bundle stamping), PO writer (escape sequences, header block, per-culture plural formula with base-language fallback, msgid_plural / msgstr[N] / cldr-keys CLDR-order round-trip), CSV writer (RFC 4180 quoting matrix, plural flattening, bundle column), JSON writer (4-space indent, identity round-trip, multi-bundle wrapper), help.txt + arguments.json + dispatcher source pins, and a sandbox export smoke that round-trips JSON / PO / CSV through minimal readers. Slice 5 part 2 (`gina i18n:import`) follows.
|
|
18
|
+
* Added `gina i18n:import <culture>` CLI command (#I18N1 slice 5 part 2). Imports a translator-edited PO / CSV / JSON file back into a culture's catalog at `<bundle>/locales/<culture>.json` — the complement of `gina i18n:export`. Together they close the translator round-trip and complete the #I18N1 contract (slices 1–5 all shipped on the 0.3.11-alpha track). Three positional shapes mirror `i18n:export`: `gina i18n:import <culture> @<project> --file=<path>` (project-wide; multi-bundle inputs route per bundle), `gina i18n:import <culture> <bundle> @<project> --file=<path>` (single bundle), with required `--file=<path>` flag and optional `--format=<json|po|csv>`, `--merge=<union|replace>`, `--dry-run`, `--force`. Format is auto-detected from the `--file` extension when `--format` is omitted. Two merge strategies via `--merge`: `union` (default) deep-merges — imported keys win for shared paths; existing keys absent from the import are preserved (a partial PO/CSV touches only the keys it lists, including per-CLDR-key behaviour for plural-form objects). `replace` overwrites the catalog entirely; existing keys absent from the import are dropped — surfaced via a "N key(s) dropped" log so translators see what they wiped. PO parser is a state-machine line-walker: handles header entry (empty `msgid ""` discarded), `msgctxt` for bundle disambiguation, multiline strings via PO continuation (`msgid ""` + `"line1"` + `"line2"`), backslash escapes (`\n`, `\t`, `\r`, `\"`, `\\`), and the slice 5 part 1 `#. cldr-keys: <list>` extracted comment that records which CLDR plural keys the export emitted — the importer maps `msgstr[N]` back to those exact CLDR keys, so plural-form catalogs round-trip across cultures with differing plural categories (English `{one,other}`, Russian `{one,few,many,other}`, Arabic all six). Falls back to canonical CLDR order when the marker is absent (best-effort for PO files authored outside this tooling). CSV parser is an RFC 4180 state-machine: handles quoted cells with embedded commas / doubled quotes / embedded newlines / CRLF line endings; auto-detects single-bundle (`key,value`) vs multi-bundle (`bundle,key,value`) shape from the header row. Plural-form CSV rows reach the catalog via dotted-suffix nesting (`items.one` + `items.other` → `items: { one, other }`). JSON inputs accept both shapes: a flat catalog (matches the on-disk shape verbatim) or a multi-bundle wrapper (`{ "<bundle>": { ...catalog }, ... }`); the CLI's `<bundle>` positional resolves the routing. Single-bundle scope errors hard when the target catalog does not exist (recommends running `gina i18n:add` first); pass `--force` to bypass and create. Project-wide scope warns when the input contains a bundle not registered in `manifest.json` and skips it; reports per-bundle ok/skipped counts at the end. Write-back uses the `connector:add` comment-preserving three-function pattern (`readExistingFile` / `mergeUnion` / `writeFile`) per architecture doc § 9: leading comment headers (everything before the first `{`) are preserved verbatim, the JSON body is rewritten with 4-space indent + trailing newline through `lib.generator.createFileFromDataSync`. `--dry-run` prints the would-write line per bundle and skips the disk write; the dropped-key count for `--merge=replace` shows in the dry-run preview too. Tests at `test/lib/i18n-import.test.js` — 84 source-inspection + pure-logic + sandbox-write assertions covering module shape, argv parsing + dispatch, format auto-detect, PO parser (escape sequences, msgctxt-as-bundle, plural reconstruction with `#. cldr-keys` round-trip, fallback to canonical CLDR order, 3-form Russian-style plurals, multiline continuation, header-entry skip), CSV parser (single + multi-bundle headers, embedded commas / doubled quotes / embedded newlines / CRLF, header-shape mismatch returns empty), `buildCatalogFromEntries` (flat / nested / dotted-suffix plural reassembly / atomic plural-form preservation), `looksLikeWrapper` heuristic (clear positives + clear negatives + the documented CLI-resolved deep-flat false positive), `mergeUnion` (imported wins, existing preserved, per-CLDR-key plural merging, type-divergent overrides, empty edge cases), comment-preserving writer + help.txt + arguments.json + dispatcher source pins, and a sandbox import smoke that round-trips union / replace / comment-header preservation / CSV → catalog through minimal readers. Full local suite green: 4506 / 4506 (4347 baseline + 75 export + 84 import). Closes the #I18N1 translator round-trip contract; #I18N2 (ICU MessageFormat opt-in via `t.icu(key, params, culture)` powered by `intl-messageformat`) follows.
|
|
19
|
+
* Added ICU MessageFormat opt-in via `t.icu()` — server-side primitive + framework wiring (#I18N2 part 1). Adds an opt-in `tIcu(key, params, culture, options)` variant powered by `intl-messageformat` to the `lib/i18n` module, exposed as `gna.t.icu(...)` (sibling of `gna.t`) and `self.t.icu(...)` (controller helper auto-binding `req.culture` from slice 3, plus `bundleName` / `devMissingKey` / `fallbackChain` from `local.options.conf.content.settings.i18n`). Existing `gna.t()` / `self.t()` shape stays unchanged — v1 catalogs (plain strings with `{name}` placeholders, plural-form objects keyed by CLDR categories, nested categories) continue to work as today. Catalog values that are NOT strings (plural-form objects, nested objects) automatically fall through to `t()` so the same bundle catalog can mix v1 and ICU shapes freely. Catalog values that ARE strings get interpreted by `intl-messageformat` — covers ICU `{count, plural, one {# item} other {# items}}`, `{gender, select, female {…} male {…} other {…}}`, nested combinators, explicit-number plural matchers (`=0`), and the cross-locale CLDR plural rules the library ships its own data for (English `one/other`, French `n in 0..1` singular, Russian `one/few/many`, Arabic `zero/one/two/few/many/other`, etc.). Adds `intl-messageformat: "^11.2.4"` to `framework/v0.3.11-alpha.2/package.json` dependencies (next to `@rhinostone/swig` and `psl`). Library is BSD-3-Clause, two transitive deps (`@formatjs/fast-memoize` + `@formatjs/icu-messageformat-parser`), zero `new Function`/`eval` calls in the published tarball — preserves the framework's post-#SCS1 eval-safety posture. After clone / merge / worktree switch, `npm install` inside `framework/v0.3.11-alpha.2/` is required to populate the dep (same convention as the existing swig / psl deps). The library is ESM-only since v10, so `lib/i18n` loads it via dynamic `import()` from a module-level loader: `ensureIcuLoaded()` returns a Promise that resolves to the `IntlMessageFormat` constructor; idempotent, cached. `loadCatalogs()` kicks off the loader fire-and-forget at bundle boot so by the time the first request is served the load has resolved and `t.icu()` is sync. Tests can `await ensureIcuLoaded()` explicitly. Failure (e.g. dep not installed) is captured on `icuLoadError`; subsequent `t.icu()` calls surface the error verbatim with an actionable "npm install intl-messageformat" hint. `IntlMessageFormat` instances are memoised per `<bundleName>::<culture>::<key>` on `process.gina._i18nIcuFormatters` so the parse cost is paid once per (bundle, culture, key) per process; `clearCatalogs(bundleName)` drops both the catalog AND the cached formatters so test isolation is clean. Tests at `test/lib/i18n-icu.test.js` — 49 source-inspection + behavioural assertions covering module exports + slice 1/3 export preservation, loader idempotence + error capture, `tIcu` basic API (null/empty key / no-culture / no-catalog / plain placeholder / missing key), plural rules (English / French `n in 0..1` / Russian `one/few/many` / `=0` explicit matchers), select / gender (female / male / other fallback / nested plural inside select), fallback chain (region → base language → bundle default → exhausted), non-string fallthrough (plural-form objects + nested categories + mixed catalog with both shapes), IcuFormatter cache (memoisation + `clearCatalogs` clearing), `gna.t.icu` source-pin (key/params/culture/options signature mirrors `gna.t`), `self.t.icu` source-pin (auto-binds `req.culture` / `local.options.conf.bundle` / `settings.i18n.devMissingKey` / `settings.i18n.fallbackChain`), framework dep declaration, and negative invariants (read-only catalogs / parse error graceful degrade / format error graceful degrade). Full local suite green: 4555 / 4555 (4506 baseline + 49 new). Slice part 2 — `tIcu` template filter for swig + nunjucks + scaffold ICU example + docs site update + roadmap status flip — follows.
|
|
20
|
+
* Added ICU MessageFormat opt-in via the `tIcu` template filter for swig + nunjucks (#I18N2 part 2). Closes #I18N2 — translators and template authors can now use ICU MessageFormat syntax across all three of gina's i18n surfaces (`gna.t.icu()` global, `self.t.icu()` controller helper from part 1, plus the `tIcu` template filter from this part). The filter shape mirrors the existing `t` filter exactly: `{{ "key" | tIcu({ count: 5 }) }}` for plurals, `{{ "key" | tIcu({ gender: 'female', name: user.name }) }}` for select / gender. Auto-binds the request culture from `req.culture` (slice 3) and the bundle from `options.conf.bundle` — same auto-binding pattern as the `t` filter. Identical surface across the swig and nunjucks engines so templates port between renderers unchanged. Catalog values that are NOT strings (plural-form objects, nested categories) fall through to the v1 `t()` path so a single bundle catalog can mix v1 and ICU shapes freely. Roadmap close-out lands in this commit too: #I18N1 (i18n core) and #I18N2 (ICU MessageFormat) both flip from 📋 to ✅ in `ROADMAP.md`. Tests at `test/lib/i18n-icu.test.js` extend with 11 new filter source-pin assertions covering: lib/swig-filters declares `self.tIcu`, swig tIcu reads `req.culture` + `options.conf.bundle`, swig tIcu forwards to `lib.i18n.tIcu`, swig `t` filter unchanged (no regression), the same 5 invariants for lib/nunjucks-filters, and a parity test confirming swig + nunjucks tIcu filters call `lib.i18n.tIcu` with identical arguments. Full local suite green: 4566 / 4566 (4555 from part 1 + 11 new). Closes the #I18N2 contract.
|
|
21
|
+
* Added built-in /_gina/metrics Prometheus exposition endpoint (#OBS1). Opt-in via app.json metrics.enabled = true; install prom-client as a peer dependency in your project (npm install prom-client). Exposes Node.js process metrics (heap, GC pause, event loop lag, active handles) via prom-client.collectDefaultMetrics(), plus a per-request HTTP counter (gina_http_requests_total{method,route,status}) and duration histogram (gina_http_request_duration_seconds{method,route,status}). Route labels come from req.routing.rule (routing.json key) — never the raw URL — to keep Prometheus cardinality bounded; status-aware fallback labels for unmatched paths (__not_found__, __method_not_allowed__, __error__, __no_route__). Endpoint is IP-restricted by default (loopback only; configurable via metrics.allowFrom in app.json); reads client IP from req.socket.remoteAddress only — does NOT trust X-Forwarded-For. Each bundle is an independent scrape target on its own port. Wired in core/server.isaac.js (source of truth) + core/server.js (engine-agnostic mirror, always-on, not gated on NODE_ENV_IS_DEV); request lifecycle hook registers response.on('finish') at request entry. New lib/metrics/src/main.js wraps prom-client (peer dep, project-resolved load via the mysql2/postgres/AI-SDK pattern). Schema/app.json extended with the metrics block. 116 new tests across test/lib/metrics.test.js (behavioural) and test/lib/metrics-wiring.test.js (source-inspection). See docs/guides/observability for adoption.
|
|
22
|
+
* Added ScyllaDB / Cassandra connector — ORM access via cql/<Entity>/*.sql files plus a session store using CQL USING TTL. Drop-in cassandra-driver-based connector following the same client.execute(query, args, { prepare: true }) pattern as MySQL/PostgreSQL with ? placeholders, @param type casting (text/int/bigint/uuid/timestamp/boolean/blob/list/set/map/etc.), and LWT [applied] handling. Driver is loaded from your project node_modules (npm install cassandra-driver).
|
|
23
|
+
* Auto-promoting `route.param.section` to `page.section` so templates that compose include paths from the section name (e.g. `{% include './includes/' + page.section + '.html' %}`) resolve without requiring the controller to set `data.page.section` itself. Mirrors the existing `param.file` → `page.view.file` auto-promotion.
|
|
24
|
+
* Added MongoDB connector — ORM access via JSON pipeline files at models/<db>/pipelines/<Entity>/*.json plus a session store backed by a TTL index. Drop-in mongodb-driver-based connector with {op, filter, doc, ...} JSON bodies, JSDoc-style @param/@return annotations, {$arg: N} positional placeholders for caller args, {$oid: <hex>} ObjectId literals, $scope substitution at load time, and castParam for BSON types (objectid, int/int32, long/int64, double/number, boolean, string/text, date/timestamp). Supported ops: findOne / find / aggregate / countDocuments / insertOne / insertMany / updateOne / updateMany / replaceOne / deleteOne / deleteMany. Session store auto-creates the TTL index on first set() with a one-shot guard; get/length/all filter on expiresAt to exclude documents that expired but were not yet reaped by the 60s MongoDB TTL monitor. Driver is loaded from your project node_modules (npm install mongodb).
|
|
25
|
+
### Changed
|
|
26
|
+
* Bumped `@rhinostone/swig` from 1.6.0 to 2.0.0 (`framework/v*/package.json`). The fork's 2.0.0 release carved internals into `@rhinostone/swig-core` and ships a self-contained pre-built esbuild bundle at `dist/swig.js`. Phase 7 of the asset build now copies the upstream esbuild bundle directly into `dist/swig.min.js` instead of running Closure Compiler on `bin/swig.js` — Closure does not follow npm `require()`, so post-2.0.0 the Closure path would carry unresolved `swig-core` requires. The framework's swig-resolver `DEFAULT_MIN` floor (`lib/swig-resolver/src/main.js`) shifts from `1.6.0` to `2.0.0`; bundles that opt into a project-pinned swig (`swig.useProject: true`) must now pin `>= 2.0.0` of `@rhinostone/swig` for the resolver to honour the override. Server-side API is unchanged — same entry points, same compiled output.
|
|
27
|
+
### Fixed
|
|
28
|
+
* Fixed `prepare_version.js` writing `settings.json`'s `version` field without also updating `settings.json`'s `def_framework` field. The original block at line 482 set `mainConfig.def_framework` but only `settingsConfig.version` (not `settingsConfig.def_framework`), producing a `version:<new> + def_framework:<old>` split inside settings.json (and in gina.db's settings/<short> blob via StateStore) on every npm publish. Mirrors the safe writer pattern already in `post_publish.js:413-421` (bumpVersion writes both `settings.version` AND `settings.def_framework` together). The defensive pre-publish gate added earlier in the same release window catches the symptom at publish time; this fixes the root cause for settings.json drift specifically. The `~/.gina/main.json` def_framework drift observed in the same v0.3.10 forensic snapshot (main.json showed `def_framework: "0.3.9"` while the framework dir on disk was at `v0.3.10-alpha.2`) is NOT fully explained by this fix — `main.json` gets `def_framework=targetedVersion` correctly at line 483 of the same block — so the trigger for main.json drift remains under investigation as a separate follow-up.
|
|
29
|
+
* Fixed `npm install -g gina@<older>` regressing `~/.gina/main.json`'s `def_framework` field to the older tarball's version. `script/post_install.js:822` previously had no semver-newer guard — any reinstall with an older version unconditionally overwrote the scalar `def_framework`. Combined with the self-perpetuating abort loop at `script/prepare_version.js:449` (once the scalar pointed to a framework dir that had been renamed away, every subsequent prepare aborted before reaching the writer that would correct it), this could leave `~/.gina/main.json` stuck pointing at a missing version. Triggered exactly this shape on the v0.3.10 stable publish (2026-05-06), where the scalar was at `0.3.9` while the framework dir on disk was at `v0.3.10-alpha.2`. Fix adds a strict-semver pre-release-aware comparator (`script/version_compare.js`, 35 unit tests + 6 source-structure pins) and gates the `def_framework` write at `post_install.js:822` so older-version reinstalls preserve the newer state and emit a `Skipping def_framework update` console.info instead. The `frameworks` LIST is still updated on regression skip (additive history). The defensive gate at `script/check_def_framework_consistency.js` (added in the same release window) continues as the publish-time safety net; this removes the trigger.
|
|
30
|
+
* Fixed cross-bundle leak under reverse-proxy sub-path mounts where the routing.json fetch would land on the wrong upstream. `core.js::getDependencies` (in `gina.min.js`) runs from the gina script-tag onload handler BEFORE `window.onGinaLoaded` populates `gina.config`, so `gina.config.webroot` was undefined at fetch time and the URL collapsed to `/_gina/assets/routing.json` — answered by whichever upstream served `/` rather than the bundle that rendered the page. Fix: `loader.js` now exposes `window.__ginaWebroot` synchronously at script parse time (whispered server-side from `page.environment.webroot`, which already includes any `X-Forwarded-Prefix` composition from the previous slice). `core.js` reads `window.__ginaWebroot` first, falling back to `gina.config.webroot` then `'/'` for backward compat. The synchronous global is reliably available because `gina.onload.min.js` is injected into `<head>` BEFORE `gina.min.js` by every full-page render path in `controller.render-swig.js` (`:1185-1194` dev, `:1262-1271` prod). +13 tests in `test/core/controller.test.js` § 10 (loader + core source pins, pure-logic resolution-chain replica, dist-equivalence check).
|
|
31
|
+
* Fixed cross-request leak of the X-Forwarded-Prefix-derived webroot prefix. `process.gina.PROXY_PREFIX` was set by `server.isaac.js` inside a `!isProxyHost && headers['x-forwarded-host']` gated block — the gate stops firing after the first proxied request flips `isProxyHost` to globally true via `setContext('isProxyHost', true)`, so subsequent requests never re-derived the prefix and the value stayed at the FIRST proxied request's value forever (until worker restart). This bit any worker handling a mix of proxied + direct calls (e.g. internal services hitting the bundle without going through the proxy — direct calls inherited the leaked prefix and rendered with the wrong webroot) and bundles behind a proxy that mounts them at multiple paths. Fix moves the prefix processing OUT of the gated block so it runs on every request, and switches the slot from process-global `process.gina.PROXY_PREFIX` to per-request `request._ginaProxyPrefix`. Reader at `controller.js` `set('page.environment.webroot')` setter site updated to read `local.req._ginaProxyPrefix` (with `local.req && typeof != 'undefined'` defensive guard). Normalisation steps (trim / strip trailing slashes / prepend leading slash / drop empty / drop '/') unchanged. +9 tests across `test/core/server.isaac.test.js` (1 new positive: writer outside gated block; 1 new negative: process.gina.PROXY_PREFIX is no longer written; 2 existing source pins re-aimed at request._ginaProxyPrefix) and `test/core/controller.test.js` § 09 (5 per-request isolation tests including the cross-request-leak repro: req A sets prefix, req B without header gets undefined and bundle-internal webroot; 1 new negative: process.gina.PROXY_PREFIX is no longer read; 2 existing source pins re-aimed at local.req._ginaProxyPrefix). Full local suite 4050/4050 green.
|
|
32
|
+
* Bumped @rhinostone/swig to 2.0.1. Fixes bracket-access expressions like `arr[arr.length-1]` and `arr[idx-1]` that previously failed with "Unexpected closing square bracket". Restores correct rendering of negative-literal expressions like `{{ -5 }}` whose leading sign was being eaten by the whitespace-control regex. Adds `{{- … -}}` / `{%- … -%}` whitespace-control parity to `@rhinostone/swig-twig`.
|
|
33
|
+
|
|
9
34
|
## 0.3.10 - 2026-05-06
|
|
10
35
|
### Added
|
|
11
36
|
* Reverse-proxy path-prefix awareness via the standard `X-Forwarded-Prefix` request header. When a reverse proxy (nginx, Traefik, etc.) mounts the bundle on a sub-path and forwards `proxy_set_header X-Forwarded-Prefix /sub;`, the framework composes a public webroot (proxy prefix + bundle internal `server.webroot`) and templates that into `gina.config.webroot`. Client-side URL construction (`/_gina/assets/routing.json` fetch, the `gina.min.css` link injection, etc.) now targets the correct upstream through the proxy instead of root-relative URLs that would route to whichever bundle answered `/`. Header value is normalised (leading slash, trailing slashes stripped, empty / "/" dropped); back-compat preserved when the header is absent.
|
package/CONVENTIONS.md
CHANGED
|
@@ -639,6 +639,38 @@ it('name', async function() {
|
|
|
639
639
|
|
|
640
640
|
> Every async `it()` block must either be declared `async` or explicitly `return` a Promise. Any test that calls an async API without doing either will silently pass without testing anything.
|
|
641
641
|
|
|
642
|
+
### Negative-invariant tests can false-positive on their own descriptive comments
|
|
643
|
+
|
|
644
|
+
When writing a "X must NOT appear" assertion that scans source content, the assertion's surrounding test description AND the code under test's own comments are part of the search surface. A test that asserts "string Y must not appear in region R" can fail when:
|
|
645
|
+
|
|
646
|
+
- The test description literally says "must not appear: Y"
|
|
647
|
+
- The reader code under test has a comment "do NOT use Y, prefer Z instead" — the literal Y is still in the file
|
|
648
|
+
- An adjacent file's comment says "this replaces the old Y mechanism" — also in the file
|
|
649
|
+
|
|
650
|
+
**Worked example** (`cd95151b`, 2026-05-07): added a negative-invariant test in `test/core/controller.test.js`:
|
|
651
|
+
|
|
652
|
+
```js
|
|
653
|
+
it("source does NOT read process.gina.PROXY_PREFIX (the leaky process-global is removed)", function() {
|
|
654
|
+
// ...
|
|
655
|
+
assert.ok(
|
|
656
|
+
block.indexOf('process.gina.PROXY_PREFIX') === -1,
|
|
657
|
+
'...'
|
|
658
|
+
);
|
|
659
|
+
});
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
The assertion failed because the source comment in `controller.js` near the new reader read `// Per-request slot (NOT process.gina.PROXY_PREFIX) so the prefix cannot leak...`. The literal `process.gina.PROXY_PREFIX` was the false positive — describing what NOT to use was the same string the test was scanning for.
|
|
663
|
+
|
|
664
|
+
**Fix:** rephrase the comment to describe the contrast without the literal forbidden token: `// Per-request slot (NOT a process-global) so the prefix cannot leak...`. Test passed without weakening.
|
|
665
|
+
|
|
666
|
+
**Authoring patterns to avoid the trap:**
|
|
667
|
+
|
|
668
|
+
- Avoid explanatory "NOT X" / "do not use X" / "replaced X" comments anywhere a negation test scans for X. Describe the alternative positively instead.
|
|
669
|
+
- If you genuinely need to mention the forbidden token (e.g., a deprecation comment in a separate file the test doesn't scan), keep it OUTSIDE the test's scan window.
|
|
670
|
+
- When a negation test fails unexpectedly, re-read the assertion alongside the surrounding source — your own comment is the most likely false positive.
|
|
671
|
+
|
|
672
|
+
**Detection rule of thumb:** if your test says "must NOT contain X" and `grep -rn "X" <region>` returns the assertion description itself OR a "not X" comment, the test will reject those false positives the same way it rejects real violations.
|
|
673
|
+
|
|
642
674
|
---
|
|
643
675
|
|
|
644
676
|
## Debugging — measurement gotchas
|
package/README.md
CHANGED
|
@@ -20,9 +20,11 @@ Node.js MVC framework with built-in HTTP/2, multi-bundle architecture, and scope
|
|
|
20
20
|
| MVC routing | `routing.json` — declare routes in config, not code; O(m) radix trie lookup |
|
|
21
21
|
| Async/await | Controller actions can be `async`; rejections routed to `throwError` automatically |
|
|
22
22
|
| ORM / entities | EventEmitter-based entity system; SQL files auto-wired to entity methods |
|
|
23
|
-
| Connectors | Couchbase, MySQL, PostgreSQL, Redis, SQLite, AI (LLM) — loaded from project `node_modules` |
|
|
23
|
+
| Connectors | Couchbase, MongoDB, ScyllaDB / Cassandra, MySQL, PostgreSQL, Redis, SQLite, AI (LLM) — loaded from project `node_modules` |
|
|
24
24
|
| AI connector | Any LLM provider via named protocol (`anthropic://`, `openai://`, `ollama://`, …) |
|
|
25
|
-
| Template engine | [`@rhinostone/swig`](https://github.com/gina-io/swig)
|
|
25
|
+
| Template engine | [`@rhinostone/swig`](https://github.com/gina-io/swig) 2.0.1 — maintained fork with CVE-2023-25345 patched; streaming SSE/chunked via `renderStream()`. Nunjucks supported as opt-in via `render.engine = "nunjucks"` |
|
|
26
|
+
| Internationalisation | Per-bundle JSON catalogs, `t()` helper, swig + nunjucks `t` filter, CLDR plurals, ICU MessageFormat opt-in via `t.icu()` |
|
|
27
|
+
| Observability | Built-in `/_gina/metrics` Prometheus endpoint (opt-in, IP-allowlisted) — Node.js process metrics + HTTP counter / duration histogram with cardinality-safe route labels |
|
|
26
28
|
| Hot reload | WatcherService evicts `require.cache` only on file change — zero per-request overhead in dev |
|
|
27
29
|
| K8s ready | `gina-container`, `gina-init`, SIGTERM drain, JSON stdout logging |
|
|
28
30
|
| Dependency injection | Mockable connectors and config for unit testing |
|
|
@@ -37,6 +39,17 @@ gina bundle:start api @myproject
|
|
|
37
39
|
open https://localhost:3100
|
|
38
40
|
```
|
|
39
41
|
|
|
42
|
+
## What's in 0.3.11
|
|
43
|
+
|
|
44
|
+
- **Internationalisation** (#I18N1 + #I18N2) — per-bundle JSON catalogs at `bundle/locales/<culture>.json`, `t(key, params, culture)` global helper auto-bound on controllers (`self.t()`) and as a swig + nunjucks `t` template filter, CLDR plurals via Node's built-in `Intl.PluralRules`, per-request locale negotiation (URL prefix > cookie > `Accept-Language` > settings default). New `gina i18n:scan / add / export / import` CLI for translator round-trip (PO / CSV / JSON). Optional ICU MessageFormat opt-in via `t.icu()` for gender / select / nested combinators powered by `intl-messageformat`. The legacy `__()` placeholder is rewired as a one-arg alias of `t()` — existing callers keep working.
|
|
45
|
+
- **Prometheus metrics endpoint** (#OBS1) — built-in `/_gina/metrics` exposing the standard Prometheus exposition format. Default metrics cover Node.js process state (heap, GC, event loop lag), HTTP request counter and duration histogram with cardinality-safe route labels (`req.routing.rule` with `__not_found__` / `__method_not_allowed__` / `__error__` / `__no_route__` fallbacks). IP-allowlist gated (loopback only by default; does NOT trust `X-Forwarded-For`). Opt-in via `app.json metrics.enabled`; install `prom-client` as a peer dependency.
|
|
46
|
+
- **ScyllaDB / Cassandra ORM connector** (#CN5) — entity classes with CQL prepared statements at `models/<keyspace>/cql/<Entity>/*.sql`, `@param` type coercion, lightweight-transaction (`IF NOT EXISTS`, `IF version = ?`) `[applied]` boolean handling, and a session store using CQL `USING TTL` for server-side reaping. Wraps the official `cassandra-driver` (Apache Software Foundation; Node.js has no first-party shard-aware driver, so token-aware routing is used). Requires Node 20+.
|
|
47
|
+
- **MongoDB ORM connector** (#CN6) — entity classes with JSON pipeline files at `models/<db>/pipelines/<Entity>/*.json`, JSDoc-style `@param`/`@return` headers, BSON-type casting (`objectid`, `int`, `long`, `double`, `boolean`, `date`, `timestamp`), `{$arg: N}` and `{$oid: "<hex>"}` placeholder shapes, eleven supported operations (`findOne` / `find` / `aggregate` / `countDocuments` / 7 writes), and a session store using a TTL index auto-created on first `set()` with `expiresAt > now` filtering on reads to cover MongoDB's 60-second TTL-monitor lag. Wraps the official `mongodb` driver.
|
|
48
|
+
- **`@rhinostone/swig` major bump 1.6.0 → 2.0.1** — upstream stable cycle. The framework's Phase 7 build switched from Closure-compiling `bin/swig.js` to copying the upstream esbuild bundle directly, so `swig-core`'s lazy `require()` works in the browser bundle. Resolver `DEFAULT_MIN` floor lifted to `2.0.0` — projects pinning `swig.useProject: true` need a `^2.0.0` install in their own `node_modules` to satisfy the resolver. Server-side API unchanged.
|
|
49
|
+
- **`page.section` auto-promotion** — `route.param.section` is now auto-promoted to `page.section` in the controller setup, for templates that compose include paths from a section name (sub-section dispatch from a single `index.html` that fans out to per-section partials based on the matched route).
|
|
50
|
+
- **X-Forwarded-Prefix per-request isolation** — fixes a cross-request webroot prefix leak under reverse-proxy sub-path mounts where the prefix was previously stored on `process.gina.PROXY_PREFIX` (process-global, sticky-after-first-request, leaking into direct/non-proxied calls); now per-request on `request._ginaProxyPrefix`. Combined with a synchronous `window.__ginaWebroot` global on the client to fix a `getDependencies` race where `gina.config.webroot` was undefined at script-tag onload time.
|
|
51
|
+
- **Release pipeline hardening** — three independent fixes for the `~/.gina/main.json` `def_framework` drift family: defensive pre-publish gate (`script/check_def_framework_consistency.js`), settings.json side fix in `prepare_version.js`, main.json side fix in `post_install.js` with a strict-semver comparator that skips def_framework updates on older-version reinstalls.
|
|
52
|
+
|
|
40
53
|
## What's in 0.3.10
|
|
41
54
|
|
|
42
55
|
- **FormValidator HTML5 form-reassociation hardening** — trilogy of fixes for `<input form="X">` controls. `bindForm` now uses `HTMLFormControlsCollection` (`form.elements`) for owner-aware control collection and attaches per-control listeners on out-of-tree reassociated controls; `unbindForm` symmetrically drains the side-table on cleanup. `updateRadio` scopes the mutual-exclusion peer set by form-owner — same-name radios in different form-owners are no longer cross-fired into each other's loop — and reconciles the IDL `.checked` with the HTML `checked` attribute on init when they disagree. `bindForm`'s `fieldsSet[id].defaultChecked` cache reads the IDL `defaultChecked` property (which mirrors the HTML attribute regardless of the live IDL state) instead of the live `.checked`, so a `type="reset"` action correctly restores the originally-checked option. No-op for the normal single-form-owner shape — only changes behaviour in the form-reassociation layouts that were broken.
|
package/ROADMAP.md
CHANGED
|
@@ -23,7 +23,7 @@ This roadmap covers planned features, architectural improvements, new connectors
|
|
|
23
23
|
| **Q4 2026** | `0.3.8` ✅ | Patch: `npm install -g gina@latest` regression fix — `psl` + `@rhinostone/swig` promoted to top-level deps · install scripts decoupled from framework `lib` registry · helpers preload guarding `lib/logger` ↔ `framework/v*/helpers` circular dep |
|
|
24
24
|
| **Q2 2026** | `0.3.9` ✅ | Consumer-feedback batch (11 framework patches): per-request middleware dispatch isolation · Couchbase 4.x JsonTranscoder · `length` filter null safety · `process.env` mirroring · 6 nunjucks render-pipeline patches (libRef fallback · namespace prefix drop · bundle filter wraps · top-level userData · `data.data` alias · ginaLoader placeholders) · `getAssets` mid-URL `{{ }}` strip-guard anchor |
|
|
25
25
|
| **Q2 2026** | `0.3.10` ✅ | FormValidator HTML5 form-reassociation hardening trilogy (`HTMLFormControlsCollection`-based `bindForm` + `unbindForm` symmetry · radio mutual-exclusion + IDL/attribute reconciliation · `defaultChecked` cache for reset) · `X-Forwarded-Prefix` reverse-proxy path-prefix awareness |
|
|
26
|
-
| **Q4 2026** | `0.4.0` | AI agents (MCP) · ScyllaDB connector · PWA scaffold ·
|
|
26
|
+
| **Q4 2026** | `0.4.0` | AI agents (MCP) · ScyllaDB connector · PWA scaffold · Advanced tutorial · Website redesign · Docs offline ZIP · Bun investigation · Couchbase v2 removal · HTTP/2 hardening · Trailer support · CLI Tier 2 (bundle/project status, rename, copy, protocol:remove, minions) |
|
|
27
27
|
| **Q1 2027** | `0.5.0` | ESM support · Template engine migration · Structured logging · Alt-Svc · HTTP/2 priorities · WebSocket over HTTP/2 · Inspector Production · CLI Tier 3 (project:move, framework:update, backup/restore, man pages) |
|
|
28
28
|
| **Q3 2027** | `1.0.0` | First stable release — Windows alpha compatibility is a hard gate |
|
|
29
29
|
|
|
@@ -35,7 +35,8 @@ This roadmap covers planned features, architectural improvements, new connectors
|
|
|
35
35
|
| --- | --- | --- | --- |
|
|
36
36
|
| ✅ | **Automatic version migration** — Upgrading or downgrading gina (e.g. `0.1.x → 0.2.0`, `0.5.x → 1.0.0`) automatically migrates `~/.gina/` config to the new version on first startup. Downgrade is free — old version data is never removed. | `0.1.8` | 2026-03-26 |
|
|
37
37
|
| ✅ | **`watchers.json`** — First-class bundle config for file watchers. Declare watchers on config files with event-based notification (no polling). Foundation for the dev-mode hot-reload system. | `0.2.0` | 2026-03-29 |
|
|
38
|
-
|
|
|
38
|
+
| ✅ | **i18n core** — Per-bundle message catalogs under `bundle/locales/<culture>.json` with a fallback chain (specific culture → base language → default). Server-side `t(key, [params], [culture])` global helper with parameter interpolation and CLDR pluralisation. Swig and Nunjucks filters with the same surface (`{{ "key"\|t }}`, `{{ "key"\|t({ name: x }) }}`). Per-request locale negotiation from URL prefix / cookie / `Accept-Language` / settings default. CLI: `gina i18n:scan` for missing-key coverage per culture, `i18n:add <culture>` to seed a new catalog, `i18n:export` / `i18n:import` for `.po` / `.csv` / `.json` round-trip with translators. Headless by design — the visual translation editor lands later as the first content feature in Beemaster (admin Phase 3). Runtime + filters + `req.culture` negotiation + full CLI all shipped on the `0.3.11-alpha` track. | `0.3.11-alpha` | 2026-05-08 |
|
|
39
|
+
| ✅ | **i18n ICU MessageFormat** — Opt-in `t.icu(key, params, culture)` variant powered by `intl-messageformat`. Adds gender / select / nested combinators (`{count, plural, one {# item} other {# items}}`, `{gender, select, female {…} male {…} other {…}}`) on top of the i18n core. Existing `t()` shape unchanged — v1 catalogs continue to work. Covers grammars (Romance, Slavic) and select expressions the v1 `{name}` + plural-forms shape can't express. Exposed as `gna.t.icu()` (global), `self.t.icu()` (controller helper), and `tIcu` template filter (swig + nunjucks). Library loaded via dynamic `import()` from a module-level loader kicked off at bundle boot — sync API after first-call resolves. | `0.3.11-alpha` | 2026-05-08 |
|
|
39
40
|
| 📋 | **PWA scaffold** — `gina bundle:add` drops `manifest.json`, a service worker stub (`sw.js`), and the required `<meta>` / `<link>` tags into the bundle boilerplate. Zero runtime dependency. Enables Gina apps to be installed on mobile as PWAs without additional tooling. | `0.4.0` | Q4 2026 |
|
|
40
41
|
| ✅ | **Per-bundle framework version** — Declare `"gina_version": "0.1.8"` on any bundle entry in `manifest.json` to pin that bundle to a specific installed framework version. The socket server continues running its own version; only the spawned bundle process uses the declared version. Validated against the tracked version list in `main.json` before start. `--gina-version=X.Y.Z` flag on `bundle:start` provides the same override without touching config files. | `0.3.0` | 2026-03-31 |
|
|
41
42
|
| ✅ | **PATCH method** — `req.patch` populated with the parsed request body (JSON or form-encoded). `req.body` aliases `req.patch`. URI params merged. `"method": "PATCH"` valid in `routing.json`. Use PATCH for partial updates (only sent fields change) vs PUT which replaces the full resource. | `0.3.0` | 2026-03-31 |
|
|
@@ -165,8 +166,8 @@ New database connectors follow the same interface as the existing Couchbase conn
|
|
|
165
166
|
| ✅ | **SQLite** | `0.2.0` | Q2 2026 | Three use cases: framework state storage (replaces JSON files under `~/.gina/`), session store for single-pod/dev deployments, and embedded ORM connector. Uses `node:sqlite` (Node.js built-in since v22.5.0 — zero npm deps). Session store done (v1 — 2026-03-27 · `96c5808a`); ORM connector done (v2 — 2026-03-28 · `08ead296`); state storage done (v3 — 2026-03-28 · `da5c55ba`). |
|
|
166
167
|
| ✅ | **MySQL / MariaDB** | `0.3.0` | Q1 2026 | ORM connector. Client: `mysql2`. Entity wiring, `sql/` layout, `?` placeholders, `@param`/`@return` annotations, native Promise + `.onComplete()`. |
|
|
167
168
|
| ✅ | **PostgreSQL** | `0.3.0` | Q1 2026 | ORM connector. Client: `pg` (node-postgres). Entity wiring, `sql/` layout, `$1`/`$2` placeholders, `@param`/`@return` annotations, idle-client error guard, native Promise + `.onComplete()`. |
|
|
168
|
-
|
|
|
169
|
-
|
|
|
169
|
+
| ✅ | **ScyllaDB** | `0.4.0` | Q4 2026 | Cassandra-compatible wide-column store. Client: `cassandra-driver` (Apache Software Foundation; Node.js has no first-party shard-aware driver — token-aware routing only). ORM connector + session store via CQL `USING TTL`. Implemented 2026-05-09 (#CN5). |
|
|
170
|
+
| ✅ | **MongoDB** | `0.4.0` | Q4 2026 | Document store connector. Client: `mongodb` (official driver, `>=7.0.0`). ORM connector with `pipelines/<Entity>/*.json` files (JSON body + JSDoc-style `@param`/`@return` annotations + `{$arg: N}` positional placeholders + `{$oid: <hex>}` ObjectId literals + `$scope` substitution at load time). Session store backed by a TTL index (`createIndex({expiresAt: 1}, {expireAfterSeconds: 0})` auto-created on first `set()` with one-shot guard). `get()`/`length()`/`all()` filter on `expiresAt` to protect against MongoDB's 60s TTL monitor lag. Implemented 2026-05-09 (#CN6). |
|
|
170
171
|
| ✅ | **Couchbase SDK v2 deprecation** | `0.2.0` | 2026-03-27 | Couchbase Server SDK v2 reached end-of-life in 2021. `connector.v2.js` now logs a deprecation warning at connection time, and a fatal error when V8 pointer compression is active (NAN bindings are incompatible). Upgrade path: set `sdk.version` to `3` or `4` in your bundle's `connectors.json`. |
|
|
171
172
|
| 📋 | **Couchbase SDK v2 removal** | `0.4.0` | Q4 2026 | `connector.v2.js` and all `sdk.version <= 2` branches removed. Default falls back to v3 when `sdk.version` is unset. Full migration guide in `CHANGELOG.md`. |
|
|
172
173
|
| ✅ | **`peerDependencies` for connector clients** | `0.3.0` | 2026-04-01 | All connector client libraries (`ioredis`, `mysql2`, `pg`, `mongodb`, `@scylladb/scylla-driver`, `couchbase`, `openai`, `@anthropic-ai/sdk`) are declared as optional `peerDependencies`. Signals the tested version range to npm/yarn and surfaces a compatibility warning when a user pins an untested version. Zero framework runtime dependency — clients are always loaded from the project's `node_modules`. |
|
|
@@ -222,7 +223,7 @@ A cold audit of the Couchbase connector identified two critical security vulnera
|
|
|
222
223
|
|
|
223
224
|
| Status | Feature | Version | Target |
|
|
224
225
|
| --- | --- | --- | --- |
|
|
225
|
-
|
|
|
226
|
+
| ✅ | **Prometheus metrics endpoint** — Built-in `/_gina/metrics` endpoint exposing Prometheus-format metrics. Opt-in via `app.json` (`"metrics": { "enabled": true }`). Collects Node.js process metrics (heap, GC, event loop lag) automatically via `prom-client.collectDefaultMetrics()`, plus HTTP request metrics — count, latency histogram, status-aware fallback labels — sourced from `req.routing.rule` (routing.json key, cardinality-safe; never the raw URL). `prom-client` is loaded from the user project's `node_modules` (peer dependency, same pattern as `ioredis` and `mysql2`). Endpoint is IP-restricted by default (loopback only; configurable via `metrics.allowFrom` in `app.json`); reads client IP from `req.socket.remoteAddress` only — does NOT trust `X-Forwarded-For`. Each bundle self-reports on its own port — point Prometheus at `host:port/_gina/metrics` per bundle, no sidecar required. | `0.3.11-alpha` | 2026-05-09 |
|
|
226
227
|
|
|
227
228
|
---
|
|
228
229
|
|
package/bin/cli
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.3.11
|
|
@@ -5105,6 +5105,13 @@ function Routing() {
|
|
|
5105
5105
|
if ( typeof(routeObject.csrfExempt) != 'undefined' ) {
|
|
5106
5106
|
params.csrfExempt = routeObject.csrfExempt;
|
|
5107
5107
|
}
|
|
5108
|
+
// #I18N1 slice 3 — propagate per-route culture-prefix flag to
|
|
5109
|
+
// req.routing.culturePrefix. When true, the negotiator at the
|
|
5110
|
+
// request-pipeline boundary reads req.routing.param.culture as
|
|
5111
|
+
// the highest-priority culture source (URL prefix).
|
|
5112
|
+
if ( typeof(routeObject.culturePrefix) != 'undefined' ) {
|
|
5113
|
+
params.culturePrefix = routeObject.culturePrefix;
|
|
5114
|
+
}
|
|
5108
5115
|
if ( typeof(routeObject.queryTimeout) != 'undefined' ) {
|
|
5109
5116
|
params.queryTimeout = parseTimeout(routeObject.queryTimeout);
|
|
5110
5117
|
}
|
|
@@ -21434,12 +21441,26 @@ function getDependencies(gina, cb) {
|
|
|
21434
21441
|
}
|
|
21435
21442
|
}
|
|
21436
21443
|
|
|
21437
|
-
// Gina
|
|
21438
|
-
//
|
|
21439
|
-
//
|
|
21440
|
-
//
|
|
21444
|
+
// Gina mandatory dependencies are handled here.
|
|
21445
|
+
//
|
|
21446
|
+
// Webroot resolution race: this code runs from the gina script-tag onload
|
|
21447
|
+
// handler (see ~line 335 below), which fires BEFORE `window.onGinaLoaded`
|
|
21448
|
+
// populates `gina.config`. At this point `gina.config.webroot` is undefined,
|
|
21449
|
+
// so the URL would fall back to '/' and routing.json would be fetched
|
|
21450
|
+
// root-relative — landing on the wrong upstream under reverse-proxy
|
|
21451
|
+
// sub-path mounts.
|
|
21452
|
+
//
|
|
21453
|
+
// `gina.onload.min.js` (whispered server-side) sets `window.__ginaWebroot`
|
|
21454
|
+
// synchronously at script parse time, BEFORE this script executes, so its
|
|
21455
|
+
// value is reliably available here. Fall back to `gina.config.webroot`
|
|
21456
|
+
// (works when `onGinaLoaded` did already run, e.g. re-entry), then to '/'.
|
|
21457
|
+
//
|
|
21458
|
+
// `core.js` itself ships in `gina.min.js`, which is served as a static
|
|
21459
|
+
// asset without a whisper pass — so `{{ page.environment.webroot }}` tokens
|
|
21441
21460
|
// embedded here would reach the browser un-interpolated and break the fetch.
|
|
21442
|
-
var _webroot = (
|
|
21461
|
+
var _webroot = (typeof window !== 'undefined' && window.__ginaWebroot)
|
|
21462
|
+
|| (gina && gina.config && gina.config.webroot)
|
|
21463
|
+
|| '/';
|
|
21443
21464
|
var arr = [
|
|
21444
21465
|
// Get routing to populate `window.gina.config.routing`
|
|
21445
21466
|
// Now fetching routing from gina
|
package/framework/{v0.3.11-alpha.1 → v0.3.11}/core/asset/plugin/dist/vendor/gina/js/gina.min.js
RENAMED
|
@@ -104,10 +104,10 @@ function Routing(){var m=typeof module!=='undefined'&&module.exports?!1:!0,E={al
|
|
|
104
104
|
(M&&typeof M=='function'||(M=require('lib/merge')),C&&typeof C=='function'||(C=require('lib/form-validator'))):(require('fs'),require('util'),require('../../inherits'),M=require('../../merge'),I=require(__dirname+'/../../../core/plugins')||getContext('gina').plugins,C=I.Validator);E.getUrlProps=function(n,l){var c={};if(m){var S=window.gina.config;c.hostname=S.hostname;typeof n!='undefined'&&(n=this.getRoute('webroot@'+n),c.hostname=n.hostname,c.host=n.host,c.webroot=n.webroot)}else S=getContext('gina').config,
|
|
105
105
|
typeof getContext('argvFilename')!='undefined'&&(S.getRouting=getContext('gina').Config.instance.getRouting),typeof n=='undefined'&&(n=S.bundle),typeof l=='undefined'&&(l=S.env),c.hostname=S.envConf[n][l].hostname,c.host=S.envConf[n][l].host,c.webroot=S.envConf[n][l].server.webroot,console.debug('[self.getUrlProps][isProxyHost = '+getContext('isProxyHost')+'] hostname ',S.envConf[n][l].hostname,vs,process.gina.PROXY_HOSTNAME);return c};E.cache=function(n,l,c,S,ka){Routing._cached.indexOf(n)==-1&&
|
|
106
106
|
(Routing._cached.length>=5E3&&E.invalidateCached(Routing._cached[0]),Routing._cached.push(n),Routing._cachedRoutes[n]={name:l,routing:c,params:S,methodParams:ka})};E.getCached=function(n,l){if(Routing._cached.indexOf(n)>-1){var c=Routing._cachedRoutes[n],S=l.method.toLowerCase();n=JSON.clone(c.routing);c={method:S,requirements:n.requirements,namespace:n.namespace||void 0,url:decodeURI(l.url),rule:n.originalRule||c.name,param:n.param,middleware:n.middleware,bundle:n.bundle,isXMLRequest:l.isXMLRequest,
|
|
107
|
-
isWithCredentials:l.isWithCredentials};typeof n.rule=='undefined'&&typeof c.rule!='undefined'&&(n.rule=c.rule);typeof n.cache!='undefined'&&(c.cache=n.cache);typeof n.csrfExempt!='undefined'&&(c.csrfExempt=n.csrfExempt);typeof n.queryTimeout!='undefined'&&(c.queryTimeout=parseTimeout(n.queryTimeout));return E.compareUrls(c,n.url,l)}return null};E.invalidateCached=function(n){Routing._cached.indexOf(n)>-1&&(Routing._cached.splice(Routing._cached.indexOf(n),
|
|
108
|
-
async function(n,l,c,S,ka){typeof c=='undefined'&&(c={routing:{}});if(/,/.test(l)){var aa=0;l=l.split(/,/g);for(var v=l.length,u={past:!1,request:c};aa<v&&!u.past;)u=await A(n,l[aa],c,S,ka),++aa;return u}return await A(n,l,c,S,ka)};var A=async function(n,l,c,S,ka){var aa=null;try{aa=n.url.split(/\//)}catch(L){console.warn(L),aa=['']}l=l.split(/\//);var v=0,u=0,V=l.length,h=0,g={},q=0,F=c.method.toLowerCase(),N='get';try{N=n.method.toLowerCase()}catch(L){}var r
|
|
109
|
-
|
|
110
|
-
n,c,S,ka)){++h;continue}/^:/.test(l[L])&&typeof N!='undefined'&&(new RegExp(N)).test(aa[L])&&(++h,c[F][l[L].substring(1)]=aa[L])}r=!0}for(var w in c[F])typeof n.requirements[w]!='undefined'&&l.indexOf(':'+w)<0&&(l[u]=':'+w,++u,aa[v]=c[F][w],++v,r||aa.length!==l.length||++V)}if(!r&&aa.length===l.length)for(;q<V;++q)aa[q]===l[q]?++h:h==q&&/:/.test(l[q])&&await U(l[q],aa[q],n,c,S,ka)&&++h;if(typeof n.requirements!='undefined'&&F==n.method.toLowerCase()&&!r&&h>=V)for(w=Object.getOwnPropertyNames(n.requirements),
|
|
107
|
+
isWithCredentials:l.isWithCredentials};typeof n.rule=='undefined'&&typeof c.rule!='undefined'&&(n.rule=c.rule);typeof n.cache!='undefined'&&(c.cache=n.cache);typeof n.csrfExempt!='undefined'&&(c.csrfExempt=n.csrfExempt);typeof n.culturePrefix!='undefined'&&(c.culturePrefix=n.culturePrefix);typeof n.queryTimeout!='undefined'&&(c.queryTimeout=parseTimeout(n.queryTimeout));return E.compareUrls(c,n.url,l)}return null};E.invalidateCached=function(n){Routing._cached.indexOf(n)>-1&&(Routing._cached.splice(Routing._cached.indexOf(n),
|
|
108
|
+
1),delete Routing._cachedRoutes[n])};E.compareUrls=async function(n,l,c,S,ka){typeof c=='undefined'&&(c={routing:{}});if(/,/.test(l)){var aa=0;l=l.split(/,/g);for(var v=l.length,u={past:!1,request:c};aa<v&&!u.past;)u=await A(n,l[aa],c,S,ka),++aa;return u}return await A(n,l,c,S,ka)};var A=async function(n,l,c,S,ka){var aa=null;try{aa=n.url.split(/\//)}catch(L){console.warn(L),aa=['']}l=l.split(/\//);var v=0,u=0,V=l.length,h=0,g={},q=0,F=c.method.toLowerCase(),N='get';try{N=n.method.toLowerCase()}catch(L){}var r=
|
|
109
|
+
!1;if(typeof n.requirements!='undefined'&&/get|delete/i.test(F)&&typeof c[F]!='undefined'||typeof n.requirements!='undefined'&&/get/i.test(F)&&/delete/i.test(N)){/get/i.test(F)&&/delete/i.test(N)&&(F=N);if(/^(delete)$/i.test(F)&&aa.length===l.length){typeof c[F]=='undefined'&&(c[F]={});for(let L=0,fa=l.length;L<fa;L++){if(aa[L]===l[L]){++h;continue}N=l[L].substring(1);if(typeof n.requirements[N]=='undefined')continue;N=n.requirements[N];if(/^\//.test(N))N=N.substring(1,N.lastIndexOf('/')-1);else if(/^validator::/.test(N)&&
|
|
110
|
+
await U(l[L],aa[L],n,c,S,ka)){++h;continue}/^:/.test(l[L])&&typeof N!='undefined'&&(new RegExp(N)).test(aa[L])&&(++h,c[F][l[L].substring(1)]=aa[L])}r=!0}for(var w in c[F])typeof n.requirements[w]!='undefined'&&l.indexOf(':'+w)<0&&(l[u]=':'+w,++u,aa[v]=c[F][w],++v,r||aa.length!==l.length||++V)}if(!r&&aa.length===l.length)for(;q<V;++q)aa[q]===l[q]?++h:h==q&&/:/.test(l[q])&&await U(l[q],aa[q],n,c,S,ka)&&++h;if(typeof n.requirements!='undefined'&&F==n.method.toLowerCase()&&!r&&h>=V)for(w=Object.getOwnPropertyNames(n.requirements),
|
|
111
111
|
v=0,l.join(',').match(/:[-_a-z0-9]+/g);v<w.length;){u=w[v];if(typeof n.param[u]=='undefined'&&/^validator::/i.test(n.requirements[u])){if(l.length!=aa.length)break;var K=l.join(',').match(/:[-_a-z0-9]+/g);let L=n.requirements[u];q={};N={};r={};try{N=JSON.parse(L.split(/::/).splice(1)[0].replace(/([^:"\s+](\w+)):/g,'"$1":').replace(/([^:"\s+](\w+))\s+:/g,'"$1":'))}catch(fa){throw fa;}if(typeof N.query!='undefined'&&typeof N.query.data!='undefined'){q=N.query.data;for(let fa in q)K.indexOf(q[fa])<0&&
|
|
112
112
|
delete q[fa];for(let fa=0,ma=l.length;fa<ma;fa++){if(!/^:/.test(l[fa]))continue;K=l[fa].replace(/^:/,'');K!=''&&typeof aa[fa]!='undefined'&&(q[K]=aa[fa],typeof c.params[K]=='undefined'&&(c.params[K]=aa[fa]))}}q=M(q,JSON.clone(c[F])||{});typeof q[u]=='undefined'&&(q[u]=null);r[u]=N;_validator=m?new C(q):new C('routing',q,null,r);if(N.count()==0){console.error('Route validation failed '+n.rule);--h;v++;continue}for(let fa in N)if(typeof N[fa].data!='undefined'&&(N[fa].data=q),r=Array.isArray(N[fa])?
|
|
113
113
|
await _validator[u][fa].apply(_validator[u],N[fa]):await _validator[u][fa](N[fa],c,S,ka),!r.isValid&&(--h,typeof r.error!='undefined'))throw r.error;}v++}g.past=h===V?!0:!1;g.past&&(c.routing=Y(n,c[F]),g.request=c);return g},U=async function(n,l,c,S,ka,aa){var v=-1,u=n.match(/:\w+/g);v=new RegExp(n,'g');var V=null,h=null,g=null;V=!1;var q=V=h=h=null,F=null,N=S.method.toLowerCase();if(!u.length)return!1;c.param.path&&v.test(c.param.path)&&(c.param.path=c.param.path.replace(v,l));c.param.namespace&&
|
|
@@ -543,6 +543,6 @@ function readyStateChange(){document.readyState==='complete'&&gina.ready()}
|
|
|
543
543
|
if(typeof window.gina=='undefined'){var gina={_global:{register:function(m){if(typeof m!='undefined')for(let E in m)window[E]=m[E]},unregister:function(m){if(typeof m=='undefined'||!Array.isArray(m))throw Error('`variables` needs to ba an array');for(let E=0,I=m.length;E<I;E++)delete window[m[E]]},initialized:[]},ready:function(m,E){readyFired?setTimeout(function(){m(E)},1):(readyList.push({name:'anonymous',fn:m,ctx:E}),document.readyState==='complete'||!document.attachEvent&&document.readyState===
|
|
544
544
|
'interactive'?setTimeout(ready,1):readyEventHandlersInstalled||(document.addEventListener?(document.addEventListener('DOMContentLoaded',ready,!1),window.addEventListener('load',ready,!1)):(document.attachEvent('onreadystatechange',readyStateChange),window.attachEvent('onload',ready)),readyEventHandlersInstalled=!0))}};window.gina=gina}define('core',['require','gina'],function(m){m('gina')(window.gina)});require.config({packages:['gina']});require('vendor/engine.io core helpers/prototypes helpers/binding helpers/dateFormat gina/link gina/validator gina/popin gina/storage utils/dom utils/events utils/data utils/effects utils/polyfill lib/inherits lib/form-validator lib/collection lib/domain lib/routing'.split(' '));
|
|
545
545
|
function getDependencies(m,E){var I=new EventTarget,M=[{func:async function(C,A){A=A.url;var U=null,D=null,Y=null;try{U=await fetch(A),D=await U.text(),typeof m=='undefined'&&(m={}),typeof window.gina.config=='undefined'&&(m.config={}),m.config[C]=JSON.parse(D),I.dispatchEvent(new CustomEvent('deps.loaded',{detail:{data:D,error:Y,timestamp:new Date}}))}catch(n){Y=Error('[ROUTING] Could not load routing\n'+(n.stack||n.message||n)),I.dispatchEvent(new CustomEvent('deps.loaded',{detail:{data:null,error:Y,
|
|
546
|
-
timestamp:new Date}}))}},args:['routing',{url:(m&&m.config&&m.config.webroot||'/')+'_gina/assets/routing.json'}]}];I.addEventListener('deps.loaded',C=>{M.splice(0,1);M.length||E()});try{for(let C=0,A=M.length;C<A;C++)M[C].func.apply(null,M[C].args)}catch(C){console.error(C.stack|C.message|C)}}
|
|
546
|
+
timestamp:new Date}}))}},args:['routing',{url:(typeof window!=='undefined'&&window.__ginaWebroot||m&&m.config&&m.config.webroot||'/')+'_gina/assets/routing.json'}]}];I.addEventListener('deps.loaded',C=>{M.splice(0,1);M.length||E()});try{for(let C=0,A=M.length;C<A;C++)M[C].func.apply(null,M[C].args)}catch(C){console.error(C.stack|C.message|C)}}
|
|
547
547
|
for(var tags=document.getElementsByTagName('script'),t=0,len=tags.length;t<len;++t)if(/(gina\.min\.js|gina\.js)/.test(tags[t].getAttribute('src'))){tags[t].onload=function(m){console.debug('Core Gina loaded !');getDependencies(gina,function(){if(window.onGinaLoaded)var E=window.onGinaLoaded;document.addEventListener?document.addEventListener('ginaloaded',function(I){window.gina=I.detail;E(I.detail)}):document.attachEvent&&document.attachEvent('ginaloaded',function(I){window.gina=I.detail;E(I.detail)})})}();
|
|
548
548
|
break};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
window.originalContext=null;
|
|
1
|
+
window.originalContext=null;window.__ginaWebroot='{{ page.environment.webroot }}';
|
|
2
2
|
window.onGinaLoaded=function(b){if(!b)return!1;if(b.isFrameworkLoaded)return!0;var e={bundle:'{{ page.environment.bundle }}',env:'{{ page.environment.env }}',envIsDev:/^true$/.test('{{ page.environment.envIsDev }}')?!0:!1,scope:'{{ page.environment.scope }}',scopeIsLocal:/^true$/.test('{{ page.environment.scopeIsLocal }}')?!0:!1,scopeIsProduction:/^true$/.test('{{ page.environment.scopeIsProduction }}')?!0:!1,isProxyHost:/^true$/.test('{{ page.environment.isProxyHost }}')?!0:!1,hostname:'{{ page.environment.hostname }}',
|
|
3
3
|
routing:JSON.parse(decodeURIComponent('{{ page.environment.routing }}')),reverseRouting:JSON.parse(decodeURIComponent('{{ page.environment.reverseRouting }}')),version:'{{ page.environment.version }}',webroot:'{{ page.environment.webroot }}',protocol:'{{ page.environment.protocol }}'};if(typeof b.config.routing!='undefined'&&b.config.routing.count()>0&&typeof b.config.reverseRouting!='undefined'&&!b.config.reverseRouting.count()||typeof b.config.routing!='undefined'&&b.config.routing.count()>0&&typeof b.config.reverseRouting==
|
|
4
4
|
'undefined'){var a=b.config.routing,d={};for(var f in a)if(/,/.test(a[f].url)){var h=a[f].url.split(/,/g),g=0;let c=h.length;for(;g<c;++g)d[h[g]]=f}else d[a[f].url]=f;b.config.reverseRouting=d}if(typeof b.config!='undefined')for(let c in b.config)e[c]=b.config[c];b.config=e;/^true$/i.test(e.g)&&(e.proxyHost=b.config.proxyHost='{{ page.environment.proxyHost }}',e.proxyHostname=b.config.proxyHostname='{{ page.environment.proxyHostname }}');b.session={id:'{{ page.data.session.id }}',originalTimeout:'{{ page.data.session.timeout }}',
|
|
Binary file
|