@oktis-works/database 0.7.1 → 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.
package/dist/index.d.ts CHANGED
@@ -2,6 +2,6 @@ export { createConnection, getConnection, getReadConnection, closeConnection, he
2
2
  export { setTenantContext, clearTenantContext, getCurrentTenantId, enableRLS } from './rls/index.js';
3
3
  export { loadMigrationsFromDir, getAppliedMigrations, applyMigration, rollbackMigration, runMigrations, runPluginMigrations, rollbackPluginMigrations, type MigrationFile, } from './migrations/runner.js';
4
4
  export { ensureCoreSchema, resolveTenantId } from './migrations/bootstrap.js';
5
- export { seedCoreData, seedDefaultRoles, seedDefaultSettings, DEFAULT_ROLES, DEFAULT_SETTINGS, } from './migrations/seed.js';
5
+ export { seedCoreData, seedDemoContent, seedDefaultRoles, seedDefaultSettings, DEFAULT_ROLES, DEFAULT_SETTINGS, } from './migrations/seed.js';
6
6
  export { schema, getSchema } from './schema/index.js';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACrG,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,wBAAwB,EACxB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACrG,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,wBAAwB,EACxB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EACL,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -3,6 +3,6 @@ export { createConnection, getConnection, getReadConnection, closeConnection, he
3
3
  export { setTenantContext, clearTenantContext, getCurrentTenantId, enableRLS } from './rls/index.js';
4
4
  export { loadMigrationsFromDir, getAppliedMigrations, applyMigration, rollbackMigration, runMigrations, runPluginMigrations, rollbackPluginMigrations, } from './migrations/runner.js';
5
5
  export { ensureCoreSchema, resolveTenantId } from './migrations/bootstrap.js';
6
- export { seedCoreData, seedDefaultRoles, seedDefaultSettings, DEFAULT_ROLES, DEFAULT_SETTINGS, } from './migrations/seed.js';
6
+ export { seedCoreData, seedDemoContent, seedDefaultRoles, seedDefaultSettings, DEFAULT_ROLES, DEFAULT_SETTINGS, } from './migrations/seed.js';
7
7
  export { schema, getSchema } from './schema/index.js';
8
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAE3C,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACrG,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,wBAAwB,GAEzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAE3C,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACrG,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,wBAAwB,GAEzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EACL,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
@@ -47,5 +47,16 @@ export declare function seedCoreData(sql?: Sql): Promise<{
47
47
  roles: number;
48
48
  settings: number;
49
49
  }>;
50
+ /**
51
+ * Seed de conteúdo demonstrativo (páginas, posts, menus, settings de leitura).
52
+ * Idempotente: usa ON CONFLICT em content (tenant_id, type, slug), menus (tenant_id, slug),
53
+ * e settings (key, tenant_id).
54
+ */
55
+ export declare function seedDemoContent(sql?: Sql): Promise<{
56
+ pages: number;
57
+ posts: number;
58
+ menus: number;
59
+ readingSettings: number;
60
+ }>;
50
61
  export {};
51
62
  //# sourceMappingURL=seed.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../src/migrations/seed.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAErC,KAAK,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC;AAExB,4EAA4E;AAC5E,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;EAMhB,CAAC;AAEX,kFAAkF;AAClF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;EAKnB,CAAC;AAEX,0FAA0F;AAC1F,wBAAsB,gBAAgB,CAAC,GAAG,GAAE,GAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBlF;AAED,gFAAgF;AAChF,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,GAAqB,GACzB,OAAO,CAAC,MAAM,CAAC,CAejB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,GAAG,GAAE,GAAqB,GACzB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAK9C"}
1
+ {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../src/migrations/seed.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAErC,KAAK,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC;AAExB,4EAA4E;AAC5E,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;EAMhB,CAAC;AAEX,kFAAkF;AAClF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;EAKnB,CAAC;AAEX,0FAA0F;AAC1F,wBAAsB,gBAAgB,CAAC,GAAG,GAAE,GAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBlF;AAED,gFAAgF;AAChF,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,GAAqB,GACzB,OAAO,CAAC,MAAM,CAAC,CAejB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,GAAG,GAAE,GAAqB,GACzB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAK9C;AAwBD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,GAAG,GAAE,GAAqB,GACzB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC,CAmQnF"}
@@ -65,4 +65,258 @@ export async function seedCoreData(sql = getConnection()) {
65
65
  const settings = await seedDefaultSettings(tenantId, sql);
66
66
  return { roles, settings };
67
67
  }
68
+ /** Lorem ipsum curto para campos de texto. */
69
+ const LOREM_IPSUM = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.';
70
+ /** Lorem ipsum longo para conteúdo de posts/páginas. */
71
+ const LOREM_LONG = `
72
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
73
+
74
+ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
75
+
76
+ Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
77
+ `;
78
+ /** Estrutura padrão do body do editor (blocos + html renderizado). */
79
+ function makeBody(html, blocks = []) {
80
+ return {
81
+ html,
82
+ blocks: blocks.length > 0 ? blocks : [
83
+ { type: 'paragraph', content: html.replace(/<[^>]*>/g, '').slice(0, 200) },
84
+ ],
85
+ };
86
+ }
87
+ /**
88
+ * Seed de conteúdo demonstrativo (páginas, posts, menus, settings de leitura).
89
+ * Idempotente: usa ON CONFLICT em content (tenant_id, type, slug), menus (tenant_id, slug),
90
+ * e settings (key, tenant_id).
91
+ */
92
+ export async function seedDemoContent(sql = getConnection()) {
93
+ const tenantId = await resolveTenantId('default');
94
+ // Autor padrão: primeiro usuário do tenant (ou cria um se não houver)
95
+ const authorResult = await sql.unsafe(`SELECT id FROM users WHERE id IN (SELECT user_id FROM tenant_users WHERE tenant_id = $1) LIMIT 1`, [tenantId]);
96
+ let authorId;
97
+ if (authorResult.length === 0) {
98
+ // Fallback: cria usuário admin se não houver nenhum
99
+ const newUser = await sql.unsafe(`INSERT INTO users (email, name, password_hash, status)
100
+ VALUES ('admin@local', 'Administrador', '$2b$10$dummy', 'ACTIVE')
101
+ RETURNING id`);
102
+ authorId = String(newUser[0]?.['id'] ?? '');
103
+ await sql.unsafe(`INSERT INTO tenant_users (tenant_id, user_id, role_id)
104
+ SELECT $1, $2, id FROM roles WHERE slug = 'TENANT_ADMIN' AND tenant_id = $1 LIMIT 1`, [tenantId, authorId]);
105
+ }
106
+ else {
107
+ authorId = String(authorResult[0]?.['id'] ?? '');
108
+ }
109
+ const now = new Date();
110
+ // ---- PÁGINAS ----
111
+ const pages = [
112
+ {
113
+ type: 'page',
114
+ slug: 'home',
115
+ title: 'Início',
116
+ excerpt: 'Bem-vindo ao seu novo site com OkCMS.',
117
+ body: makeBody(`
118
+ <section class="hero">
119
+ <h1>Bem-vindo ao OkCMS</h1>
120
+ <p>Seu novo site está pronto para personalizar.</p>
121
+ <a href="/blog" class="btn btn-primary">Ver Blog</a>
122
+ </section>
123
+ <section id="sobre" class="about-preview">
124
+ <h2>Sobre Nós</h2>
125
+ <p>${LOREM_IPSUM}</p>
126
+ <a href="/sobre">Ler mais →</a>
127
+ </section>
128
+ <section class="latest-posts">
129
+ <h2>Últimos Artigos</h2>
130
+ <p>Os artigos mais recentes aparecerão aqui automaticamente.</p>
131
+ </section>
132
+ <section id="contato" class="contact">
133
+ <h2>Entre em Contato</h2>
134
+ <p>Preencha o formulário ou envie um e-mail para contato@exemplo.com</p>
135
+ </section>
136
+ `, [
137
+ { type: 'heading', level: 1, content: 'Bem-vindo ao OkCMS' },
138
+ { type: 'paragraph', content: 'Seu novo site está pronto para personalizar.' },
139
+ { type: 'heading', level: 2, content: 'Sobre Nós' },
140
+ { type: 'paragraph', content: LOREM_IPSUM },
141
+ { type: 'heading', level: 2, content: 'Últimos Artigos' },
142
+ { type: 'paragraph', content: 'Os artigos mais recentes aparecerão aqui automaticamente.' },
143
+ { type: 'heading', level: 2, content: 'Entre em Contato' },
144
+ { type: 'paragraph', content: 'Preencha o formulário ou envie um e-mail para contato@exemplo.com' },
145
+ ]),
146
+ },
147
+ {
148
+ type: 'page',
149
+ slug: 'sobre',
150
+ title: 'Sobre Nós',
151
+ excerpt: 'Conheça nossa história e missão.',
152
+ body: makeBody(`
153
+ <h2>Nossa História</h2>
154
+ <p>${LOREM_LONG}</p>
155
+ <h2>Nossa Missão</h2>
156
+ <p>${LOREM_IPSUM}</p>
157
+ <h2>Equipe</h2>
158
+ <p>${LOREM_IPSUM}</p>
159
+ `, [
160
+ { type: 'heading', level: 2, content: 'Nossa História' },
161
+ { type: 'paragraph', content: LOREM_LONG },
162
+ { type: 'heading', level: 2, content: 'Nossa Missão' },
163
+ { type: 'paragraph', content: LOREM_IPSUM },
164
+ { type: 'heading', level: 2, content: 'Equipe' },
165
+ { type: 'paragraph', content: LOREM_IPSUM },
166
+ ]),
167
+ },
168
+ {
169
+ type: 'page',
170
+ slug: 'blog',
171
+ title: 'Blog',
172
+ excerpt: 'Artigos, tutoriais e novidades.',
173
+ body: makeBody(`
174
+ <p>Bem-vindo ao nosso blog. Aqui você encontrará artigos, tutoriais e novidades sobre OkCMS.</p>
175
+ <p>Os posts mais recentes são listados abaixo automaticamente.</p>
176
+ `, [
177
+ { type: 'paragraph', content: 'Bem-vindo ao nosso blog. Aqui você encontrará artigos, tutoriais e novidades sobre OkCMS.' },
178
+ { type: 'paragraph', content: 'Os posts mais recentes são listados abaixo automaticamente.' },
179
+ ]),
180
+ },
181
+ ];
182
+ let pagesCreated = 0;
183
+ const pageIds = {};
184
+ for (const page of pages) {
185
+ const result = await sql.unsafe(`INSERT INTO content (tenant_id, type, title, slug, body, excerpt, status, author_id, published_at, created_at, updated_at)
186
+ VALUES ($1, $2, $3, $4, to_jsonb($5::text), $6, 'PUBLISHED', $7, $8, $9, $10)
187
+ ON CONFLICT (tenant_id, type, slug) DO UPDATE SET
188
+ title = EXCLUDED.title,
189
+ body = to_jsonb(EXCLUDED.body::text),
190
+ excerpt = EXCLUDED.excerpt,
191
+ status = EXCLUDED.status,
192
+ author_id = EXCLUDED.author_id,
193
+ published_at = EXCLUDED.published_at,
194
+ updated_at = EXCLUDED.updated_at
195
+ RETURNING id`, [tenantId, page.type, page.title, page.slug, JSON.stringify(page.body), page.excerpt, authorId, now, now, now]);
196
+ pagesCreated += result.length;
197
+ pageIds[page.slug] = String(result[0]?.['id'] ?? '');
198
+ }
199
+ // ---- POSTS ----
200
+ const posts = [
201
+ {
202
+ type: 'post',
203
+ slug: 'primeiro-post',
204
+ title: 'Primeiro Artigo do Blog',
205
+ excerpt: 'Este é o primeiro artigo de demonstração do blog.',
206
+ body: makeBody(`
207
+ <h1>Primeiro Artigo do Blog</h1>
208
+ <p>${LOREM_IPSUM}</p>
209
+ <h2>Introdução</h2>
210
+ <p>${LOREM_LONG}</p>
211
+ <h2>Desenvolvimento</h2>
212
+ <p>${LOREM_IPSUM}</p>
213
+ <h3>Subseção Exemplo</h3>
214
+ <p>${LOREM_IPSUM}</p>
215
+ <h2>Conclusão</h2>
216
+ <p>${LOREM_LONG}</p>
217
+ `, [
218
+ { type: 'heading', level: 1, content: 'Primeiro Artigo do Blog' },
219
+ { type: 'paragraph', content: LOREM_IPSUM },
220
+ { type: 'heading', level: 2, content: 'Introdução' },
221
+ { type: 'paragraph', content: LOREM_LONG },
222
+ { type: 'heading', level: 2, content: 'Desenvolvimento' },
223
+ { type: 'paragraph', content: LOREM_IPSUM },
224
+ { type: 'heading', level: 3, content: 'Subseção Exemplo' },
225
+ { type: 'paragraph', content: LOREM_IPSUM },
226
+ { type: 'heading', level: 2, content: 'Conclusão' },
227
+ { type: 'paragraph', content: LOREM_LONG },
228
+ ]),
229
+ },
230
+ {
231
+ type: 'post',
232
+ slug: 'segundo-post',
233
+ title: 'Dicas para Começar com OkCMS',
234
+ excerpt: 'Aprenda os primeiros passos para criar seu site com OkCMS.',
235
+ body: makeBody(`
236
+ <h1>Dicas para Começar com OkCMS</h1>
237
+ <p>${LOREM_IPSUM}</p>
238
+ <h2>Instalação</h2>
239
+ <p>${LOREM_LONG}</p>
240
+ <h2>Configuração Inicial</h2>
241
+ <p>${LOREM_IPSUM}</p>
242
+ <h3>Temas</h3>
243
+ <p>${LOREM_IPSUM}</p>
244
+ <h3>Plugins</h3>
245
+ <p>${LOREM_IPSUM}</p>
246
+ <h2>Criando Conteúdo</h2>
247
+ <p>${LOREM_LONG}</p>
248
+ <h2>Deploy</h2>
249
+ <p>${LOREM_IPSUM}</p>
250
+ `, [
251
+ { type: 'heading', level: 1, content: 'Dicas para Começar com OkCMS' },
252
+ { type: 'paragraph', content: LOREM_IPSUM },
253
+ { type: 'heading', level: 2, content: 'Instalação' },
254
+ { type: 'paragraph', content: LOREM_LONG },
255
+ { type: 'heading', level: 2, content: 'Configuração Inicial' },
256
+ { type: 'paragraph', content: LOREM_IPSUM },
257
+ { type: 'heading', level: 3, content: 'Temas' },
258
+ { type: 'paragraph', content: LOREM_IPSUM },
259
+ { type: 'heading', level: 3, content: 'Plugins' },
260
+ { type: 'paragraph', content: LOREM_IPSUM },
261
+ { type: 'heading', level: 2, content: 'Criando Conteúdo' },
262
+ { type: 'paragraph', content: LOREM_LONG },
263
+ { type: 'heading', level: 2, content: 'Deploy' },
264
+ { type: 'paragraph', content: LOREM_IPSUM },
265
+ ]),
266
+ },
267
+ ];
268
+ let postsCreated = 0;
269
+ for (const post of posts) {
270
+ const result = await sql.unsafe(`INSERT INTO content (tenant_id, type, title, slug, body, excerpt, status, author_id, published_at, created_at, updated_at)
271
+ VALUES ($1, $2, $3, $4, to_jsonb($5::text), $6, 'PUBLISHED', $7, $8, $9, $10)
272
+ ON CONFLICT (tenant_id, type, slug) DO UPDATE SET
273
+ title = EXCLUDED.title,
274
+ body = to_jsonb(EXCLUDED.body::text),
275
+ excerpt = EXCLUDED.excerpt,
276
+ status = EXCLUDED.status,
277
+ author_id = EXCLUDED.author_id,
278
+ published_at = EXCLUDED.published_at,
279
+ updated_at = EXCLUDED.updated_at
280
+ RETURNING id`, [tenantId, post.type, post.title, post.slug, JSON.stringify(post.body), post.excerpt, authorId, now, now, now]);
281
+ postsCreated += result.length;
282
+ }
283
+ // ---- MENUS ----
284
+ const headerMenuItems = [
285
+ { type: 'home', label: 'Início', url: '/' },
286
+ { type: 'page', label: 'Sobre', url: '/sobre', contentId: pageIds['sobre'] },
287
+ { type: 'page', label: 'Blog', url: '/blog', contentId: pageIds['blog'] },
288
+ ];
289
+ const footerMenuItems = [
290
+ { type: 'custom', label: 'Contato', url: '/#contato' },
291
+ { type: 'custom', label: 'Privacidade', url: '/privacidade' },
292
+ ];
293
+ let menusCreated = 0;
294
+ for (const [slug, name, items] of [
295
+ ['header', 'Menu Principal', headerMenuItems],
296
+ ['footer', 'Rodapé', footerMenuItems],
297
+ ]) {
298
+ const result = await sql.unsafe(`INSERT INTO menus (tenant_id, name, slug, items)
299
+ VALUES ($1, $2, $3, $4::jsonb)
300
+ ON CONFLICT (tenant_id, slug) DO UPDATE SET
301
+ name = EXCLUDED.name,
302
+ items = EXCLUDED.items
303
+ RETURNING id`, [tenantId, name, slug, items]);
304
+ menusCreated += result.length;
305
+ }
306
+ // ---- SETTINGS DE LEITURA (Static Front Page) ----
307
+ let readingSettingsCreated = 0;
308
+ if (pageIds['home'] && pageIds['blog']) {
309
+ for (const [key, value] of [
310
+ ['static_front_page', pageIds['home']],
311
+ ['page_for_posts', pageIds['blog']],
312
+ ]) {
313
+ const result = await sql.unsafe(`INSERT INTO settings (tenant_id, key, value, "group", type)
314
+ VALUES ($1, $2, to_jsonb($3::text), 'reading', 'string')
315
+ ON CONFLICT (key, tenant_id) DO UPDATE SET value = to_jsonb($3::text)
316
+ RETURNING id`, [tenantId, key, value]);
317
+ readingSettingsCreated += result.length;
318
+ }
319
+ }
320
+ return { pages: pagesCreated, posts: postsCreated, menus: menusCreated, readingSettings: readingSettingsCreated };
321
+ }
68
322
  //# sourceMappingURL=seed.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"seed.js","sourceRoot":"","sources":["../../src/migrations/seed.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,2EAA2E;AAC3E,gDAAgD;AAChD,wEAAwE;AACxE,kBAAkB;AAClB,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAE7E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKjD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE;IAC5C,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE;IAC/C,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;IAClC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE;IACjC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;CAC1B,CAAC;AAEX,kFAAkF;AAClF,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE;IACvD,EAAE,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,8BAA8B,EAAE,IAAI,EAAE,QAAQ,EAAE;IACjF,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE;IACnD,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,QAAQ,EAAE;CACvD,CAAC;AAEX,0FAA0F;AAC1F,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAW,aAAa,EAAE;IAC/D,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,oEAAoE;QACpE,qEAAqE;QACrE,mEAAmE;QACnE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,MAAM,CAC3B;;;oBAGc,EACd,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CACvB,CAAC;QACF,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,MAAW,aAAa,EAAE;IAE1B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;QACjC,uEAAuE;QACvE,8DAA8D;QAC9D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,MAAM,CAC3B;;;oBAGc,EACd,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CACnC,CAAC;QACF,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAW,aAAa,EAAE;IAE1B,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"seed.js","sourceRoot":"","sources":["../../src/migrations/seed.ts"],"names":[],"mappings":"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"}
@@ -536,6 +536,34 @@ CREATE TABLE IF NOT EXISTS webhooks (
536
536
  -- mantidos para que instalações existentes migrem sem perder seus segredos.
537
537
  ALTER TABLE webhooks ADD COLUMN IF NOT EXISTS auth_type VARCHAR(30) NOT NULL DEFAULT 'hmac_sha256';
538
538
  ALTER TABLE webhooks ADD COLUMN IF NOT EXISTS auth_config JSONB NOT NULL DEFAULT '{}'::jsonb;
539
+
540
+ -- ============================================================
541
+ -- Webhook hardening (Item 19 — rotação de segredos + dead-letter)
542
+ -- ============================================================
543
+ CREATE TABLE IF NOT EXISTS webhook_secrets (
544
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
545
+ webhook_id UUID NOT NULL REFERENCES webhooks(id) ON DELETE CASCADE,
546
+ secret VARCHAR(255) NOT NULL,
547
+ version INT NOT NULL DEFAULT 1,
548
+ is_active BOOLEAN NOT NULL DEFAULT true,
549
+ rotated_at TIMESTAMPTZ,
550
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
551
+ UNIQUE(webhook_id, version)
552
+ );
553
+
554
+ CREATE INDEX IF NOT EXISTS idx_webhook_secrets_webhook ON webhook_secrets(webhook_id, is_active);
555
+
556
+ CREATE TABLE IF NOT EXISTS webhook_dead_letters (
557
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
558
+ webhook_id UUID NOT NULL REFERENCES webhooks(id) ON DELETE CASCADE,
559
+ event VARCHAR(191) NOT NULL,
560
+ payload JSONB NOT NULL,
561
+ error TEXT,
562
+ attempts INT NOT NULL DEFAULT 1,
563
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
564
+ );
565
+
566
+ CREATE INDEX IF NOT EXISTS idx_webhook_dead_letters_webhook ON webhook_dead_letters(webhook_id, created_at);
539
567
  UPDATE webhooks
540
568
  SET auth_config = jsonb_build_object('secret', secret)
541
569
  WHERE auth_type = 'hmac_sha256' AND auth_config = '{}'::jsonb AND secret <> '';
@@ -779,6 +807,103 @@ CREATE TABLE IF NOT EXISTS content_taxonomy_terms (
779
807
  CREATE INDEX IF NOT EXISTS idx_content_terms_content ON content_taxonomy_terms(content_id);
780
808
  CREATE INDEX IF NOT EXISTS idx_content_terms_term ON content_taxonomy_terms(term_id);
781
809
 
810
+ -- ============================================================
811
+ -- Comments (Item 11 — paridade WordPress: comentários moderados, thread)
812
+ -- ============================================================
813
+ CREATE TABLE IF NOT EXISTS comments (
814
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
815
+ tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
816
+ content_id UUID NOT NULL REFERENCES content(id) ON DELETE CASCADE,
817
+ parent_id UUID REFERENCES comments(id) ON DELETE CASCADE,
818
+ author_name VARCHAR(255) NOT NULL,
819
+ author_email VARCHAR(255),
820
+ author_url VARCHAR(500),
821
+ author_id UUID REFERENCES users(id) ON DELETE SET NULL,
822
+ body TEXT NOT NULL,
823
+ status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
824
+ ip_address VARCHAR(64),
825
+ user_agent VARCHAR(500),
826
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
827
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
828
+ );
829
+
830
+ CREATE INDEX IF NOT EXISTS idx_comments_content_status ON comments(content_id, status);
831
+ CREATE INDEX IF NOT EXISTS idx_comments_tenant_status ON comments(tenant_id, status);
832
+ CREATE INDEX IF NOT EXISTS idx_comments_parent ON comments(parent_id);
833
+
834
+ CREATE TABLE IF NOT EXISTS comment_meta (
835
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
836
+ comment_id UUID NOT NULL REFERENCES comments(id) ON DELETE CASCADE,
837
+ key VARCHAR(191) NOT NULL,
838
+ value JSONB,
839
+ UNIQUE(comment_id, key)
840
+ );
841
+
842
+ ALTER TABLE comments ENABLE ROW LEVEL SECURITY;
843
+ ALTER TABLE comments FORCE ROW LEVEL SECURITY;
844
+ DO $$
845
+ BEGIN
846
+ IF NOT EXISTS (
847
+ SELECT 1 FROM pg_policies
848
+ WHERE policyname = 'tenant_isolation_comments' AND tablename = 'comments'
849
+ ) THEN
850
+ CREATE POLICY tenant_isolation_comments ON comments
851
+ USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid OR tenant_id IS NULL);
852
+ END IF;
853
+ END $$;
854
+
855
+ ALTER TABLE comment_meta ENABLE ROW LEVEL SECURITY;
856
+ ALTER TABLE comment_meta FORCE ROW LEVEL SECURITY;
857
+ DO $$
858
+ BEGIN
859
+ IF NOT EXISTS (
860
+ SELECT 1 FROM pg_policies
861
+ WHERE policyname = 'tenant_isolation_comment_meta' AND tablename = 'comment_meta'
862
+ ) THEN
863
+ CREATE POLICY tenant_isolation_comment_meta ON comment_meta
864
+ USING (EXISTS (
865
+ SELECT 1 FROM comments c
866
+ WHERE c.id = comment_meta.comment_id
867
+ AND (c.tenant_id = current_setting('app.current_tenant_id', true)::uuid OR c.tenant_id IS NULL)
868
+ ));
869
+ END IF;
870
+ END $$;
871
+
872
+ -- ============================================================
873
+ -- Mails (Item 12 — paridade WordPress: outbox durável para api.mail.send)
874
+ -- ============================================================
875
+ CREATE TABLE IF NOT EXISTS mails (
876
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
877
+ tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
878
+ plugin_name VARCHAR(255) NOT NULL,
879
+ to_email VARCHAR(320) NOT NULL,
880
+ subject VARCHAR(998) NOT NULL,
881
+ html TEXT,
882
+ text TEXT,
883
+ template VARCHAR(191),
884
+ params JSONB,
885
+ status VARCHAR(20) NOT NULL DEFAULT 'QUEUED',
886
+ attempts INT NOT NULL DEFAULT 0,
887
+ error TEXT,
888
+ sent_at TIMESTAMPTZ,
889
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
890
+ );
891
+
892
+ CREATE INDEX IF NOT EXISTS idx_mails_tenant_status ON mails(tenant_id, status);
893
+
894
+ ALTER TABLE mails ENABLE ROW LEVEL SECURITY;
895
+ ALTER TABLE mails FORCE ROW LEVEL SECURITY;
896
+ DO $$
897
+ BEGIN
898
+ IF NOT EXISTS (
899
+ SELECT 1 FROM pg_policies
900
+ WHERE policyname = 'tenant_isolation_mails' AND tablename = 'mails'
901
+ ) THEN
902
+ CREATE POLICY tenant_isolation_mails ON mails
903
+ USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid OR tenant_id IS NULL);
904
+ END IF;
905
+ END $$;
906
+
782
907
  ALTER TABLE taxonomy_terms ENABLE ROW LEVEL SECURITY;
783
908
  ALTER TABLE taxonomy_terms FORCE ROW LEVEL SECURITY;
784
909
  ALTER TABLE content_taxonomy_terms ENABLE ROW LEVEL SECURITY;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oktis-works/database",
3
- "version": "0.7.1",
3
+ "version": "0.9.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -19,8 +19,8 @@
19
19
  "db:rollback": "node --loader ts-node/esm src/migrations/runner.ts rollback"
20
20
  },
21
21
  "dependencies": {
22
- "@oktis-works/types": "^0.8.0",
23
- "@oktis-works/config": "^0.6.3",
22
+ "@oktis-works/types": "^0.9.0",
23
+ "@oktis-works/config": "^0.6.4",
24
24
  "postgres": "3.4.0"
25
25
  },
26
26
  "devDependencies": {