Add company-scoped brand and company settings API.

brand now carries a NOT NULL company_id (unique per (company_id, name))
with brand.list/upsert/delete backed by resolveCompanyAccess. Adds
companysetting key-value store (list/get/set/delete, frontend flag).
This commit is contained in:
seb
2026-08-01 06:59:27 +02:00
parent c839b2ba35
commit 787e411547
18 changed files with 1810 additions and 1192 deletions

View File

@@ -113,6 +113,51 @@ const MENU = {
},
],
},
companysetting: {
label: 'companysetting',
items: [
{
value: 'companysetting.list',
label: 'list',
hint: 'googleAuthId, companyId, frontendOnly? → rows',
},
{
value: 'companysetting.get',
label: 'get',
hint: 'googleAuthId, companyId, key → row',
},
{
value: 'companysetting.set',
label: 'set',
hint: 'googleAuthId, companyId, JSON setting → row',
},
{
value: 'companysetting.delete',
label: 'delete',
hint: 'googleAuthId, companyId, key',
},
],
},
brand: {
label: 'brand',
items: [
{
value: 'brand.list',
label: 'list',
hint: 'googleAuthId, companyId → rows',
},
{
value: 'brand.upsert',
label: 'upsert',
hint: 'googleAuthId, companyId, JSON brand → row',
},
{
value: 'brand.delete',
label: 'delete',
hint: 'googleAuthId, companyId, id',
},
],
},
category: {
label: 'category',
items: [
@@ -418,6 +463,139 @@ async function runMethod(client, action) {
await client.unit.delete(Number(googleAuthId), Number(companyId), si);
return ['ok', true];
}
case 'companysetting.list': {
const googleAuthId = await askInt('google_auth id');
if (googleAuthId == null) return;
const companyId = await askInt('company id');
if (companyId == null) return;
const frontendOnly = await askText('frontendOnly (true/false)', {
placeholder: 'false',
});
if (frontendOnly == null) return;
return [
'result[]',
await client.companysetting.list(Number(googleAuthId), Number(companyId), {
frontendOnly: frontendOnly.trim().toLowerCase() === 'true',
}),
];
}
case 'companysetting.get': {
const googleAuthId = await askInt('google_auth id');
if (googleAuthId == null) return;
const companyId = await askInt('company id');
if (companyId == null) return;
const key = await askText('key', {
validate: (v) => (!v?.trim() ? 'Required' : undefined),
});
if (key == null) return;
const frontendOnly = await askText('frontendOnly (true/false)', {
placeholder: 'false',
});
if (frontendOnly == null) return;
return [
'result',
await client.companysetting.get(
Number(googleAuthId),
Number(companyId),
key,
{ frontendOnly: frontendOnly.trim().toLowerCase() === 'true' },
),
];
}
case 'companysetting.set': {
const googleAuthId = await askInt('google_auth id');
if (googleAuthId == null) return;
const companyId = await askInt('company id');
if (companyId == null) return;
const settingJson = await askText('setting JSON', {
placeholder: '{"key":"theme","value":"dark","frontend":true}',
validate: (v) => {
if (!v?.trim()) return 'Required';
try {
const parsed = JSON.parse(v);
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
return 'Must be a JSON object';
}
} catch {
return 'Invalid JSON';
}
},
});
if (settingJson == null) return;
return [
'result',
await client.companysetting.set(
Number(googleAuthId),
Number(companyId),
JSON.parse(settingJson),
),
];
}
case 'companysetting.delete': {
const googleAuthId = await askInt('google_auth id');
if (googleAuthId == null) return;
const companyId = await askInt('company id');
if (companyId == null) return;
const key = await askText('key', {
validate: (v) => (!v?.trim() ? 'Required' : undefined),
});
if (key == null) return;
await client.companysetting.delete(
Number(googleAuthId),
Number(companyId),
key,
);
return ['ok', true];
}
case 'brand.list': {
const googleAuthId = await askInt('google_auth id');
if (googleAuthId == null) return;
const companyId = await askInt('company id');
if (companyId == null) return;
return [
'result[]',
await client.brand.list(Number(googleAuthId), Number(companyId)),
];
}
case 'brand.upsert': {
const googleAuthId = await askInt('google_auth id');
if (googleAuthId == null) return;
const companyId = await askInt('company id');
if (companyId == null) return;
const brandJson = await askText('brand JSON', {
placeholder: '{"name":"Nike","gsprpinfo":"..."}',
validate: (v) => {
if (!v?.trim()) return 'Required';
try {
const parsed = JSON.parse(v);
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
return 'Must be a JSON object';
}
} catch {
return 'Invalid JSON';
}
},
});
if (brandJson == null) return;
return [
'result',
await client.brand.upsert(
Number(googleAuthId),
Number(companyId),
JSON.parse(brandJson),
),
];
}
case 'brand.delete': {
const googleAuthId = await askInt('google_auth id');
if (googleAuthId == null) return;
const companyId = await askInt('company id');
if (companyId == null) return;
const id = await askInt('brand id');
if (id == null) return;
await client.brand.delete(Number(googleAuthId), Number(companyId), id);
return ['ok', true];
}
case 'lang.create': {
const iso639 = await askText('ISO 639', {
placeholder: 'de',