@sonatel-os/strapi-plugin-tcg 0.3.1 → 0.3.2
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/server/index.js +56 -9
- package/dist/server/index.mjs +56 -9
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -235,14 +235,28 @@ const ACTIONS = [
|
|
|
235
235
|
{ section: "plugins", uid: RBAC.PLAYERS_READ, displayName: "Read players" },
|
|
236
236
|
{ section: "plugins", uid: RBAC.PLAYERS_WRITE, displayName: "Deactivate players, grant cards" },
|
|
237
237
|
{ section: "plugins", uid: RBAC.REDEMPTIONS_READ, displayName: "Read redemptions" },
|
|
238
|
-
{
|
|
238
|
+
{
|
|
239
|
+
section: "plugins",
|
|
240
|
+
uid: RBAC.REDEMPTIONS_FULFILL,
|
|
241
|
+
displayName: "Fulfill or cancel redemptions (booth)"
|
|
242
|
+
},
|
|
239
243
|
{ section: "plugins", uid: RBAC.AUDIT_READ, displayName: "Read the pull audit log" },
|
|
240
244
|
{ section: "plugins", uid: RBAC.REWARDS_READ, displayName: "Read the reward catalog" },
|
|
241
245
|
{ section: "plugins", uid: RBAC.REWARDS_WRITE, displayName: "Edit the reward catalog" },
|
|
242
246
|
{ section: "plugins", uid: RBAC.LIVE_READ, displayName: "Read live boosts" },
|
|
243
247
|
{ section: "plugins", uid: RBAC.LIVE_WRITE, displayName: "Create and edit live boosts" },
|
|
244
|
-
{
|
|
245
|
-
|
|
248
|
+
{
|
|
249
|
+
section: "settings",
|
|
250
|
+
category: CATEGORY,
|
|
251
|
+
uid: RBAC.SETTINGS_READ,
|
|
252
|
+
displayName: "Read settings"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
section: "settings",
|
|
256
|
+
category: CATEGORY,
|
|
257
|
+
uid: RBAC.SETTINGS_WRITE,
|
|
258
|
+
displayName: "Edit settings"
|
|
259
|
+
}
|
|
246
260
|
].map((a) => ({ ...a, pluginName: PLUGIN_ID }));
|
|
247
261
|
const timers = [];
|
|
248
262
|
const UNIQUE_COLUMNS = [
|
|
@@ -250,21 +264,46 @@ const UNIQUE_COLUMNS = [
|
|
|
250
264
|
["plugin::tcg.player", "code"],
|
|
251
265
|
["plugin::tcg.redemption", "code"]
|
|
252
266
|
];
|
|
267
|
+
const hasIndex = async (knex, table, name) => {
|
|
268
|
+
const client = String(knex.client?.config?.client ?? "");
|
|
269
|
+
if (/mysql/.test(client)) {
|
|
270
|
+
const rows2 = await knex.raw("SHOW INDEX FROM ?? WHERE Key_name = ?", [table, name]);
|
|
271
|
+
return (rows2?.[0] ?? []).length > 0;
|
|
272
|
+
}
|
|
273
|
+
if (/pg|postgres/.test(client)) {
|
|
274
|
+
const rows2 = await knex.raw("SELECT 1 FROM pg_indexes WHERE tablename = ? AND indexname = ?", [
|
|
275
|
+
table,
|
|
276
|
+
name
|
|
277
|
+
]);
|
|
278
|
+
return (rows2?.rows ?? []).length > 0;
|
|
279
|
+
}
|
|
280
|
+
const rows = await knex.raw("PRAGMA index_list(??)", [table]);
|
|
281
|
+
return (rows ?? []).some((r) => r.name === name);
|
|
282
|
+
};
|
|
253
283
|
const ensureUniqueIndexes = async (strapi) => {
|
|
284
|
+
const knex = strapi.db.connection;
|
|
254
285
|
for (const [uid, column] of UNIQUE_COLUMNS) {
|
|
255
286
|
const table = strapi.db.metadata.get(uid)?.tableName;
|
|
256
287
|
if (!table) continue;
|
|
257
288
|
const name = `${table}_${column}_tcg_uq`;
|
|
258
289
|
try {
|
|
259
|
-
await
|
|
290
|
+
if (await hasIndex(knex, table, name)) continue;
|
|
291
|
+
await knex.schema.alterTable(table, (t) => t.unique([column], { indexName: name }));
|
|
292
|
+
strapi.log.info(`${LOG_PREFIX} unique index ${name} created`);
|
|
260
293
|
} catch (err) {
|
|
261
|
-
if (!/exist|duplicate/i.test(err.message))
|
|
294
|
+
if (!/exist|duplicate/i.test(err.message))
|
|
295
|
+
strapi.log.warn(`${LOG_PREFIX} unique index ${name}: ${err.message}`);
|
|
262
296
|
}
|
|
263
297
|
}
|
|
264
298
|
};
|
|
265
299
|
const bootstrap = async ({ strapi }) => {
|
|
266
300
|
await strapi.service("admin::permission").actionProvider.registerMany(ACTIONS);
|
|
267
|
-
|
|
301
|
+
setTimeout(
|
|
302
|
+
() => ensureUniqueIndexes(strapi).catch(
|
|
303
|
+
(err) => strapi.log.warn(`${LOG_PREFIX} unique indexes: ${err.message}`)
|
|
304
|
+
),
|
|
305
|
+
5e3
|
|
306
|
+
);
|
|
268
307
|
const plugin = strapi.plugin(PLUGIN_ID);
|
|
269
308
|
if (plugin.service("settings").sweepsEnabled()) {
|
|
270
309
|
const safe = (label, fn) => async () => {
|
|
@@ -275,13 +314,21 @@ const bootstrap = async ({ strapi }) => {
|
|
|
275
314
|
strapi.log.warn(`${LOG_PREFIX} sweep ${label} failed: ${err.message}`);
|
|
276
315
|
}
|
|
277
316
|
};
|
|
278
|
-
const nonceTimer = setInterval(
|
|
279
|
-
|
|
317
|
+
const nonceTimer = setInterval(
|
|
318
|
+
safe("nonces", () => plugin.service("qr").sweep()),
|
|
319
|
+
NONCE_SWEEP_INTERVAL_MS
|
|
320
|
+
);
|
|
321
|
+
const tradeTimer = setInterval(
|
|
322
|
+
safe("expired offers", () => plugin.service("trade").sweep()),
|
|
323
|
+
TRADE_SWEEP_INTERVAL_MS
|
|
324
|
+
);
|
|
280
325
|
nonceTimer.unref();
|
|
281
326
|
tradeTimer.unref();
|
|
282
327
|
timers.push(nonceTimer, tradeTimer);
|
|
283
328
|
}
|
|
284
|
-
strapi.log.info(
|
|
329
|
+
strapi.log.info(
|
|
330
|
+
`${LOG_PREFIX} ready — ${ACTIONS.length} RBAC actions, content API at /api/${PLUGIN_ID}`
|
|
331
|
+
);
|
|
285
332
|
};
|
|
286
333
|
const stopTimers = () => {
|
|
287
334
|
while (timers.length) clearInterval(timers.pop());
|
package/dist/server/index.mjs
CHANGED
|
@@ -234,14 +234,28 @@ const ACTIONS = [
|
|
|
234
234
|
{ section: "plugins", uid: RBAC.PLAYERS_READ, displayName: "Read players" },
|
|
235
235
|
{ section: "plugins", uid: RBAC.PLAYERS_WRITE, displayName: "Deactivate players, grant cards" },
|
|
236
236
|
{ section: "plugins", uid: RBAC.REDEMPTIONS_READ, displayName: "Read redemptions" },
|
|
237
|
-
{
|
|
237
|
+
{
|
|
238
|
+
section: "plugins",
|
|
239
|
+
uid: RBAC.REDEMPTIONS_FULFILL,
|
|
240
|
+
displayName: "Fulfill or cancel redemptions (booth)"
|
|
241
|
+
},
|
|
238
242
|
{ section: "plugins", uid: RBAC.AUDIT_READ, displayName: "Read the pull audit log" },
|
|
239
243
|
{ section: "plugins", uid: RBAC.REWARDS_READ, displayName: "Read the reward catalog" },
|
|
240
244
|
{ section: "plugins", uid: RBAC.REWARDS_WRITE, displayName: "Edit the reward catalog" },
|
|
241
245
|
{ section: "plugins", uid: RBAC.LIVE_READ, displayName: "Read live boosts" },
|
|
242
246
|
{ section: "plugins", uid: RBAC.LIVE_WRITE, displayName: "Create and edit live boosts" },
|
|
243
|
-
{
|
|
244
|
-
|
|
247
|
+
{
|
|
248
|
+
section: "settings",
|
|
249
|
+
category: CATEGORY,
|
|
250
|
+
uid: RBAC.SETTINGS_READ,
|
|
251
|
+
displayName: "Read settings"
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
section: "settings",
|
|
255
|
+
category: CATEGORY,
|
|
256
|
+
uid: RBAC.SETTINGS_WRITE,
|
|
257
|
+
displayName: "Edit settings"
|
|
258
|
+
}
|
|
245
259
|
].map((a) => ({ ...a, pluginName: PLUGIN_ID }));
|
|
246
260
|
const timers = [];
|
|
247
261
|
const UNIQUE_COLUMNS = [
|
|
@@ -249,21 +263,46 @@ const UNIQUE_COLUMNS = [
|
|
|
249
263
|
["plugin::tcg.player", "code"],
|
|
250
264
|
["plugin::tcg.redemption", "code"]
|
|
251
265
|
];
|
|
266
|
+
const hasIndex = async (knex, table, name) => {
|
|
267
|
+
const client = String(knex.client?.config?.client ?? "");
|
|
268
|
+
if (/mysql/.test(client)) {
|
|
269
|
+
const rows2 = await knex.raw("SHOW INDEX FROM ?? WHERE Key_name = ?", [table, name]);
|
|
270
|
+
return (rows2?.[0] ?? []).length > 0;
|
|
271
|
+
}
|
|
272
|
+
if (/pg|postgres/.test(client)) {
|
|
273
|
+
const rows2 = await knex.raw("SELECT 1 FROM pg_indexes WHERE tablename = ? AND indexname = ?", [
|
|
274
|
+
table,
|
|
275
|
+
name
|
|
276
|
+
]);
|
|
277
|
+
return (rows2?.rows ?? []).length > 0;
|
|
278
|
+
}
|
|
279
|
+
const rows = await knex.raw("PRAGMA index_list(??)", [table]);
|
|
280
|
+
return (rows ?? []).some((r) => r.name === name);
|
|
281
|
+
};
|
|
252
282
|
const ensureUniqueIndexes = async (strapi) => {
|
|
283
|
+
const knex = strapi.db.connection;
|
|
253
284
|
for (const [uid, column] of UNIQUE_COLUMNS) {
|
|
254
285
|
const table = strapi.db.metadata.get(uid)?.tableName;
|
|
255
286
|
if (!table) continue;
|
|
256
287
|
const name = `${table}_${column}_tcg_uq`;
|
|
257
288
|
try {
|
|
258
|
-
await
|
|
289
|
+
if (await hasIndex(knex, table, name)) continue;
|
|
290
|
+
await knex.schema.alterTable(table, (t) => t.unique([column], { indexName: name }));
|
|
291
|
+
strapi.log.info(`${LOG_PREFIX} unique index ${name} created`);
|
|
259
292
|
} catch (err) {
|
|
260
|
-
if (!/exist|duplicate/i.test(err.message))
|
|
293
|
+
if (!/exist|duplicate/i.test(err.message))
|
|
294
|
+
strapi.log.warn(`${LOG_PREFIX} unique index ${name}: ${err.message}`);
|
|
261
295
|
}
|
|
262
296
|
}
|
|
263
297
|
};
|
|
264
298
|
const bootstrap = async ({ strapi }) => {
|
|
265
299
|
await strapi.service("admin::permission").actionProvider.registerMany(ACTIONS);
|
|
266
|
-
|
|
300
|
+
setTimeout(
|
|
301
|
+
() => ensureUniqueIndexes(strapi).catch(
|
|
302
|
+
(err) => strapi.log.warn(`${LOG_PREFIX} unique indexes: ${err.message}`)
|
|
303
|
+
),
|
|
304
|
+
5e3
|
|
305
|
+
);
|
|
267
306
|
const plugin = strapi.plugin(PLUGIN_ID);
|
|
268
307
|
if (plugin.service("settings").sweepsEnabled()) {
|
|
269
308
|
const safe = (label, fn) => async () => {
|
|
@@ -274,13 +313,21 @@ const bootstrap = async ({ strapi }) => {
|
|
|
274
313
|
strapi.log.warn(`${LOG_PREFIX} sweep ${label} failed: ${err.message}`);
|
|
275
314
|
}
|
|
276
315
|
};
|
|
277
|
-
const nonceTimer = setInterval(
|
|
278
|
-
|
|
316
|
+
const nonceTimer = setInterval(
|
|
317
|
+
safe("nonces", () => plugin.service("qr").sweep()),
|
|
318
|
+
NONCE_SWEEP_INTERVAL_MS
|
|
319
|
+
);
|
|
320
|
+
const tradeTimer = setInterval(
|
|
321
|
+
safe("expired offers", () => plugin.service("trade").sweep()),
|
|
322
|
+
TRADE_SWEEP_INTERVAL_MS
|
|
323
|
+
);
|
|
279
324
|
nonceTimer.unref();
|
|
280
325
|
tradeTimer.unref();
|
|
281
326
|
timers.push(nonceTimer, tradeTimer);
|
|
282
327
|
}
|
|
283
|
-
strapi.log.info(
|
|
328
|
+
strapi.log.info(
|
|
329
|
+
`${LOG_PREFIX} ready — ${ACTIONS.length} RBAC actions, content API at /api/${PLUGIN_ID}`
|
|
330
|
+
);
|
|
284
331
|
};
|
|
285
332
|
const stopTimers = () => {
|
|
286
333
|
while (timers.length) clearInterval(timers.pop());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sonatel-os/strapi-plugin-tcg",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "A full trading-card-game module for Strapi v5: seasons, packs, cards, pulls, trades, redemptions — with admin screens and RBAC.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "LPIX-11 <mohamed.johnson@orange-sonatel.com>",
|