odac 0.9.0

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.
Files changed (213) hide show
  1. package/.editorconfig +21 -0
  2. package/.github/workflows/auto-pr-description.yml +49 -0
  3. package/.github/workflows/release.yml +32 -0
  4. package/.github/workflows/test-coverage.yml +58 -0
  5. package/.husky/pre-commit +2 -0
  6. package/.kiro/steering/code-style.md +56 -0
  7. package/.kiro/steering/product.md +20 -0
  8. package/.kiro/steering/structure.md +77 -0
  9. package/.kiro/steering/tech.md +87 -0
  10. package/.prettierrc +10 -0
  11. package/.releaserc.js +134 -0
  12. package/AGENTS.md +84 -0
  13. package/CHANGELOG.md +181 -0
  14. package/CODE_OF_CONDUCT.md +83 -0
  15. package/CONTRIBUTING.md +63 -0
  16. package/LICENSE +661 -0
  17. package/README.md +57 -0
  18. package/SECURITY.md +26 -0
  19. package/bin/candy +10 -0
  20. package/bin/candypack +10 -0
  21. package/cli/index.js +3 -0
  22. package/cli/src/Cli.js +348 -0
  23. package/cli/src/Connector.js +93 -0
  24. package/cli/src/Monitor.js +416 -0
  25. package/core/Candy.js +87 -0
  26. package/core/Commands.js +239 -0
  27. package/core/Config.js +1094 -0
  28. package/core/Lang.js +52 -0
  29. package/core/Log.js +43 -0
  30. package/core/Process.js +26 -0
  31. package/docs/backend/01-overview/01-whats-in-the-candy-box.md +9 -0
  32. package/docs/backend/01-overview/02-super-handy-helper-functions.md +9 -0
  33. package/docs/backend/01-overview/03-development-server.md +79 -0
  34. package/docs/backend/02-structure/01-typical-project-layout.md +39 -0
  35. package/docs/backend/03-config/00-configuration-overview.md +214 -0
  36. package/docs/backend/03-config/01-database-connection.md +60 -0
  37. package/docs/backend/03-config/02-static-route-mapping-optional.md +20 -0
  38. package/docs/backend/03-config/03-request-timeout.md +11 -0
  39. package/docs/backend/03-config/04-environment-variables.md +227 -0
  40. package/docs/backend/03-config/05-early-hints.md +352 -0
  41. package/docs/backend/04-routing/01-basic-page-routes.md +28 -0
  42. package/docs/backend/04-routing/02-controller-less-view-routes.md +43 -0
  43. package/docs/backend/04-routing/03-api-and-data-routes.md +20 -0
  44. package/docs/backend/04-routing/04-authentication-aware-routes.md +48 -0
  45. package/docs/backend/04-routing/05-advanced-routing.md +14 -0
  46. package/docs/backend/04-routing/06-error-pages.md +101 -0
  47. package/docs/backend/04-routing/07-cron-jobs.md +149 -0
  48. package/docs/backend/05-controllers/01-how-to-build-a-controller.md +17 -0
  49. package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +20 -0
  50. package/docs/backend/05-controllers/03-controller-classes.md +93 -0
  51. package/docs/backend/05-forms/01-custom-forms.md +395 -0
  52. package/docs/backend/05-forms/02-automatic-database-insert.md +297 -0
  53. package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +96 -0
  54. package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +40 -0
  55. package/docs/backend/07-views/01-the-view-directory.md +73 -0
  56. package/docs/backend/07-views/02-rendering-a-view.md +179 -0
  57. package/docs/backend/07-views/03-template-syntax.md +181 -0
  58. package/docs/backend/07-views/03-variables.md +328 -0
  59. package/docs/backend/07-views/04-request-data.md +231 -0
  60. package/docs/backend/07-views/05-conditionals.md +290 -0
  61. package/docs/backend/07-views/06-loops.md +353 -0
  62. package/docs/backend/07-views/07-translations.md +358 -0
  63. package/docs/backend/07-views/08-backend-javascript.md +398 -0
  64. package/docs/backend/07-views/09-comments.md +297 -0
  65. package/docs/backend/08-database/01-database-connection.md +99 -0
  66. package/docs/backend/08-database/02-using-mysql.md +322 -0
  67. package/docs/backend/09-validation/01-the-validator-service.md +424 -0
  68. package/docs/backend/10-authentication/01-user-logins-with-authjs.md +53 -0
  69. package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +55 -0
  70. package/docs/backend/10-authentication/03-register.md +134 -0
  71. package/docs/backend/10-authentication/04-candy-register-forms.md +676 -0
  72. package/docs/backend/10-authentication/05-session-management.md +159 -0
  73. package/docs/backend/10-authentication/06-candy-login-forms.md +596 -0
  74. package/docs/backend/11-mail/01-the-mail-service.md +42 -0
  75. package/docs/backend/12-streaming/01-streaming-overview.md +300 -0
  76. package/docs/backend/13-utilities/01-candy-var.md +504 -0
  77. package/docs/frontend/01-overview/01-introduction.md +146 -0
  78. package/docs/frontend/02-ajax-navigation/01-quick-start.md +608 -0
  79. package/docs/frontend/02-ajax-navigation/02-configuration.md +370 -0
  80. package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +519 -0
  81. package/docs/frontend/03-forms/01-form-handling.md +420 -0
  82. package/docs/frontend/04-api-requests/01-get-post.md +443 -0
  83. package/docs/frontend/05-streaming/01-client-streaming.md +163 -0
  84. package/docs/index.json +452 -0
  85. package/docs/server/01-installation/01-quick-install.md +19 -0
  86. package/docs/server/01-installation/02-manual-installation-via-npm.md +9 -0
  87. package/docs/server/02-get-started/01-core-concepts.md +7 -0
  88. package/docs/server/02-get-started/02-basic-commands.md +57 -0
  89. package/docs/server/02-get-started/03-cli-reference.md +276 -0
  90. package/docs/server/02-get-started/04-cli-quick-reference.md +102 -0
  91. package/docs/server/03-service/01-start-a-new-service.md +57 -0
  92. package/docs/server/03-service/02-delete-a-service.md +48 -0
  93. package/docs/server/04-web/01-create-a-website.md +36 -0
  94. package/docs/server/04-web/02-list-websites.md +9 -0
  95. package/docs/server/04-web/03-delete-a-website.md +29 -0
  96. package/docs/server/05-subdomain/01-create-a-subdomain.md +32 -0
  97. package/docs/server/05-subdomain/02-list-subdomains.md +33 -0
  98. package/docs/server/05-subdomain/03-delete-a-subdomain.md +41 -0
  99. package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +34 -0
  100. package/docs/server/07-mail/01-create-a-mail-account.md +23 -0
  101. package/docs/server/07-mail/02-delete-a-mail-account.md +20 -0
  102. package/docs/server/07-mail/03-list-mail-accounts.md +20 -0
  103. package/docs/server/07-mail/04-change-account-password.md +23 -0
  104. package/eslint.config.mjs +120 -0
  105. package/framework/index.js +4 -0
  106. package/framework/src/Auth.js +309 -0
  107. package/framework/src/Candy.js +81 -0
  108. package/framework/src/Config.js +79 -0
  109. package/framework/src/Env.js +60 -0
  110. package/framework/src/Lang.js +57 -0
  111. package/framework/src/Mail.js +83 -0
  112. package/framework/src/Mysql.js +575 -0
  113. package/framework/src/Request.js +301 -0
  114. package/framework/src/Route/Cron.js +128 -0
  115. package/framework/src/Route/Internal.js +439 -0
  116. package/framework/src/Route.js +455 -0
  117. package/framework/src/Server.js +15 -0
  118. package/framework/src/Stream.js +163 -0
  119. package/framework/src/Token.js +37 -0
  120. package/framework/src/Validator.js +271 -0
  121. package/framework/src/Var.js +211 -0
  122. package/framework/src/View/EarlyHints.js +190 -0
  123. package/framework/src/View/Form.js +600 -0
  124. package/framework/src/View.js +513 -0
  125. package/framework/web/candy.js +838 -0
  126. package/jest.config.js +22 -0
  127. package/locale/de-DE.json +80 -0
  128. package/locale/en-US.json +79 -0
  129. package/locale/es-ES.json +80 -0
  130. package/locale/fr-FR.json +80 -0
  131. package/locale/pt-BR.json +80 -0
  132. package/locale/ru-RU.json +80 -0
  133. package/locale/tr-TR.json +85 -0
  134. package/locale/zh-CN.json +80 -0
  135. package/package.json +86 -0
  136. package/server/index.js +5 -0
  137. package/server/src/Api.js +88 -0
  138. package/server/src/DNS.js +940 -0
  139. package/server/src/Hub.js +535 -0
  140. package/server/src/Mail.js +571 -0
  141. package/server/src/SSL.js +180 -0
  142. package/server/src/Server.js +27 -0
  143. package/server/src/Service.js +248 -0
  144. package/server/src/Subdomain.js +64 -0
  145. package/server/src/Web/Firewall.js +170 -0
  146. package/server/src/Web/Proxy.js +134 -0
  147. package/server/src/Web.js +451 -0
  148. package/server/src/mail/imap.js +1091 -0
  149. package/server/src/mail/server.js +32 -0
  150. package/server/src/mail/smtp.js +786 -0
  151. package/test/cli/Cli.test.js +36 -0
  152. package/test/core/Candy.test.js +234 -0
  153. package/test/core/Commands.test.js +538 -0
  154. package/test/core/Config.test.js +1435 -0
  155. package/test/core/Lang.test.js +250 -0
  156. package/test/core/Process.test.js +156 -0
  157. package/test/framework/Route.test.js +239 -0
  158. package/test/framework/View/EarlyHints.test.js +282 -0
  159. package/test/scripts/check-coverage.js +132 -0
  160. package/test/server/Api.test.js +647 -0
  161. package/test/server/Client.test.js +338 -0
  162. package/test/server/DNS.test.js +2050 -0
  163. package/test/server/DNS.test.js.bak +2084 -0
  164. package/test/server/Log.test.js +73 -0
  165. package/test/server/Mail.account.test_.js +460 -0
  166. package/test/server/Mail.init.test_.js +411 -0
  167. package/test/server/Mail.test_.js +1340 -0
  168. package/test/server/SSL.test_.js +1491 -0
  169. package/test/server/Server.test.js +765 -0
  170. package/test/server/Service.test_.js +1127 -0
  171. package/test/server/Subdomain.test.js +440 -0
  172. package/test/server/Web/Firewall.test.js +175 -0
  173. package/test/server/Web.test_.js +1562 -0
  174. package/test/server/__mocks__/acme-client.js +17 -0
  175. package/test/server/__mocks__/bcrypt.js +50 -0
  176. package/test/server/__mocks__/child_process.js +389 -0
  177. package/test/server/__mocks__/crypto.js +432 -0
  178. package/test/server/__mocks__/fs.js +450 -0
  179. package/test/server/__mocks__/globalCandy.js +227 -0
  180. package/test/server/__mocks__/http-proxy.js +105 -0
  181. package/test/server/__mocks__/http.js +575 -0
  182. package/test/server/__mocks__/https.js +272 -0
  183. package/test/server/__mocks__/index.js +249 -0
  184. package/test/server/__mocks__/mail/server.js +100 -0
  185. package/test/server/__mocks__/mail/smtp.js +31 -0
  186. package/test/server/__mocks__/mailparser.js +81 -0
  187. package/test/server/__mocks__/net.js +369 -0
  188. package/test/server/__mocks__/node-forge.js +328 -0
  189. package/test/server/__mocks__/os.js +320 -0
  190. package/test/server/__mocks__/path.js +291 -0
  191. package/test/server/__mocks__/selfsigned.js +8 -0
  192. package/test/server/__mocks__/server/src/mail/server.js +100 -0
  193. package/test/server/__mocks__/server/src/mail/smtp.js +31 -0
  194. package/test/server/__mocks__/smtp-server.js +106 -0
  195. package/test/server/__mocks__/sqlite3.js +394 -0
  196. package/test/server/__mocks__/testFactories.js +299 -0
  197. package/test/server/__mocks__/testHelpers.js +363 -0
  198. package/test/server/__mocks__/tls.js +229 -0
  199. package/watchdog/index.js +3 -0
  200. package/watchdog/src/Watchdog.js +156 -0
  201. package/web/config.json +5 -0
  202. package/web/controller/page/about.js +27 -0
  203. package/web/controller/page/index.js +34 -0
  204. package/web/package.json +18 -0
  205. package/web/public/assets/css/style.css +1835 -0
  206. package/web/public/assets/js/app.js +96 -0
  207. package/web/route/www.js +19 -0
  208. package/web/skeleton/main.html +22 -0
  209. package/web/view/content/about.html +65 -0
  210. package/web/view/content/home.html +205 -0
  211. package/web/view/footer/main.html +11 -0
  212. package/web/view/head/main.html +5 -0
  213. package/web/view/header/main.html +14 -0
package/.editorconfig ADDED
@@ -0,0 +1,21 @@
1
+ # EditorConfig is awesome: https://EditorConfig.org
2
+
3
+ # top-most EditorConfig file
4
+ root = true
5
+
6
+ [*]
7
+ indent_style = space
8
+ indent_size = 2
9
+ end_of_line = lf
10
+ charset = utf-8
11
+ trim_trailing_whitespace = true
12
+ insert_final_newline = true
13
+
14
+ [*.js]
15
+ quote_type = single
16
+
17
+ [*.json]
18
+ indent_size = 2
19
+
20
+ [*.md]
21
+ trim_trailing_whitespace = false
@@ -0,0 +1,49 @@
1
+ name: Auto-generate PR Description
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened]
6
+ branches:
7
+ - main
8
+
9
+ jobs:
10
+ update-pr-description:
11
+ runs-on: ubuntu-latest
12
+ # Only run for PRs from `dev` to `main`
13
+ if: github.head_ref == 'dev' && github.base_ref == 'main'
14
+ permissions:
15
+ pull-requests: write
16
+ contents: read
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v4
20
+ with:
21
+ # Fetch all history for all branches and tags to get the commit messages
22
+ fetch-depth: 0
23
+
24
+ - name: Generate PR Body
25
+ id: generate_body
26
+ run: |
27
+ # Get commit messages from the PR's commits
28
+ COMMITS=$(git log origin/${{ github.base_ref }}..origin/${{ github.head_ref }} --pretty=format:"* %s")
29
+ # Set the multiline output for the next step
30
+ {
31
+ echo 'body<<EOF'
32
+ echo "This PR includes the following changes:"
33
+ echo ""
34
+ echo "$COMMITS"
35
+ echo 'EOF'
36
+ } >> "$GITHUB_OUTPUT"
37
+
38
+ - name: Update PR Title and Body
39
+ uses: actions/github-script@v7
40
+ with:
41
+ github-token: ${{ secrets.GITHUB_TOKEN }}
42
+ script: |
43
+ github.rest.pulls.update({
44
+ owner: context.repo.owner,
45
+ repo: context.repo.repo,
46
+ pull_number: context.issue.number,
47
+ title: 'Sync `dev` to `main`',
48
+ body: `${{ steps.generate_body.outputs.body }}`
49
+ });
@@ -0,0 +1,32 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths-ignore:
8
+ - 'CHANGELOG.md'
9
+ - 'package.json'
10
+ workflow_dispatch:
11
+
12
+ jobs:
13
+ release:
14
+ name: Release
15
+ runs-on: ubuntu-latest
16
+ if: "!contains(github.event.head_commit.message, 'CandyPack v') || github.event_name == 'workflow_dispatch'"
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v3
20
+ with:
21
+ fetch-depth: 0
22
+ - name: Setup Node.js
23
+ uses: actions/setup-node@v3
24
+ with:
25
+ node-version: '20'
26
+ - name: Install dependencies
27
+ run: npm install
28
+ - name: Release
29
+ env:
30
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
32
+ run: npx semantic-release
@@ -0,0 +1,58 @@
1
+ name: Test Coverage
2
+
3
+ on:
4
+ push:
5
+ branches: [main, dev]
6
+ paths:
7
+ - '**/*.js'
8
+ - 'package.json'
9
+ - 'jest.config.js'
10
+ pull_request:
11
+ branches: [main, dev]
12
+ paths:
13
+ - '**/*.js'
14
+ - 'package.json'
15
+ - 'jest.config.js'
16
+
17
+ jobs:
18
+ test:
19
+ runs-on: ubuntu-latest
20
+
21
+ strategy:
22
+ matrix:
23
+ node-version: [18.x, 22.x]
24
+
25
+ steps:
26
+ - name: Checkout code
27
+ uses: actions/checkout@v4
28
+
29
+ - name: Setup Node.js ${{ matrix.node-version }}
30
+ uses: actions/setup-node@v4
31
+ with:
32
+ node-version: ${{ matrix.node-version }}
33
+
34
+ - name: Install dependencies
35
+ run: npm install
36
+
37
+ - name: Run linter
38
+ run: npm run lint
39
+
40
+ - name: Run tests with coverage
41
+ run: npm test
42
+
43
+ - name: Upload coverage reports
44
+ if: matrix.node-version == '18.x'
45
+ uses: codecov/codecov-action@v3
46
+ with:
47
+ files: ./coverage/lcov.info
48
+ flags: unittests
49
+ name: codecov-umbrella
50
+ fail_ci_if_error: false
51
+
52
+ - name: Comment PR with coverage
53
+ if: github.event_name == 'pull_request' && matrix.node-version == '18.x'
54
+ uses: romeovs/lcov-reporter-action@v0.3.1
55
+ with:
56
+ lcov-file: ./coverage/lcov.info
57
+ github-token: ${{ secrets.GITHUB_TOKEN }}
58
+ delete-old-comments: true
@@ -0,0 +1,2 @@
1
+ npx lint-staged
2
+ node test/scripts/check-coverage.js
@@ -0,0 +1,56 @@
1
+ ---
2
+ inclusion: always
3
+ ---
4
+
5
+ # Code Style Guidelines
6
+
7
+ ## Comments
8
+
9
+ - **Language**: All code comments MUST be written in English
10
+ - **Minimalism**: Avoid unnecessary comments - write self-documenting code instead
11
+ - **When to comment**: Only add comments when the code's intent is not immediately clear from the code itself
12
+ - **What not to comment**:
13
+ - Obvious operations (e.g., `// Set variable` before `x = 5`)
14
+ - Code that explains itself through clear naming
15
+ - Redundant descriptions of what the code does
16
+
17
+ ## Examples
18
+
19
+ ### Bad (unnecessary comments):
20
+ ```javascript
21
+ // Get user email
22
+ const email = user.email
23
+
24
+ // Loop through items
25
+ for (const item of items) {
26
+ // Process item
27
+ processItem(item)
28
+ }
29
+ ```
30
+
31
+ ### Good (self-documenting):
32
+ ```javascript
33
+ const email = user.email
34
+
35
+ for (const item of items) {
36
+ processItem(item)
37
+ }
38
+ ```
39
+
40
+ ### Good (necessary comment):
41
+ ```javascript
42
+ // ACME protocol requires 30-second delay between retries
43
+ await sleep(30000)
44
+
45
+ // Workaround for MySQL connection pool bug in v2.3.0
46
+ if (connection.threadId === null) {
47
+ connection = await reconnect()
48
+ }
49
+ ```
50
+
51
+ ## General Principles
52
+
53
+ - Let the code speak for itself through clear variable and function names
54
+ - Use comments sparingly to explain "why" not "what"
55
+ - Keep comments concise and to the point
56
+ - Update or remove comments when code changes
@@ -0,0 +1,20 @@
1
+ # CandyPack Product Overview
2
+
3
+ CandyPack is a next-generation server and framework toolkit that combines hosting infrastructure with a web development framework. It's designed as a lightweight, zero-config solution for building and deploying modern web applications.
4
+
5
+ ## Core Components
6
+
7
+ - **Server**: Full-featured hosting platform with DNS, SSL, mail server (IMAP/SMTP), and multi-domain support
8
+ - **Backend**: Web application framework with routing, authentication, CSRF protection, and internationalization
9
+ - **Frontend**: Client-side framework (candy.js) with AJAX navigation, form handling, and API requests
10
+ - **CLI**: Command-line interface for server management and deployment
11
+ - **Watchdog**: Process monitoring and management system
12
+
13
+ ## Key Philosophy
14
+
15
+ - **Developer-first**: Zero-config approach, focus on code rather than infrastructure
16
+ - **Performance-oriented**: Lightweight and optimized for speed
17
+ - **Security-focused**: Built-in CSRF protection, SSL automation, secure defaults
18
+ - **Global-ready**: Multi-language support and internationalization built-in
19
+
20
+ The project follows AGPL-3.0 licensing and targets Node.js 18+ environments.
@@ -0,0 +1,77 @@
1
+ # Project Structure & Architecture
2
+
3
+ ## Directory Organization
4
+
5
+ ```
6
+ ├── bin/ # Executable binaries (candy, candypack)
7
+ ├── cli/ # Command-line interface
8
+ │ └── src/ # CLI implementation (Cli.js, Connector.js, Monitor.js)
9
+ ├── core/ # Core dependency injection system
10
+ ├── framework/ # Web framework implementation
11
+ │ ├── src/ # Framework modules (Auth, Route, Server, etc.)
12
+ │ └── web/ # Client-side JavaScript (candy.js)
13
+ ├── server/ # Server infrastructure
14
+ │ └── src/ # Server modules (DNS, SSL, Mail, Web, etc.)
15
+ ├── watchdog/ # Process monitoring system
16
+ ├── web/ # Template website (copied when creating new sites)
17
+ │ ├── controller/ # Template controllers
18
+ │ ├── package.json # Template package.json with {{domain}} placeholders
19
+ │ └── config.json # Template configuration
20
+ ├── docs/ # Documentation (backend, frontend & server)
21
+ │ ├── index.json # Documentation navigation structure
22
+ │ ├── backend/ # Backend documentation files
23
+ │ ├── frontend/ # Frontend documentation files
24
+ │ └── server/ # Server documentation files
25
+ ├── locale/ # Internationalization files
26
+ └── test/ # Jest test files
27
+ ```
28
+
29
+ ## Architecture Patterns
30
+
31
+ ### Dependency Injection (Core)
32
+
33
+ - **Global Candy**: Singleton registry pattern via `global.Candy`
34
+ - **Module Loading**: Dynamic require with `core()`, `cli()`, `server()`, `watchdog()` methods
35
+ - **Singleton Management**: Automatic instantiation and caching
36
+
37
+ ### Framework Pattern
38
+
39
+ - **Request Lifecycle**: Each request gets a fresh Candy instance with req/res context
40
+ - **Controller Pattern**: Simple function exports in `controller/` directories
41
+ - **Helper Functions**: Global shortcuts (`__()`, `abort()`, `return()`, etc.)
42
+
43
+ ### File Naming Conventions
44
+
45
+ - **PascalCase**: Class files and main modules (e.g., `Candy.js`, `Server.js`)
46
+ - **camelCase**: Utility functions and instances
47
+ - **lowercase**: Entry points (`index.js`)
48
+
49
+ ### Module Structure
50
+
51
+ - Each module can have an optional `init()` method for setup
52
+ - Framework modules receive Candy instance for request context
53
+ - Server modules are typically singletons for infrastructure
54
+
55
+ ### Web Template System
56
+
57
+ - **Template Directory**: `web/` serves as the template for new websites
58
+ - **Automatic Copying**: When creating a new site, entire `web/` directory is copied
59
+ - **Template Variables**: Files can contain placeholders like `{{domain}}` and `{{domain_original}}`
60
+ - **Post-Processing**: After copying, template variables are replaced with actual values
61
+ - **Template Files**:
62
+ - `package.json` - Contains domain placeholders for name and description
63
+ - `config.json` - Basic routing configuration
64
+ - `controller/` - Example controller implementations
65
+
66
+ ### Documentation System
67
+
68
+ - **Index File**: `docs/index.json` contains the navigation structure for all documentation
69
+ - **Adding New Docs**: When creating new documentation files, they MUST be added to `docs/index.json`
70
+ - **Language**: All documentation content must be written in English
71
+ - **Structure**: Documentation is organized into THREE sections only:
72
+ - `docs/server/` - Server infrastructure documentation (CLI, DNS, SSL, Mail)
73
+ - `docs/backend/` - Backend framework documentation (Controllers, Routing, Auth, Database)
74
+ - `docs/frontend/` - Frontend documentation (candy.js, AJAX navigation, Forms)
75
+ - **IMPORTANT**: There is NO `docs/framework/` directory - backend docs go in `docs/backend/`
76
+ - **File Organization**: Each section has folders with numbered prefixes (01-overview, 02-structure, etc.)
77
+ - **Navigation**: The index.json file defines the title and hierarchy shown in documentation site
@@ -0,0 +1,87 @@
1
+ # Technology Stack & Build System
2
+
3
+ ## Tech Stack
4
+
5
+ - **Runtime**: Node.js 18+ (required)
6
+ - **Language**: JavaScript (ES6+, CommonJS modules)
7
+ - **Database**: MySQL2, SQLite3 support
8
+ - **Security**: bcrypt, node-forge, ACME client for SSL
9
+ - **Mail**: Built-in SMTP/IMAP server with DKIM signing
10
+ - **Proxy**: HTTP proxy for multi-domain hosting
11
+ - **DNS**: Native DNS server implementation
12
+
13
+ ## Code Quality Tools
14
+
15
+ - **Linting**: ESLint with Prettier integration
16
+ - **Testing**: Jest with coverage reporting (no threshold enforcement)
17
+ - **Git Hooks**: Husky with pre-commit linting and test execution
18
+ - **Release**: Semantic Release with conventional commits
19
+ - **Test Check**: Automatic test execution on commit for changed files (pass/fail only)
20
+
21
+ ## Common Commands
22
+
23
+ ```bash
24
+ # Development
25
+ npm run lint # Run ESLint
26
+ npm run lint:fix # Fix linting issues automatically
27
+ npm test # Run Jest tests with coverage
28
+ npm run test:watch # Run tests in watch mode
29
+
30
+ # Release
31
+ npm run release # Semantic release (automated)
32
+
33
+ # Installation
34
+ curl -sL https://candypack.dev/install | bash # Quick install
35
+ npm install -g candypack # Manual install
36
+
37
+ # Git Hooks & CI/CD
38
+ # Pre-commit automatically runs:
39
+ # 1. lint-staged (ESLint + Prettier on staged files)
40
+ # 2. Test execution for changed core/ and server/ files (test/scripts/check-coverage.js)
41
+ # Note: Coverage is tracked but doesn't block commits - focus is on test pass/fail
42
+
43
+ # GitHub Actions (on PR to main/dev):
44
+ # 1. Runs all tests with coverage
45
+ # 2. Runs linter
46
+ # 3. Tests on Node.js 18.x and 22.x
47
+ # 4. Uploads coverage to Codecov
48
+ # 5. Comments PR with coverage report
49
+ ```
50
+
51
+ ## Code Style
52
+
53
+ - **Prettier Config**: No semicolons, single quotes, 140 char width, 2-space tabs
54
+ - **ESLint**: Separate configs for server/framework/web/browser contexts
55
+ - **Globals**: `Candy` and `__` are global variables across the codebase
56
+ - **Module System**: CommonJS (`require`/`module.exports`) for server-side code
57
+
58
+ ## Logging Standards
59
+
60
+ ### Server & Core Modules
61
+ - **Log Class**: Use `Candy.core('Log', false).init('ModuleName')` for all logging in `server/` and `core/` directories
62
+ - **Usage Pattern**:
63
+
64
+ ```javascript
65
+ const {log, error} = Candy.core('Log', false).init('ModuleName')
66
+
67
+ log('Info message')
68
+ log('Message with %s placeholder', 'value')
69
+ error('Error message', errorObject)
70
+ ```
71
+
72
+ - **CLI Mode**: Logs are automatically suppressed in CLI mode to avoid breaking the interface
73
+ - **Location**: Log class is in `core/Log.js` (also available via `server/src/Log.js` for backward compatibility)
74
+
75
+ ### Framework Modules
76
+ - **Console Logging**: Use `console.log()` and `console.error()` directly in `framework/` directory
77
+ - **Reason**: Framework runs in user's application context where Log class may not be available
78
+ - **Usage Pattern**:
79
+
80
+ ```javascript
81
+ console.log('[ModuleName] Info message')
82
+ console.error('[ModuleName] Error:', error.message)
83
+ ```
84
+
85
+ ### General Rule
86
+ - **Server/Core**: Always use Log class (never `console.log`)
87
+ - **Framework**: Always use `console.log` (Log class not guaranteed to be available)
package/.prettierrc ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "printWidth": 140,
5
+ "tabWidth": 2,
6
+ "trailingComma": "none",
7
+ "arrowParens": "avoid",
8
+ "bracketSpacing": false,
9
+ "endOfLine": "lf"
10
+ }
package/.releaserc.js ADDED
@@ -0,0 +1,134 @@
1
+ module.exports = {
2
+ branches: ['main'],
3
+ plugins: [
4
+ [
5
+ '@semantic-release/commit-analyzer',
6
+ {
7
+ preset: 'conventionalcommits'
8
+ }
9
+ ],
10
+ [
11
+ '@semantic-release/release-notes-generator',
12
+ {
13
+ preset: 'conventionalcommits',
14
+ writerOpts: {
15
+ transform: (c, context) => {
16
+ const commit = JSON.parse(JSON.stringify(c))
17
+
18
+ const map = {
19
+ feat: "✨ What's New",
20
+ fix: '🛠️ Fixes & Improvements',
21
+ perf: '⚡️ Performance Upgrades',
22
+ refactor: '⚙️ Engine Tuning',
23
+ docs: '📚 Documentation',
24
+ style: '🎨 Style',
25
+ test: '✅ Tests',
26
+ chore: '🔧 Maintenance & Cleanup',
27
+ build: '🏗️ Build',
28
+ ci: '🤖 CI'
29
+ }
30
+
31
+ commit.type = map[commit.type] || commit.type
32
+
33
+ const hide = ['🎨 Style', '🔧 Maintenance & Cleanup', '🏗️ Build', '🤖 CI', '✅ Tests']
34
+ if (!commit.type || hide.includes(commit.type)) return false
35
+
36
+ if (commit.scope === '*' || commit.scope === 'root') commit.scope = ''
37
+
38
+ if (commit.notes) {
39
+ commit.notes.forEach(n => {
40
+ n.title = '💥 BREAKING CHANGES'
41
+ })
42
+ }
43
+
44
+ if (commit.subject) {
45
+ // Find and extract PR number from the subject, e.g., "feat: new thing (#123)"
46
+ const prRegex = /\s\(#(\d+)\)$/
47
+ const prMatch = commit.subject.match(prRegex)
48
+ const prNumber = prMatch ? prMatch[1] : null
49
+
50
+ // If a PR number is found, remove it from the subject to avoid it appearing twice
51
+ if (prNumber) {
52
+ commit.subject = commit.subject.replace(prRegex, '')
53
+ }
54
+
55
+ let prLink = ''
56
+
57
+ // Get author name - prefer GitHub login if available
58
+ const email = commit.committer.email || commit.authorEmail || ''
59
+ const ghUserMatch = email.match(/^(?:\d+\+)?([a-zA-Z0-9-]+)@users\.noreply\.github\.com$/)
60
+ const ghUser = ghUserMatch ? ghUserMatch[1] : null
61
+
62
+ let attribution = ''
63
+ if (ghUser) attribution = `by @${ghUser}`
64
+
65
+ // Get PR link if a number was found
66
+ if (prNumber && context.host && context.owner && context.repository) {
67
+ const prUrl = `https://${context.host}/${context.owner}/${context.repository}/pull/${prNumber}`
68
+ const prLink = `[#${prNumber}](${prUrl})`
69
+ attribution = attribution ? `${attribution} in ${prLink}` : prLink
70
+ }
71
+
72
+ // Append the attribution string to the subject if we created one
73
+ // if (attribution && prLink) {
74
+ // commit.subject = `${commit.subject} ${attribution} in ${prLink}`;
75
+ // } else if (prLink) {
76
+ // commit.subject = `${commit.subject} ${prLink}`;
77
+ // } else if (attribution) {
78
+ // commit.subject = `${commit.subject} ${attribution}`;
79
+ // }
80
+ }
81
+ return commit
82
+ },
83
+ groupBy: 'type',
84
+ commitGroupsSort: (a, b) => (a.title > b.title ? 1 : -1),
85
+ commitsSort: ['scope', 'subject'],
86
+ headerPartial: '',
87
+ commitPartial: '- {{#if scope}}**{{scope}}:** {{/if}}{{subject}}\n',
88
+ mainTemplate: `
89
+ {{#if commitGroups}}
90
+ {{#each commitGroups}}
91
+ ### {{title}}
92
+
93
+ {{#each commits}}
94
+ {{> commit root=@root}}
95
+ {{/each}}
96
+
97
+ {{/each}}
98
+ {{/if}}
99
+
100
+ {{#if noteGroups}}
101
+ {{#each noteGroups}}
102
+ ### {{title}}
103
+
104
+ {{#each notes}}
105
+ - {{text}}
106
+ {{/each}}
107
+
108
+ {{/each}}
109
+ {{/if}}
110
+
111
+ ---
112
+
113
+ Powered by [🍭 CandyPack](https://candypack.dev)
114
+ `
115
+ }
116
+ }
117
+ ],
118
+ [
119
+ '@semantic-release/changelog',
120
+ {
121
+ changelogFile: 'CHANGELOG.md'
122
+ }
123
+ ],
124
+ '@semantic-release/npm',
125
+ [
126
+ '@semantic-release/git',
127
+ {
128
+ assets: ['package.json', 'CHANGELOG.md'],
129
+ message: '🍭 CandyPack v${nextRelease.version} Released'
130
+ }
131
+ ],
132
+ '@semantic-release/github'
133
+ ]
134
+ }
package/AGENTS.md ADDED
@@ -0,0 +1,84 @@
1
+ # AGENTS Guidelines for This Repository
2
+
3
+ This document provides a comprehensive guide for developers working on the CandyPack source code. It covers the project's architecture, class system, directory structure, and usage patterns.
4
+
5
+ ## 1. Project Overview
6
+
7
+ CandyPack is a toolkit for building and deploying web applications, consisting of two main parts:
8
+ 1. **A Core System**: A background service that manages servers (web, mail, etc.), process monitoring, and provides a command-line interface (CLI).
9
+ 2. **A Web Framework**: A lightweight framework for building the actual web applications that are served by the core system.
10
+
11
+ ## 2. Core Architecture (`core/Candy.js`)
12
+
13
+ The heart of the core system is a service container implemented in `core/Candy.js`. This module creates a global singleton object named `Candy`.
14
+
15
+ ### Service Container
16
+
17
+ The `Candy` object acts as a service locator and dependency injection container. It can dynamically load and cache modules (services) from different parts of the application.
18
+
19
+ - **Registration and Resolution**: Modules are registered with a key and can be resolved (retrieved) using that key. The container handles the instantiation of classes and can cache them as singletons.
20
+ - **Module Loaders**: It has dedicated methods for loading modules from specific directories:
21
+ - `Candy.core(name)`: Loads a module from the `core/` directory.
22
+ - `Candy.cli(name)`: Loads a module from the `cli/src/` directory.
23
+ - `Candy.server(name)`: Loads a module from the `server/src/` directory.
24
+ - `Candy.watchdog(name)`: Loads a module from the `watchdog/src` directory.
25
+
26
+ **Example Usage:**
27
+ To access the application's configuration manager (defined in `core/Config.js`), you would use:
28
+ ```javascript
29
+ const config = Candy.core('Config');
30
+ ```
31
+
32
+ ## 3. Web Framework Architecture (`framework/src/Candy.js`)
33
+
34
+ The web framework provides the tools to build a website or API. Its main entry point is `framework/src/Candy.js`. Unlike the core `Candy` object, the framework creates a **request-specific instance** for every incoming HTTP request.
35
+
36
+ ### Request-Specific Context
37
+
38
+ When a web request hits the server, the framework's `instance()` method is called to create a `_candy` object. This object is a "context" that holds all the necessary components for handling that specific request.
39
+
40
+ This context object includes:
41
+ - `Request`: An object representing the incoming HTTP request.
42
+ - `View`: A view renderer for HTML pages.
43
+ - `Auth`: An authentication manager.
44
+ - `Token`: A CSRF token handler.
45
+ - `Lang`: An internationalization (i18n) helper.
46
+ - `Mysql`: A database connection handler.
47
+
48
+ It also attaches numerous helper functions to the context object for convenience within a controller, such as:
49
+ - `return(data)`: Ends the request and sends data back to the client.
50
+ - `direct(url)`: Redirects the client to a new URL.
51
+ - `cookie(key, value)`: Sets a cookie.
52
+ - `validator()`: Creates a new input validator.
53
+
54
+ This context object is passed to the controller function that handles the route.
55
+
56
+ ## 4. Directory Structure Guide
57
+
58
+ - `bin/`: Executable scripts for the CLI (`candy`, `candypack`).
59
+ - `cli/`: Source code for the CLI. The main logic is in `cli/src/Cli.js`.
60
+ - `core/`: Core application logic and shared modules (e.g., `Config.js`, `Commands.js`).
61
+ - `framework/`: The source code for the web framework.
62
+ - `server/`: Low-level server implementations (HTTP, Mail, DNS, SSL).
63
+ - `web/`: **This is a template for a user's website.** When a new site is created with CandyPack, this directory is copied to serve as the starting point.
64
+ - `web/index.js`: The entry point for a web application. It initializes the framework.
65
+ - `web/route/`: Contains route definition files.
66
+ - `web/controller/`: Contains controller files.
67
+ - `web/view/`: (Assumed) Would contain HTML templates for the `View` engine.
68
+ - `web/config.json`: Application-specific configuration.
69
+ - `test/`: Project test files.
70
+ - `watchdog/`: A process monitor that ensures the main CandyPack server stays running.
71
+
72
+ ## 5. Using the CLI (`bin/candy`)
73
+
74
+ The `candy` command is the main tool for managing the CandyPack server.
75
+
76
+ - `candy`: Shows the server status (online/offline, uptime, etc.) and lists available commands.
77
+ - `candy start`: (Inferred) Starts the CandyPack server daemon.
78
+ - `candy stop`: (Inferred) Stops the server.
79
+ - `candy restart`: (Inferred) Restarts the server.
80
+ - `candy monitor`: Opens an interactive terminal UI to monitor the status of all hosted websites and services.
81
+ - `candy debug`: Opens an interactive UI to view live logs from different core modules.
82
+ - `candy help <command>`: Shows detailed help for a specific command.
83
+
84
+ The commands are defined in `core/Commands.js` and implemented in various modules, primarily `cli/src/Cli.js`.