go-duck-cli 1.0.8 → 1.1.1
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 +30 -15
- package/generators/ai_docs.js +130 -0
- package/generators/broker.js +63 -0
- package/generators/config.js +149 -7
- package/generators/devops.js +210 -43
- package/generators/docs.js +23 -4
- package/generators/elasticsearch.js +263 -0
- package/generators/kratos.js +229 -41
- package/generators/metering.js +280 -48
- package/generators/migrations.js +92 -198
- package/generators/mqtt.js +2 -39
- package/generators/multitenancy.js +274 -71
- package/generators/nats.js +39 -0
- package/generators/outbox.js +171 -0
- package/generators/postgrest.js +7 -3
- package/generators/postman.js +405 -0
- package/generators/repository.js +27 -0
- package/generators/router.js +27 -0
- package/generators/security.js +95 -14
- package/generators/serverless.js +147 -0
- package/generators/storage.js +589 -0
- package/generators/swagger.js +84 -60
- package/generators/telemetry.js +23 -32
- package/generators/websocket.js +55 -21
- package/index.js +481 -116
- package/package.json +6 -4
- package/parser/gdl.js +163 -24
- package/templates/docs/index.html.hbs +5 -5
- package/templates/docs/layout.hbs +221 -62
- package/templates/docs/pages/audit.hbs +83 -35
- package/templates/docs/pages/cli.hbs +18 -0
- package/templates/docs/pages/configuration.hbs +241 -0
- package/templates/docs/pages/datadog.hbs +46 -0
- package/templates/docs/pages/elasticsearch.hbs +121 -0
- package/templates/docs/pages/federation.hbs +241 -0
- package/templates/docs/pages/gdl-advanced.hbs +91 -0
- package/templates/docs/pages/gdl-annotations.hbs +137 -0
- package/templates/docs/pages/gdl-entities.hbs +134 -0
- package/templates/docs/pages/gdl-relationships.hbs +80 -0
- package/templates/docs/pages/gdl.hbs +60 -204
- package/templates/docs/pages/graphql.hbs +58 -44
- package/templates/docs/pages/grpc.hbs +53 -90
- package/templates/docs/pages/hybrid-store.hbs +127 -0
- package/templates/docs/pages/index.hbs +418 -149
- package/templates/docs/pages/keycloak.hbs +43 -0
- package/templates/docs/pages/legend.hbs +116 -0
- package/templates/docs/pages/mosquitto.hbs +39 -0
- package/templates/docs/pages/multitenancy.hbs +139 -71
- package/templates/docs/pages/otel.hbs +40 -0
- package/templates/docs/pages/realtime.hbs +38 -12
- package/templates/docs/pages/redis.hbs +40 -0
- package/templates/docs/pages/rest.hbs +120 -202
- package/templates/docs/pages/saga.hbs +94 -0
- package/templates/docs/pages/security.hbs +150 -44
- package/templates/docs/pages/serverless.hbs +157 -0
- package/templates/docs/pages/storage.hbs +127 -0
- package/templates/docs/pages/wizard.hbs +683 -0
- package/templates/docs/triple_identity_registry.png +0 -0
- package/templates/go/controller.go.hbs +287 -283
- package/templates/go/entity.go.hbs +17 -15
- package/templates/go/main.go.hbs +47 -180
- package/templates/go/migrator.go.hbs +65 -0
- package/templates/go/router.go.hbs +272 -0
- package/templates/graphql/resolver.go.hbs +53 -34
- package/templates/graphql/schema.graphql.hbs +17 -5
- package/templates/kratos/service.go.hbs +169 -34
- package/templates/proto/entity.proto.hbs +10 -14
- package/test_nested.gdl +21 -0
- package/templates/docs/intro.mp4 +0 -0
- package/test_parser.js +0 -9
package/generators/migrations.js
CHANGED
|
@@ -5,236 +5,130 @@ import { toLiquibaseType } from '../parser/gdl.js';
|
|
|
5
5
|
|
|
6
6
|
export const generateLiquibaseChangelogs = async (entities, relationships, projectRootDir, delta = null, enums = []) => {
|
|
7
7
|
const migrationsDir = path.join(projectRootDir, 'migrations');
|
|
8
|
-
const
|
|
9
|
-
const changelogsDir = path.join(liquibaseDir, 'changelogs');
|
|
8
|
+
const sqlDir = path.join(migrationsDir, 'sql');
|
|
10
9
|
await fs.ensureDir(migrationsDir);
|
|
11
|
-
await fs.ensureDir(
|
|
12
|
-
await fs.ensureDir(changelogsDir);
|
|
10
|
+
await fs.ensureDir(sqlDir);
|
|
13
11
|
|
|
14
12
|
const timestamp = new Date().toISOString().replace(/[-:T]/g, '').split('.')[0];
|
|
15
|
-
const dateStamp = timestamp.substring(0, 8); // YYYYMMDD
|
|
16
13
|
|
|
17
14
|
// -------------------------------------------------------
|
|
18
|
-
//
|
|
15
|
+
// Core Management Tables (Always present if they don't exist)
|
|
19
16
|
// -------------------------------------------------------
|
|
20
|
-
|
|
17
|
+
if (!delta) {
|
|
18
|
+
const coreFileName = `00000_init_core_tables.sql`;
|
|
19
|
+
const corePath = path.join(sqlDir, coreFileName);
|
|
20
|
+
|
|
21
|
+
if (!await fs.pathExists(corePath)) {
|
|
22
|
+
const coreSql = `-- +goose Up
|
|
23
|
+
-- +goose StatementBegin
|
|
24
|
+
CREATE TABLE IF NOT EXISTS tenant_roles (
|
|
25
|
+
id BIGSERIAL PRIMARY KEY,
|
|
26
|
+
role_name VARCHAR(255) UNIQUE NOT NULL,
|
|
27
|
+
db_name VARCHAR(255) NOT NULL
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE TABLE IF NOT EXISTS audit_log (
|
|
31
|
+
id BIGSERIAL PRIMARY KEY,
|
|
32
|
+
entity_name VARCHAR(255) NOT NULL,
|
|
33
|
+
tenant_db VARCHAR(255),
|
|
34
|
+
entity_id VARCHAR(255) NOT NULL,
|
|
35
|
+
action VARCHAR(50) NOT NULL,
|
|
36
|
+
previous_value TEXT,
|
|
37
|
+
new_value TEXT,
|
|
38
|
+
modified_by VARCHAR(255),
|
|
39
|
+
keycloak_id VARCHAR(255),
|
|
40
|
+
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
41
|
+
client_ip VARCHAR(50)
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE TABLE IF NOT EXISTS api_usage (
|
|
45
|
+
id BIGSERIAL PRIMARY KEY,
|
|
46
|
+
user_id VARCHAR(255) NOT NULL,
|
|
47
|
+
api_path VARCHAR(255) NOT NULL,
|
|
48
|
+
tenant_db VARCHAR(255),
|
|
49
|
+
usage_count BIGINT NOT NULL DEFAULT 0,
|
|
50
|
+
max_limit BIGINT NOT NULL DEFAULT 1000,
|
|
51
|
+
last_accessed TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
52
|
+
);
|
|
53
|
+
-- +goose StatementEnd
|
|
54
|
+
|
|
55
|
+
-- +goose Down
|
|
56
|
+
-- +goose StatementBegin
|
|
57
|
+
DROP TABLE IF EXISTS tenant_roles CASCADE;
|
|
58
|
+
DROP TABLE IF EXISTS audit_log CASCADE;
|
|
59
|
+
DROP TABLE IF EXISTS api_usage CASCADE;
|
|
60
|
+
-- +goose StatementEnd
|
|
61
|
+
`;
|
|
62
|
+
await fs.writeFile(corePath, coreSql);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// -------------------------------------------------------
|
|
67
|
+
// Entity Migrations
|
|
68
|
+
// -------------------------------------------------------
|
|
69
|
+
let sqlUp = '-- +goose Up\n-- +goose StatementBegin\n';
|
|
70
|
+
let sqlDown = '-- +goose Down\n-- +goose StatementBegin\n';
|
|
21
71
|
|
|
22
72
|
const entitiesToCreate = delta ? delta.newEntities : entities;
|
|
23
|
-
|
|
73
|
+
|
|
74
|
+
if (entitiesToCreate.length === 0 && (!delta || (!delta.newFields && !delta.newRelationships))) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
24
77
|
|
|
25
78
|
// Create New Tables
|
|
26
79
|
for (const entity of entitiesToCreate) {
|
|
27
|
-
let columns =
|
|
28
|
-
<column name="id" type="BIGINT" autoIncrement="true">
|
|
29
|
-
<constraints primaryKey="true" nullable="false"/>
|
|
30
|
-
</column>`;
|
|
80
|
+
let columns = ' id BIGSERIAL PRIMARY KEY';
|
|
31
81
|
|
|
32
82
|
for (const field of entity.fields) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
columns += `
|
|
42
|
-
<column name="${field.name.toLowerCase()}" type="${liqType}">
|
|
43
|
-
<constraints nullable="${field.required ? 'false' : 'true'}"/>
|
|
44
|
-
</column>`;
|
|
45
|
-
}
|
|
83
|
+
let sqlType = toLiquibaseType(field, enums);
|
|
84
|
+
if (sqlType === 'JSON') sqlType = 'JSONB'; // Force JSONB for Postgres
|
|
85
|
+
|
|
86
|
+
const constraints = [];
|
|
87
|
+
if (field.required) constraints.push('NOT NULL');
|
|
88
|
+
if (field.unique) constraints.push('UNIQUE');
|
|
89
|
+
|
|
90
|
+
columns += `,\n ${field.name.toLowerCase()} ${sqlType} ${constraints.join(' ')}`;
|
|
46
91
|
}
|
|
47
92
|
|
|
48
|
-
//
|
|
93
|
+
// Auditing / Timestamp columns
|
|
49
94
|
if (entity.annotation === '@Audited') {
|
|
50
|
-
columns +=
|
|
51
|
-
<column name="created_by" type="VARCHAR(255)"/>
|
|
52
|
-
<column name="created_date" type="TIMESTAMP"/>
|
|
53
|
-
<column name="last_modified_by" type="VARCHAR(255)"/>
|
|
54
|
-
<column name="last_modified_date" type="TIMESTAMP"/>
|
|
55
|
-
<column name="last_modified_user_id" type="VARCHAR(255)"/>`;
|
|
95
|
+
columns += `,\n created_by VARCHAR(255),\n created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n last_modified_by VARCHAR(255),\n last_modified_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n last_modified_user_id VARCHAR(255)`;
|
|
56
96
|
} else {
|
|
57
|
-
columns +=
|
|
58
|
-
<column name="created_at" type="TIMESTAMP"/>
|
|
59
|
-
<column name="updated_at" type="TIMESTAMP"/>`;
|
|
97
|
+
columns += `,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP`;
|
|
60
98
|
}
|
|
61
99
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
<preConditions onFail="MARK_RAN"><not><tableExists tableName="${entity.name.toLowerCase()}"/></not></preConditions>
|
|
65
|
-
<createTable tableName="${entity.name.toLowerCase()}">
|
|
66
|
-
${columns}
|
|
67
|
-
</createTable>
|
|
68
|
-
</changeSet>
|
|
69
|
-
`;
|
|
100
|
+
sqlUp += `CREATE TABLE IF NOT EXISTS ${entity.name.toLowerCase()} (\n${columns}\n);\n\n`;
|
|
101
|
+
sqlDown += `DROP TABLE IF EXISTS ${entity.name.toLowerCase()} CASCADE;\n`;
|
|
70
102
|
}
|
|
71
103
|
|
|
72
|
-
// Add New Fields
|
|
104
|
+
// Add New Fields
|
|
73
105
|
if (delta && delta.newFields) {
|
|
74
106
|
for (const [entityName, fields] of Object.entries(delta.newFields)) {
|
|
75
|
-
if (fields.length === 0) continue;
|
|
76
|
-
let columnTags = '';
|
|
77
107
|
for (const field of fields) {
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
<column name="${field.name.toLowerCase()}" type="${liqType}">
|
|
87
|
-
<constraints nullable="${field.required ? 'false' : 'true'}"/>
|
|
88
|
-
</column>`;
|
|
89
|
-
}
|
|
108
|
+
let sqlType = toLiquibaseType(field, enums);
|
|
109
|
+
if (sqlType === 'JSON') sqlType = 'JSONB';
|
|
110
|
+
const constraints = [];
|
|
111
|
+
if (field.required) constraints.push('NOT NULL');
|
|
112
|
+
if (field.unique) constraints.push('UNIQUE');
|
|
113
|
+
|
|
114
|
+
sqlUp += `ALTER TABLE ${entityName.toLowerCase()} ADD COLUMN IF NOT EXISTS ${field.name.toLowerCase()} ${sqlType} ${constraints.join(' ')};\n`;
|
|
115
|
+
sqlDown += `ALTER TABLE ${entityName.toLowerCase()} DROP COLUMN IF EXISTS ${field.name.toLowerCase()};\n`;
|
|
90
116
|
}
|
|
91
|
-
changeSets += `
|
|
92
|
-
<changeSet id="${entityName.toLowerCase()}-add-fields-${timestamp}" author="go-duck">
|
|
93
|
-
<addColumn tableName="${entityName.toLowerCase()}">
|
|
94
|
-
${columnTags}
|
|
95
|
-
</addColumn>
|
|
96
|
-
</changeSet>
|
|
97
|
-
`;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Foreign Keys + Index
|
|
102
|
-
for (const rel of relationshipsToAdd) {
|
|
103
|
-
if (rel.type === 'OneToMany') {
|
|
104
|
-
const childTable = rel.to.entity.toLowerCase();
|
|
105
|
-
const fkNullable = rel.required ? 'false' : 'true';
|
|
106
|
-
const fkCol = rel.to.field.toLowerCase() + '_id';
|
|
107
|
-
const parentTable = rel.from.entity.toLowerCase();
|
|
108
|
-
const fkName = `fk_${childTable}_${rel.to.field.toLowerCase()}`;
|
|
109
|
-
const idxName = `idx_${childTable}_${fkCol}`;
|
|
110
|
-
changeSets += `
|
|
111
|
-
<changeSet id="rel-${parentTable}-${childTable}-${timestamp}" author="go-duck">
|
|
112
|
-
<preConditions onFail="MARK_RAN">
|
|
113
|
-
<not>
|
|
114
|
-
<columnExists tableName="${childTable}" columnName="${fkCol}"/>
|
|
115
|
-
</not>
|
|
116
|
-
</preConditions>
|
|
117
|
-
<addColumn tableName="${childTable}">
|
|
118
|
-
<column name="${fkCol}" type="BIGINT">
|
|
119
|
-
<constraints nullable="${fkNullable}" foreignKeyName="${fkName}" referencedTableName="${parentTable}" referencedColumnNames="id"/>
|
|
120
|
-
</column>
|
|
121
|
-
</addColumn>
|
|
122
|
-
</changeSet>
|
|
123
|
-
|
|
124
|
-
<changeSet id="idx-${idxName}-${timestamp}" author="go-duck">
|
|
125
|
-
<preConditions onFail="MARK_RAN">
|
|
126
|
-
<not><indexExists indexName="${idxName}"/></not>
|
|
127
|
-
</preConditions>
|
|
128
|
-
<createIndex indexName="${idxName}" tableName="${childTable}">
|
|
129
|
-
<column name="${fkCol}"/>
|
|
130
|
-
</createIndex>
|
|
131
|
-
</changeSet>
|
|
132
|
-
`;
|
|
133
117
|
}
|
|
134
118
|
}
|
|
135
119
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
changeSets += `
|
|
139
|
-
<changeSet id="management-tables-init" author="go-duck">
|
|
140
|
-
<preConditions onFail="MARK_RAN"><not><tableExists tableName="tenant_roles"/></not></preConditions>
|
|
141
|
-
<createTable tableName="tenant_roles">
|
|
142
|
-
<column name="id" type="BIGINT" autoIncrement="true"><constraints primaryKey="true" nullable="false"/></column>
|
|
143
|
-
<column name="role_name" type="VARCHAR(255)"><constraints nullable="false" unique="true"/></column>
|
|
144
|
-
<column name="db_name" type="VARCHAR(255)"><constraints nullable="false"/></column>
|
|
145
|
-
</createTable>
|
|
146
|
-
</changeSet>
|
|
147
|
-
|
|
148
|
-
<changeSet id="audit-log-table-init" author="go-duck">
|
|
149
|
-
<preConditions onFail="MARK_RAN"><not><tableExists tableName="audit_log"/></not></preConditions>
|
|
150
|
-
<createTable tableName="audit_log">
|
|
151
|
-
<column name="id" type="BIGINT" autoIncrement="true"><constraints primaryKey="true" nullable="false"/></column>
|
|
152
|
-
<column name="entity_name" type="VARCHAR(255)"><constraints nullable="false"/></column>
|
|
153
|
-
<column name="entity_id" type="VARCHAR(255)"><constraints nullable="false"/></column>
|
|
154
|
-
<column name="action" type="VARCHAR(50)"><constraints nullable="false"/></column>
|
|
155
|
-
<column name="previous_value" type="TEXT"/><column name="new_value" type="TEXT"/>
|
|
156
|
-
<column name="modified_by" type="VARCHAR(255)"/><column name="keycloak_id" type="VARCHAR(255)"/>
|
|
157
|
-
<column name="modified_at" type="TIMESTAMP"><constraints nullable="false"/></column>
|
|
158
|
-
<column name="client_ip" type="VARCHAR(50)"/>
|
|
159
|
-
</createTable>
|
|
160
|
-
</changeSet>
|
|
161
|
-
|
|
162
|
-
<changeSet id="api-usage-table-init" author="go-duck">
|
|
163
|
-
<preConditions onFail="MARK_RAN"><not><tableExists tableName="api_usage"/></not></preConditions>
|
|
164
|
-
<createTable tableName="api_usage">
|
|
165
|
-
<column name="id" type="BIGINT" autoIncrement="true"><constraints primaryKey="true" nullable="false"/></column>
|
|
166
|
-
<column name="user_id" type="VARCHAR(255)"><constraints nullable="false"/></column>
|
|
167
|
-
<column name="api_path" type="VARCHAR(255)"><constraints nullable="false"/></column>
|
|
168
|
-
<column name="usage_count" type="BIGINT" defaultValueNumeric="0"><constraints nullable="false"/></column>
|
|
169
|
-
<column name="max_limit" type="BIGINT" defaultValueNumeric="1000"><constraints nullable="false"/></column>
|
|
170
|
-
<column name="last_accessed" type="TIMESTAMP"/>
|
|
171
|
-
</createTable>
|
|
172
|
-
</changeSet>
|
|
173
|
-
`;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// -------------------------------------------------------
|
|
177
|
-
// STEP 2: Only write files if there are real changesets
|
|
178
|
-
// -------------------------------------------------------
|
|
179
|
-
if (changeSets.trim() === '') {
|
|
180
|
-
console.log(chalk.gray(' No database changes detected.'));
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
120
|
+
sqlUp += '-- +goose StatementEnd\n\n';
|
|
121
|
+
sqlDown += '-- +goose StatementEnd\n';
|
|
183
122
|
|
|
184
|
-
// Build descriptive filename from what actually changed
|
|
185
123
|
const descParts = [];
|
|
186
124
|
if (!delta) {
|
|
187
|
-
|
|
188
|
-
descParts.push('init');
|
|
189
|
-
if (entityNames) descParts.push(entityNames);
|
|
190
|
-
} else {
|
|
191
|
-
if (delta.newEntities && delta.newEntities.length > 0)
|
|
192
|
-
descParts.push('create-' + delta.newEntities.map(e => e.name.toLowerCase()).join('-'));
|
|
193
|
-
if (delta.newFields && Object.keys(delta.newFields).length > 0)
|
|
194
|
-
descParts.push('add-fields-to-' + Object.keys(delta.newFields).map(n => n.toLowerCase()).join('-'));
|
|
195
|
-
if (delta.newRelationships && delta.newRelationships.length > 0)
|
|
196
|
-
descParts.push('add-relations');
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const changelogFileName = `changelog-${dateStamp}-${descParts.join('__')}.xml`;
|
|
200
|
-
const changelogPath = path.join(changelogsDir, changelogFileName);
|
|
201
|
-
const masterPath = path.join(liquibaseDir, 'master.xml');
|
|
202
|
-
|
|
203
|
-
// Write the changelog XML
|
|
204
|
-
const changelogXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
205
|
-
<databaseChangeLog
|
|
206
|
-
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
|
207
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
208
|
-
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
|
209
|
-
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
|
|
210
|
-
${changeSets}
|
|
211
|
-
</databaseChangeLog>
|
|
212
|
-
`;
|
|
213
|
-
await fs.writeFile(changelogPath, changelogXml);
|
|
214
|
-
|
|
215
|
-
// Register in master.xml (only now that the file exists)
|
|
216
|
-
let masterXml = '';
|
|
217
|
-
if (await fs.pathExists(masterPath)) {
|
|
218
|
-
masterXml = await fs.readFile(masterPath, 'utf8');
|
|
219
|
-
if (!masterXml.includes(changelogFileName)) {
|
|
220
|
-
const includeLine = ` <include file="changelogs/${changelogFileName}" relativeToChangelogFile="true"/>`;
|
|
221
|
-
masterXml = masterXml.replace('</databaseChangeLog>', `${includeLine}\n</databaseChangeLog>`);
|
|
222
|
-
}
|
|
125
|
+
descParts.push('initial_schema');
|
|
223
126
|
} else {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
|
227
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
228
|
-
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
|
229
|
-
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
|
|
230
|
-
|
|
231
|
-
<include file="changelogs/${changelogFileName}" relativeToChangelogFile="true"/>
|
|
232
|
-
</databaseChangeLog>
|
|
233
|
-
`;
|
|
127
|
+
if (delta.newEntities?.length > 0) descParts.push('create_' + delta.newEntities.map(e => e.name.toLowerCase()).join('_'));
|
|
128
|
+
if (delta.newFields) descParts.push('add_fields');
|
|
234
129
|
}
|
|
235
|
-
await fs.writeFile(masterPath, masterXml);
|
|
236
130
|
|
|
237
|
-
|
|
131
|
+
const fileName = `${timestamp}_${descParts.join('_')}.sql`;
|
|
132
|
+
await fs.writeFile(path.join(sqlDir, fileName), sqlUp + sqlDown);
|
|
133
|
+
console.log(chalk.gray(` Generated Goose SQL Migration: ${fileName}`));
|
|
238
134
|
};
|
|
239
|
-
|
|
240
|
-
const _unused = null; // toLiquibaseType imported from parser/gdl.js
|
package/generators/mqtt.js
CHANGED
|
@@ -6,29 +6,16 @@ export const generateMQTTCode = async (config, outputDir) => {
|
|
|
6
6
|
const messagingDir = path.join(outputDir, 'messaging');
|
|
7
7
|
await fs.ensureDir(messagingDir);
|
|
8
8
|
|
|
9
|
-
const mqttClientGo = `
|
|
10
|
-
package messaging
|
|
9
|
+
const mqttClientGo = `package messaging
|
|
11
10
|
|
|
12
11
|
import (
|
|
13
|
-
"encoding/json"
|
|
14
|
-
"fmt"
|
|
15
12
|
"log"
|
|
16
|
-
"time"
|
|
17
|
-
|
|
18
13
|
"{{app_name}}/config"
|
|
19
14
|
mq "github.com/eclipse/paho.mqtt.golang"
|
|
20
15
|
)
|
|
21
16
|
|
|
22
17
|
var MQTTClient mq.Client
|
|
23
18
|
|
|
24
|
-
type EventMessage struct {
|
|
25
|
-
Action string \`json:"action"\`
|
|
26
|
-
Entity string \`json:"entity"\`
|
|
27
|
-
EventTime time.Time \`json:"event_time"\`
|
|
28
|
-
Payload interface{} \`json:"payload"\`
|
|
29
|
-
PreviousValue interface{} \`json:"previous_value,omitempty"\`
|
|
30
|
-
}
|
|
31
|
-
|
|
32
19
|
func InitMQTT(cfg *config.Config) {
|
|
33
20
|
if !cfg.GoDuck.Messaging.MQTT.Enabled {
|
|
34
21
|
log.Println("MQTT Messaging is disabled.")
|
|
@@ -56,32 +43,8 @@ func InitMQTT(cfg *config.Config) {
|
|
|
56
43
|
|
|
57
44
|
MQTTClient = client
|
|
58
45
|
}
|
|
59
|
-
|
|
60
|
-
func PublishEvent(topicPrefix string, action string, entity string, payload interface{}, prev interface{}) {
|
|
61
|
-
if MQTTClient == nil || !MQTTClient.IsConnected() {
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
msg := EventMessage{
|
|
66
|
-
Action: action,
|
|
67
|
-
Entity: entity,
|
|
68
|
-
EventTime: time.Now(),
|
|
69
|
-
Payload: payload,
|
|
70
|
-
PreviousValue: prev,
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
data, err := json.Marshal(msg)
|
|
74
|
-
if err != nil {
|
|
75
|
-
log.Printf("Error marshaling MQTT message: %v", err)
|
|
76
|
-
return
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
topic := fmt.Sprintf("%s/%s/%s", topicPrefix, entity, action)
|
|
80
|
-
token := MQTTClient.Publish(topic, 0, false, data)
|
|
81
|
-
token.Wait()
|
|
82
|
-
}
|
|
83
46
|
`;
|
|
84
47
|
|
|
85
48
|
await fs.writeFile(path.join(messagingDir, 'mqtt.go'), mqttClientGo.replace(/{{app_name}}/g, config.name));
|
|
86
|
-
console.log(chalk.gray(' Generated MQTT
|
|
49
|
+
console.log(chalk.gray(' Generated MQTT Connection Client'));
|
|
87
50
|
};
|