Files
Felitendo ff0d3108fe feat: merge the web dashboard into the monorepo as ftstore admin
FTStore now holds both halves of the product:

  ios/   the swift app — the fork of claration/Feather, unchanged apart
         from its new home
  web/   FTStore Admin, formerly its own repository. serves the
         dashboard at /admin, the ftstore.json feed and IPA downloads

app-repo.json and Images/ stay at the repo root on purpose: the former is
a published AltStore source whose raw.githubusercontent URL is what
installed copies resolve updates through, so moving it would break every
subscriber.

The admin server is renamed throughout: package ftstore-admin, images
ghcr.io/<owner>/ftstore-admin-{app,worker}, postgres role/db ftstore,
session cookie ftstore_session, temp dir /tmp/ftstore, backup type
ftstore-settings, outbound user-agent FTStoreAdmin. backups written under the old
name still import, and compose is pinned to name: ftstore so the
volume prefix does not follow the directory name.

apply-rebrand.sh gains a relocation step: upstream's tree is rooted at
the repo root while ours lives in ios/, so a merge drops Feather's files
next to ios/ and the script folds them in before renaming. it never
touches web/. still idempotent.

release tags are namespaced — v* for the app, web-v* for the server —
so a server release no longer triggers a macOS build or rewrites
app-repo.json. workflows are prefixed ios-/web- and path-filtered.
2026-08-03 10:25:03 +02:00

127 lines
3.8 KiB
TypeScript

import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
// Default settings
const defaultSettings = [
{ key: "scan_interval_minutes", value: "30", type: "number" },
{ key: "json_regen_interval_minutes", value: "60", type: "number" },
{ key: "cleanup_interval_hours", value: "24", type: "number" },
{ key: "max_versions_per_app", value: "5", type: "number" },
{ key: "log_retention_days", value: "30", type: "number" },
{ key: "github_release_scan_limit", value: "5", type: "number" },
{ key: "auto_scan_enabled", value: "true", type: "boolean" },
{ key: "auto_json_regen", value: "true", type: "boolean" },
{ key: "auto_cleanup", value: "true", type: "boolean" },
{
key: "source_name",
value: "FTStore",
type: "string",
},
{
key: "source_description",
value: "Automated iOS IPA distribution",
type: "string",
},
{ key: "site_domain", value: "", type: "string" },
{ key: "telegram_api_id", value: "", type: "string" },
{ key: "telegram_api_hash", value: "", type: "string" },
{ key: "telegram_phone", value: "", type: "string" },
{ key: "github_token", value: "", type: "string" },
{ key: "github_owner", value: "", type: "string" },
{ key: "github_repo", value: "", type: "string" },
{ key: "github_branch", value: "main", type: "string" },
{ key: "ftstore_app_github_token", value: "", type: "string" },
{ key: "appstore_country", value: "us", type: "string" },
{ key: "temp_dir", value: "/tmp/ftstore", type: "string" },
{ key: "storage_dir", value: "/app/storage", type: "string" },
{ key: "max_storage_gb", value: "0", type: "number" },
{ key: "download_require_app_ua", value: "true", type: "boolean" },
{
key: "known_tweaks",
value: JSON.stringify([]),
type: "json",
},
];
for (const setting of defaultSettings) {
await prisma.setting.upsert({
where: { key: setting.key },
update: {},
create: setting,
});
}
// Common entitlement descriptions
const privacyDescriptions = [
{
key: "NSCameraUsageDescription",
description: "Access to camera for taking photos and videos",
},
{
key: "NSMicrophoneUsageDescription",
description: "Access to microphone for audio recording",
},
{
key: "NSPhotoLibraryUsageDescription",
description: "Access to photo library for saving and selecting images",
},
{
key: "NSPhotoLibraryAddUsageDescription",
description: "Access to save photos to your library",
},
{
key: "NSLocationWhenInUseUsageDescription",
description: "Access to location while using the app",
},
{
key: "NSLocationAlwaysUsageDescription",
description: "Access to location in the background",
},
{
key: "NSContactsUsageDescription",
description: "Access to contacts",
},
{
key: "NSCalendarsUsageDescription",
description: "Access to calendar events",
},
{
key: "NSFaceIDUsageDescription",
description: "Face ID for authentication",
},
{
key: "NSBluetoothAlwaysUsageDescription",
description: "Access to Bluetooth for connecting devices",
},
{
key: "NSLocalNetworkUsageDescription",
description: "Access to local network for device discovery",
},
{
key: "NSUserTrackingUsageDescription",
description: "Permission to track activity across apps and websites",
},
];
for (const desc of privacyDescriptions) {
await prisma.privacyDescriptionCache.upsert({
where: { key: desc.key },
update: {},
create: desc,
});
}
console.log("Seed completed successfully");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});