{"id":19774787,"url":"https://github.com/bigskysoftware/chill","last_synced_at":"2025-04-30T18:33:55.404Z","repository":{"id":37521534,"uuid":"488360799","full_name":"bigskysoftware/chill","owner":"bigskysoftware","description":"Chill Platform","archived":false,"fork":false,"pushed_at":"2024-04-05T16:09:20.000Z","size":527,"stargazers_count":22,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-13T16:14:34.149Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bigskysoftware.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-05-03T20:56:22.000Z","updated_at":"2024-01-17T11:19:24.000Z","dependencies_parsed_at":"2023-10-02T03:25:44.631Z","dependency_job_id":"3e8ea640-c37a-4752-a14d-db48233ff9cd","html_url":"https://github.com/bigskysoftware/chill","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigskysoftware%2Fchill","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigskysoftware%2Fchill/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigskysoftware%2Fchill/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigskysoftware%2Fchill/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bigskysoftware","download_url":"https://codeload.github.com/bigskysoftware/chill/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224219441,"owners_count":17275477,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T05:13:53.445Z","updated_at":"2024-11-12T05:13:54.073Z","avatar_url":"https://github.com/bigskysoftware.png","language":"Java","funding_links":[],"categories":["开发框架"],"sub_categories":[],"readme":"# Chill PL\n\nThe Chill Platform is a Java web and cloud application development platform.  It takes a different approach than most\nother java web frameworks in that it:\n\n* Provides complete out-of-the-box infrastructure for building cloud-based web applications, including authentication \n  and background job support\n* Minimizes the amount of architecture that application builders need to deal with\n* Favors code over configuration files or conventions, surfacing configuration hooks rather than relying on files or \n  implicit mappings\n\nChill takes advantage of many of the great, light-weight java projects available today including:\n\n* The Javalin Web Framework\n* The JobRunr Background Job Processor\n* Picocli for command line processing\n* HikariCP for connection pooling\n* Jedis for working with Redis\n\n## High-Level Architecture\n\nChill follows the web/worker model popularized by Heroku:\n\n* Web nodes handle web requests\n* Worker nodes handle background jobs\n\nThis allows you to scale the web infrastructure and the background job infrastructure independently.  At dev time,\na node will act as both a web node and a worker node, making it easy to develop.\n\nChill integrates standard cloud technologies to make developing applications easy:\n\n* Redis is used heavily for job scheduling, session management, RPC implementation, etc.\n* A simple wrapper around the S3 API is used for cloud file management\n* A simple layer on top of JDBC for RDBMS access\n\nFor all of these resources, Chill PL provides a default implementation if none is specified, which allows you to\nspin up a development server or run tests without any additional software installation.\n\nChill PL aims to produce a *single \"fat\" jar* as the final project for Chill-based applications, making deployment and\napplication launching very easy.\n\nChill PL uses Maven as a build tool, but tries to minimize the use of it, relying on it mainly for dependency resolution.\nMaven is \"the standard\" and works well with many IDEs and tools, but Chill PL tries to provide command\nline tools for application management tasks, rather than relying on Maven infrastructure.\n\n## Chill PL Specific Technologies\n\nChill PL leverages existing java libraries where it makes sense, but it also includes a significant number of modules\nthat provide functionality to complete the platform:\n\n* ChillRecord - A micro-ORM for working with databases, inspired by ActiveRecord, Mongoid and other ORMs\n* ChillMigrations - A simple system for managing migrations (database mutations) in your system\n* ChillUtils - A collection of quality of life improvements for java development, including `TheMissingUtil` and `NiceList`\n* ChillLog - A pluggable logging adapter that can be wired into whatever your preferred logging infrastructure is\n* ChillScript - A hypertalk-inspired scripting language for scripting in your Chill applications\n* ChillTemplates - ChillScript-based templates for building first-class hypermedia applications\n* ChillRoutes - An extension to the standard Javalin routing infrastructure\n* ChillHelper - A mechanism for adding \"helper\" functions for use in your web templates, inspired by Rails\n* ChillEnv - A mechanism for flexibly resolving environment variables in a clear and obvious manner\n* ChillRPC - A mechanism calling and servicing Remote Procedure Calls (RPC) via Redis\n\n### ChillRecord\n\nChillRecord is a micro-ORM that lives on top of JDBC.  It is insipred by ActiveRecord, Mongoid and many other simple\nORMs.  It tries to stay \"close to the metal\" with respect to JDBC, and not get in the way too much, with a focus on\nthings like validation life cycle events, rather than an elaborate OR mapping layer.\n\nAlso somewhat uniquely, ChillRecord relies on \"inline code generation\": ChillRecord domain objects include a main\nmethod that will generate the boilerplate getters and setters for the class, based on the fields declared on it.\nThis is a novel way of dealing with the difficulty of meta-programming infrastructure on the JVM.  It takes a bit\nto get used to, but once you do you will find it very easy to work with.\n\nHere is an example ChillRecord:\n\n```java\npublic class Vehicle extends ChillRecord {\n\n    ChillField\u003cLong\u003e id = pk(\"id\");\n    ChillField\u003cTimestamp\u003e createdAt = createdAt(\"created_at\");\n    ChillField\u003cTimestamp\u003e updatedAt = updatedAt(\"updated_at\").optimisticLock();\n\n    ChillField\u003cString\u003e make = field(\"make\", String.class);\n    ChillField\u003cString\u003e model = field(\"model\", String.class);\n    ChillField\u003cString\u003e uuid = uuid(\"uuid\");\n\n    ChillField\u003cInteger\u003e year = field(\"year\", Integer.class);\n\n    FK\u003cVehicle, User\u003e user = fk(\"user_id\", User.class);\n\n    //region chill.Record GENERATED CODE\n\n    public Vehicle createOrThrow(){\n        if(!create()){\n            throw new chill.db.ChillValidation.ValidationException(getErrors());\n        }\n        return this;\n    }\n\n    public Vehicle saveOrThrow(){\n        if(!save()){\n            throw new chill.db.ChillValidation.ValidationException(getErrors());\n        }\n        return this;\n    }\n\n    public Vehicle firstOrCreateOrThrow(){\n        return (Vehicle) firstOrCreateImpl();\n    }\n\n    @chill.db.ChillRecord.Generated public java.lang.Long getId() {\n        return id.get();\n    }\n\n    @chill.db.ChillRecord.Generated public java.sql.Timestamp getCreatedAt() {\n        return createdAt.get();\n    }\n\n    // ... getters/setter omitted\n \n    public static final chill.db.ChillRecord.Finder\u003cVehicle\u003e find = finder(Vehicle.class);\n\n    //endregion\n\n    public static void main(String[] args) {\n        codeGen();\n    }\n\n}\n```\n\nThis class consists of three regions:\n\n* In the first region, `ChillField`s are declared on the class.  This tells Chill how to map this class to an underlying\n  database table.  This is the source of truth for the mapping between the class and the DB: there is no other config file!\n* The second region begins with ``//region chill.Record GENERATED CODE``.  This is the generated code for the class and\n  includes getters/setters for all the fields, a static `find` field for finding things in the database, etc.  Note that\n  most editors will allow you to collapse this region, which is nice because it's all boilerplate anyway.\n* The final section is the code generator, which is a `main()` method on the record itself.  This method simply calls the\n  `codeGen()` method, which generates the code for the current model class, and is found on all model classes.  When you\n  add or remove fields, you simply run this main method and copy and paste the generated code into the second region.\n  note that if you decide to explicitly code a getter or setter, the code generator will detect that and will not generate\n  a getter or setter.  This allows you to cleanly develop your domain logic in the \"normal\" java manner without confusing\n  collisions or a complicated inheritance hierarchy.\n\n### Chill Migrations\n\nChill Migrations are database migrations, specified in the `model.Migrations` file.  Here is an example migrations file:\n\n```java\npackage model;\n\nimport chill.db.ChillMigrations;\n\npublic class Migrations extends ChillMigrations {\n\n    public final ChillMigration migration_2022_03_08_22_26_44 = new ChillMigration(\"create user\"){\n        protected void up() {\n            exec(\"\"\"\n                    CREATE TABLE user (\n                                  id INT AUTO_INCREMENT PRIMARY KEY,\n                                  created_at TIMESTAMP,\n                                  updated_at TIMESTAMP,\n                                  email VARCHAR(250) DEFAULT NULL,\n                                  password VARCHAR(250) DEFAULT NULL,\n                                  uuid VARCHAR(250) DEFAULT NULL\n                                );\n                    \"\"\");\n        }\n        protected void down() {\n            exec(\"DROP TABLE user\");\n        }\n    };\n\n    public static void main(String[] args) {\n        generateNewMigration();\n    }\n}\n```\n\nA `model.Migrations` file consists of a series of migrations specified as fields of type `ChillMigration`.  Each `ChillMigration`\nhas an `up()` and `down()` method in which is applies and rolls back changes to the underlying database.  SQL is the \nprimary mechanism for mutating the database, but you can also run domain logic as well: it's just java code!\n\nMigrations can be applied to a database in two ways:\n\n* via a command line: `$ java jar MyApp.jar --migrations up:*`\n* via a migrations console: `$ java jar MyApp.jar --migrations`\n\n### ChillUtils\n\nChill provides many \"quality of life\" improvements for java developers through the `chill.util` package.  In particular,\n`TheMissingUtils` provides a number of useful methods for day-to-day java coding:\n\n* `forceThrow()` and `safely()` allows you to force checked exceptions to be thrown as unchecked exceptions to avoid\n  checked exception hell.\n* `time()` can time an operation for you\n* `join()` can join a string on given a delimiter\n\nMany of these features are small and exist scattered around the various Java libraries, but `TheMissingUtils` centralizes\nthem into one place and makes them easy to find.\n\nAnother quality of life improvement is `chill.util.NiceList` which extends `java.util.List` and provides many functions found on \nthe java Streams objects, without necessitating going through that library.  `NiceList` is used extensively in other\nchill packages to make life easier for you.\n\n### Chill Logging\n\nChill logging is Yet Another Logging Facade with a simple and easy plugin point, `ChillLogs.setAdapter()` that allows\nyou to route logs to whatever backend logging framework you prefer.\n\nBy default, Chill Apps will set things up so the default logging is done to standard out at level `INFO` but toggleable\non a per-user basis to `DEBUG` when you need to troubleshoot a particular account.\n\nThis behavior is easy to override in your own application.\n\n### ChillScript\n\nChillScript is a hypertalk-inspired dynamically typed scripting language for Chill applications:\n\n```applescript\n  set lst to [1, 2, 3]\n  for num in lst\n    System.out.println(num)\n  end\n```\n\nThe main focus of Chill PL is on *java* development, but a dynamic scripting language comes in useful in a few places:\n\n* You can start a console repl (inspired by the Rails console) that allows you to work with your application dynamically\n* You can create maintenance scripts, etc. in the language\n* It is used in the templating system, `ChillTemplates`, discussed below\n\n### ChillTemplates\n\nChillTemplates are the Server-Side Rendering (SSR) templating library for Chill Applications.  They rely on ChillScript\nand should look familiar:\n\n```html\n#layout /layout/layout.html\n\n\u003csection\u003e\n    \u003ch3\u003eContacts\u003c/h3\u003e\n    #for contact in current_user.contacts\n      \u003cdiv\u003e\u003ca href=\"/contacts/${contact.uuid}\"\u003e${contact.name}\u003c/a\u003e\u003c/div\u003e\n    #end\n    \u003cdiv\u003e\n        \u003ca href=\"/contacts/new\"\u003eNew Contact\u003c/a\u003e\n    \u003c/div\u003e\n\u003c/section\u003e\n```\n\nYou can see that ChillTemplates use `#` to start directives and `${}` for embedding expressions.\n\nHere we see a template that specifies layout for the current template, using the `#layout` directive and then\niterates over a list of contacts using the `#for` directive.\n\nThe name of the contact is embedded in a link via a familiar `${contact.name}` syntax.  Expressions are HTML escaped by\ndefault.\n\n### ChillRoutes\n\nChill routes is a wrapper around the Javalin web framework.  Like Javalin, it allows you to specify routes in a \nsemi-declarative manner in a `web.web.Routes` file:\n\n```java\npackage web;\n\npublic class web.Routes extends ChillRoutes {\n\n  public void init() {\n\n    //====================================================\n    //  CORE ROUTES\n    //====================================================\n\n    get(\"/\", () -\u003e render(\"index.html\"));\n\n    // include another routes file\n    include(OtherRoutes.class);\n    \n  }\n  \n}\n```\n\nYou can see here we include another routes file, allowing us to group our HTTP routes together in an organized manner.\n\n### ChillHelper\n\nChillHelper allows you to surface helper methods in your views, via the `web.Helper` class:\n\n```java\npackage web;\n\nimport chill.web.ChillHelper;\nimport chill.web.macros.FormMacros;\n\npublic class Helper extends ChillHelper {\n    {\n        include(FormHelper.class);\n    }\n\n    public static String exampleHelperMethod() {\n       return \"Here is an example helper!\";\n    }\n}\n```\n\nStatic methods found in the helper class will be automatically available within templates.  You can include other helper\nclasses via the `include()` method.\n\n### ChillEnv\n\nThe `ChillEnv` class resolves environment variables against config files (`config/chill.toml`), environment variables,\nor manual overrides.  It will print out the state of environment variables on system startup:\n\n```\nINFO  [2022-04-14T13:32:37.696369017] - Chill Environment: \nINFO  [2022-04-14T13:32:37.706742681] -     MODE=DEV (source:Manually Set)\nINFO  [2022-04-14T13:32:37.706985949] -     PORT=8800 (source:Default Value)\nINFO  [2022-04-14T13:32:37.707148326] -     DB_URL=j0dbc:h2:file:./db/demo;DB_CLOSE_DELAY=-1;CASE_INSENSITIVE_IDENTIFIERS=true (source:TOML file)\nINFO  [2022-04-14T13:32:37.707297615] -     DB_DRIVER=org.h2.Driver (source:TOML file)\nINFO  [2022-04-14T13:32:37.707440319] -     DB_USERNAME=null \u003cunset\u003e\nINFO  [2022-04-14T13:32:37.707576879] -     DB_PASSWORD=null \u003cunset\u003e\nINFO  [2022-04-14T13:32:37.707724069] -     DB_CONNECTION_POOL_CONFIG=null \u003cunset\u003e\nINFO  [2022-04-14T13:32:37.707866529] -     REDIS_URL=localhost (source:Default Value)\nINFO  [2022-04-14T13:32:37.707995548] -     S3.REGION=null \u003cunset\u003e\nINFO  [2022-04-14T13:32:37.708096770] -     S3.ACCESS_KEY=null \u003cunset\u003e\nINFO  [2022-04-14T13:32:37.708238307] -     S3.SECRET_KEY=null \u003cunset\u003e\n```\n\n### ChillRPC\n\nChillRPC allows you to register and invoke RPC handlers:\n\n```java\n    RPC.implement(SampleInterface.class).with(new SampleImpl())\n    var rpcInterface = RPC.make(SampleInterface.class);\n    int oneAdded = rpcInterface.addOne(41);\n```\n\nRPC functions will be invoked through Redis, so no URL end point configuration is required.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbigskysoftware%2Fchill","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbigskysoftware%2Fchill","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbigskysoftware%2Fchill/lists"}