go-duck-cli 1.2.1 → 1.2.3

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/README.md CHANGED
@@ -13,6 +13,7 @@
13
13
  <p align="center">
14
14
  <a href="https://badge.fury.io/js/go-duck-cli"><img src="https://badge.fury.io/js/go-duck-cli.svg" alt="npm version"></a>
15
15
  <a href="https://opensource.org/licenses/ISC"><img src="https://img.shields.io/badge/License-ISC-blue.svg" alt="License: ISC"></a>
16
+ ![Version](https://img.shields.io/badge/version-1.2.25-blue)
16
17
  </p>
17
18
 
18
19
  ---
@@ -64,6 +65,8 @@ GO-DUCK has officially reached the **410% Achievement Status**, evolving from a
64
65
  ### ✨ Primary Features (The 410% Core)
65
66
 
66
67
  * **Federated Multi-Tenancy**: Side-by-side **Database-per-Tenant isolation** with a **Master-Tenant Registry** (Role ↔ DB ↔ Opaque UUID).
68
+ * **Multi-Protocol REST**: Dynamically switchable REST rendering using standard `json` or high-performance `messagepack` based on configuration.
69
+ * **gRPC-Web Native Proxy**: Natively wraps Kratos gRPC to automatically serve a web proxy (e.g. on port `9090`) to allow direct frontend Protobuf interaction.
67
70
  * **Industrial-Grade Parallel Harvester**: Asynchronous goroutine-based data aggregation across multiple silos with `?federated=true` opt-in.
68
71
  * **Precision Harvesting**: Surgical multi-silo selection via comma-separated `X-Tenant-ID` headers.
69
72
  * **Super Admin Security Boundaries**: Strict architectural separation between Business APIs and Infrastructure Control APIs.
@@ -72,7 +75,7 @@ GO-DUCK has officially reached the **410% Achievement Status**, evolving from a
72
75
  * **Distributed Saga Consistency**: Integrated **Transactional Outbox** pattern and background workers in every silo to guarantee eventual consistency across the federation.
73
76
  * **Zero-Trust Identity Registry**: Decoupled mapping layer ensuring physical database names and internal IDs never leak to the client.
74
77
  * **Universal Storage Mesh**: Dynamic Multi-Provider Registry allowing hot-swapping at runtime via `?provider=` queries, alongside Distributed Cross-Scan endpoints to auto-locate files across AWS, GCS, SFTP, and GitHub lakes.
75
- * **Spring-style Elasticsearch Search**: Real-time sync for entities marked with `@Searchable`, supporting fuzzy matching and complex queries.
78
+ * **Spring-style Elasticsearch Search**: Real-time sync for entities marked with `@Searchable`, supporting native `query_string` syntax (wildcards like `*`, booleans, ranges, and fuzzy matching).
76
79
  * **SaaS Quota Engine**: Redis-backed API bandwidth tracking with dynamic, hierarchical limits (User vs. Role mapping).
77
80
  * **Resilience Layer**: Sony/Gobreaker Integration + Zero-Trust Distributed Redis Rate Limiter.
78
81
  * **Comprehensive GDL Schema Evolution**: Detects structural deltas intelligently and automatically generates Goose SQL for dropped entities (`DROP TABLE`), dropped fields (`DROP COLUMN`), and altered fields (`ALTER TYPE`, constraints) to keep databases in absolute sync.
@@ -104,6 +107,15 @@ Ensure your development environment meets the following requirements:
104
107
  * **Docker:** v20+
105
108
  * **Composability:** v2+
106
109
 
110
+ ## Quick‑Start
111
+
112
+ Follow these four steps to get a generated microservice running locally and in Kubernetes:
113
+
114
+ 1. **Create**: `go-duck create -o ./my-app -c config.yaml`
115
+ 2. **Enter**: `cd my-app`
116
+ 3. **Build & Push**: `./push.sh my-registry/my-app:1.0.0`
117
+ 4. **Deploy**: `kubectl apply -f devops/k8s/`
118
+
107
119
  ## 🚀 Scaffold & Run
108
120
 
109
121
  Follow these steps to create and run a new microservice with GO-DUCK:
@@ -114,6 +126,36 @@ go-duck create -o ./my-app -c config.yaml
114
126
 
115
127
  # 2. Enter the application directory
116
128
  cd my-app
129
+
130
+ # 3. Build, tag, and push Docker image (updates app.yaml)
131
+ ./push.sh my-registry/my-app:1.0.0
132
+
133
+ # 4. Deploy to Kubernetes
134
+ kubectl apply -f devops/k8s/
135
+
136
+ ### 🚢 Deploy to Kubernetes & Push Images
137
+
138
+ The generated project includes a **devops/k8s** directory with ready‑to‑apply Kubernetes manifests:
139
+
140
+ - `mongo.yaml` – StatefulSet & Service for MongoDB.
141
+ - `minio.yaml` – Deployment & Service for MinIO object storage.
142
+ - `app.yaml` – Deployment for the generated Go microservice, referencing a placeholder image name (`<app‑name>:latest`). Replace the image with the tag you push.
143
+
144
+ A helper script **push.sh** (located at the project root) automates the Docker build, tag, push, and then updates the `app.yaml` image field:
145
+
146
+ ```bash
147
+ ./push.sh my-registry/my-app:1.0.0
148
+ ```
149
+
150
+ After pushing, deploy everything with:
151
+
152
+ ```bash
153
+ kubectl apply -f devops/k8s/
154
+ ```
155
+
156
+ > [!NOTE]
157
+ > The K8s manifests use placeholder values (e.g., resource limits, storage class). Adjust them to match your cluster requirements before applying.
158
+
117
159
  ```
118
160
 
119
161
  ### 🏗️ Compiling Protobuf & gRPC Contracts
@@ -156,6 +198,37 @@ docker-compose up -d
156
198
  go run main.go
157
199
  ```
158
200
 
201
+ ## 🌐 Calling the Multi-Protocol Endpoints
202
+
203
+ GO-DUCK automatically exposes your microservice across three distinct ports to serve different architectural needs without code duplication:
204
+
205
+ 1. **REST API (Port 8080 by default)**
206
+ Standard HTTP endpoints for web browsers and legacy clients.
207
+ - **JSON (Default):** Perfect for general use.
208
+ - **MessagePack (High Performance):** To switch to binary MessagePack, update your `config.yaml` before generation:
209
+ ```yaml
210
+ server:
211
+ rest:
212
+ port: 8080
213
+ protocol: "messagepack"
214
+ ```
215
+ Clients must send the `Accept: application/msgpack` and `Content-Type: application/msgpack` headers to consume this endpoint correctly.
216
+ - **Pagination & Sorting:** All `GetAll` endpoints support pagination via `?page=1&size=20`, and dynamic sorting via `?sort=field,asc` or `?sort=field,desc` (e.g. `?sort=name,desc`).
217
+
218
+ 2. **Native Kratos gRPC (Port 9000 by default)**
219
+ Pure HTTP/2 Protobuf communication. Used strictly for internal **backend-to-backend** communication (e.g., Microservice A calling Microservice B) where maximum throughput is required.
220
+
221
+ 3. **gRPC-Web Proxy (Port 9090 by default)**
222
+ Web browsers cannot speak raw HTTP/2 gRPC. This port acts as an HTTP/1.1 proxy bridge, allowing frontend frameworks (React, Angular, Vue) to interact directly with the Protobuf gRPC contracts.
223
+ To disable or change the proxy port, update your `config.yaml`:
224
+ ```yaml
225
+ server:
226
+ grpc:
227
+ web_enabled: true
228
+ web_port: 9090
229
+ ```
230
+ *Frontend Tip: Use the `grpc-web` npm package to generate a frontend client that communicates with this port!*
231
+
159
232
  ## Usage
160
233
 
161
234
  The `go-duck-cli` has two main commands: `create` and `import-gdl`.
@@ -52,7 +52,7 @@ export const generateAIDocs = async (config, entities, outputDir, enums, openEnt
52
52
  for (const entity of entities) {
53
53
  const routeName = entity.name.toLowerCase() + 's';
54
54
  endpointsContent += `\n#### ${entity.name}\n`;
55
- endpointsContent += `- \`GET /api/${routeName}\` (Pagination, e.g. \`?page=1&size=10&eager=true\`)\n`;
55
+ endpointsContent += `- \`GET /api/${routeName}\` (Pagination & dynamic sorting, e.g. \`?page=1&size=10&eager=true&sort=id,asc\`)\n`;
56
56
  endpointsContent += `- \`GET /api/${routeName}/:id\`\n`;
57
57
  endpointsContent += `- \`POST /api/${routeName}\`\n`;
58
58
  endpointsContent += `- \`PUT /api/${routeName}/:id\`\n`;
@@ -88,6 +88,7 @@ export const generateAIDocs = async (config, entities, outputDir, enums, openEnt
88
88
  if (entity.isSearchable) entitiesContent += `- \`@Searchable\`\n`;
89
89
  if (entity.isAudited) entitiesContent += `- \`@Audited\`\n`;
90
90
  if (entity.isFederated) entitiesContent += `- \`@Federated\`\n`;
91
+ if (entity.isDelete) entitiesContent += `- \`@Delete\`\n`;
91
92
 
92
93
  entitiesContent += `\nFields:\n`;
93
94
  for (const field of entity.fields) {
@@ -101,16 +102,20 @@ export const generateAIDocs = async (config, entities, outputDir, enums, openEnt
101
102
  // 4. PROTOCOLS.md
102
103
  let protoContent = `# Additional Network Protocols\n\n`;
103
104
  protoContent += `## GraphQL Surface\n`;
104
- protoContent += `- **Endpoint**: \`POST /query\`\n`;
105
- protoContent += `- **Playground**: \`GET /\`\n\n`;
105
+ protoContent += `- **Endpoint**: \`POST /graphql\` (Secured via JWT and Tenant headers)\n`;
106
+ protoContent += `- **Playground**: GraphQL Playground UI is enabled on the server.\n`;
107
+ protoContent += `- **Queries**: \`list[Entity]s(page: Int, size: Int)\`, \`get[Entity](id: ID!)\`\n`;
108
+ protoContent += `- **Mutations**: \`create[Entity](input: CreateInput)\`, \`update[Entity](id: ID!, input: UpdateInput)\`, \`delete[Entity](id: ID!)\`\n`;
109
+ protoContent += `- **Postman Collection Integration**: The auto-generated Postman collection includes a comprehensive **GraphQL Federation Layer** folder containing test queries and mutations for all entities.\n\n`;
106
110
 
107
111
  protoContent += `## WebSocket Engine\n`;
108
- protoContent += `- **Endpoint**: \`ws[s]://host/ws\`\n`;
109
- protoContent += `- **Format**: JSON Envelope Payload \`{ "type": "...", "payload": {...} }\`\n\n`;
112
+ protoContent += `- **Endpoint**: \`ws[s]://host/ws?token={JWT}\`\n`;
113
+ protoContent += `- **Format**: JSON Envelope Payload with HMAC-SHA256 digital signature: \`{ "type": "...", "payload": {...} }\`\n\n`;
110
114
 
111
- protoContent += `## gRPC (Kratos) Engine\n`;
112
- protoContent += `- **Port**: \`9000\` (Default)\n`;
113
- protoContent += `- **Proto Definitions**: Located in \`api/.../\`\n`;
115
+ protoContent += `## gRPC & gRPC-Web Engine\n`;
116
+ protoContent += `- **Native Kratos gRPC Port**: \`9000\` (TCP)\n`;
117
+ protoContent += `- **gRPC-Web Proxy Port**: \`9090\` (HTTP/1.1 for web clients)\n`;
118
+ protoContent += `- **Proto Definitions**: Located in \`api/v1/*.proto\`\n`;
114
119
 
115
120
  await fs.writeFile(path.join(aiDocsDir, 'PROTOCOLS.md'), protoContent);
116
121
 
@@ -118,6 +123,15 @@ export const generateAIDocs = async (config, entities, outputDir, enums, openEnt
118
123
  let agentInstructions = `# LLM / AI AGENT INSTRUCTIONS 🤖\n\n`;
119
124
  agentInstructions += `Welcome to the generated codebase for **${appName}**.\n\n`;
120
125
  agentInstructions += `This application was generated by the GO-DUCK-CLI (An advanced Evolutionary Go Code Generator).\n\n`;
126
+ agentInstructions += `### High-Velocity Commands:\n`;
127
+ agentInstructions += `- **Build Project**: \`go build ./...\`\n`;
128
+ agentInstructions += `- **Protobuf Compilation**: \`./generate.sh\` (or \`.\\generate.bat\` on Windows)\n`;
129
+ agentInstructions += `- **Local Dependencies & Dev Boot**: \`docker-compose up -d && go run main.go\`\n`;
130
+ agentInstructions += `- **Docker Build & Push**: \`./push.sh\` (Builds and pushes the Docker image to registry)\n\n`;
131
+ agentInstructions += `### GDL Evolution & Schema Deletions:\n`;
132
+ agentInstructions += `- **Snapshot Merging (Multi-File GDL)**: The generator implements stateful snapshot merging. Running \`import-gdl\` on a single GDL file will NOT wipe out other entities; previous snapshots are retrieved from the \`.go-duck/\` state folder and merged automatically.\n`;
133
+ agentInstructions += `- **Altering/Dropping Fields**: To add, drop, or edit fields within an entity, update the fields inline in the GDL entity block. Running \`import-gdl\` generates targeted Goose SQL column-level migrations.\n`;
134
+ agentInstructions += `- **Dropping Entities**: To completely delete an entity, its database table, all generated code files, and its snapshot, append the \`@Delete\` annotation above the entity definition block and run \`import-gdl\`.\n\n`;
121
135
  agentInstructions += `### How to navigate this system:\n`;
122
136
  agentInstructions += `The full system specifications and dynamically generated blueprints have been exported for you in the \`docs/ai/\` folder. Look there before attempting any code modifications.\n\n`;
123
137
  agentInstructions += `- **[docs/ai/ARCHITECTURE.md](docs/ai/ARCHITECTURE.md)**: Describes the databases, caching layers, configuration structure, and middleware enabled in this project.\n`;
@@ -25,13 +25,16 @@ type Config struct {
25
25
  Description string \`mapstructure:"description"\`
26
26
 
27
27
  Server struct {
28
- Port int \`mapstructure:"port"\`
29
- ReadTimeout time.Duration \`mapstructure:"read-timeout"\`
30
- WriteTimeout time.Duration \`mapstructure:"write-timeout"\`
28
+ REST struct {
29
+ Port int \`mapstructure:"port"\`
30
+ Protocol string \`mapstructure:"protocol"\`
31
+ } \`mapstructure:"rest"\`
31
32
  GRPC struct {
32
- Addr string \`mapstructure:"addr"\`
33
- Network string \`mapstructure:"network"\`
34
- Timeout time.Duration \`mapstructure:"timeout"\`
33
+ Addr string \`mapstructure:"addr"\`
34
+ Network string \`mapstructure:"network"\`
35
+ Timeout time.Duration \`mapstructure:"timeout"\`
36
+ WebEnabled bool \`mapstructure:"web_enabled"\`
37
+ WebPort int \`mapstructure:"web_port"\`
35
38
  } \`mapstructure:"grpc"\`
36
39
  CORS struct {
37
40
  AllowOrigins []string \`mapstructure:"allow-origins"\`
@@ -237,7 +240,8 @@ func LoadConfig() (*Config, error) {
237
240
  v.AddConfigPath(".")
238
241
 
239
242
  // Default values
240
- v.SetDefault("go-duck.server.port", 8080)
243
+ v.SetDefault("go-duck.server.rest.port", 8080)
244
+ v.SetDefault("go-duck.server.rest.protocol", "json")
241
245
  v.SetDefault("go-duck.security.rate-limit.rps", 100.0)
242
246
  v.SetDefault("go-duck.security.rate-limit.burst", 200)
243
247
  v.SetDefault("go-duck.logging.datadog.enabled", false)
@@ -254,6 +258,8 @@ func LoadConfig() (*Config, error) {
254
258
  v.SetDefault("go-duck.server.grpc.addr", ":9000")
255
259
  v.SetDefault("go-duck.server.grpc.network", "tcp")
256
260
  v.SetDefault("go-duck.server.grpc.timeout", "1s")
261
+ v.SetDefault("go-duck.server.grpc.web_enabled", false)
262
+ v.SetDefault("go-duck.server.grpc.web_port", 9090)
257
263
  v.SetDefault("go-duck.resilience.circuit-breaker.enabled", true)
258
264
  v.SetDefault("go-duck.resilience.circuit-breaker.failure-threshold", 5)
259
265
  v.SetDefault("go-duck.resilience.circuit-breaker.timeout", "60s")