mirror of
https://github.com/nestriness/nestri.git
synced 2026-09-20 01:35:19 +03:00
Squashes the current state of the internal working tree onto this history. The two trees had grown apart with no common ancestor, so this is a content sync rather than a merge, and the published history is preserved rather than rewritten — a force-push here would break every existing fork and clone to no benefit. What lands: - Waitlist: API route, core module, and migration 0006 alongside game aliases. - User verification. - CI, oxfmt config, editor settings. - Assorted fixes across the API routes and core modules. The repository's own README, the wordmark and the per-package READMEs are kept from this side; the internal tree had dropped them and they are what a stranger arriving here reads first. The marketing site in the internal tree is deliberately not here. It is a separate product with its own repo and its own licence, and this repo is the open one — a closed component does not belong in it regardless of how convenient the directory looked. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
130 lines
3.5 KiB
TypeScript
130 lines
3.5 KiB
TypeScript
import * as Alchemy from 'alchemy';
|
|
import { adopt } from 'alchemy/AdoptPolicy';
|
|
import * as Cloudflare from 'alchemy/Cloudflare';
|
|
import { Redacted } from 'effect';
|
|
import * as Effect from 'effect/Effect';
|
|
|
|
const steamApiKey = Redacted.make(process.env.STEAM_API_KEY!);
|
|
const sshAuthKey = process.env.SSH_AUTH_KEY || 'dev-ssh-auth-key-change-in-prod';
|
|
const adminSharedSecret =
|
|
process.env.ADMIN_SHARED_SECRET || 'dev-admin-shared-secret-change-in-prod';
|
|
|
|
const AuthStorage = Cloudflare.KV.Namespace('auth-storage');
|
|
|
|
const Database = Effect.gen(function* () {
|
|
const { stage } = yield* Alchemy.Stack;
|
|
const database = stage === 'production' ? 'defaultdb' : 'sandbox';
|
|
return yield* Cloudflare.Hyperdrive.Connection('db', {
|
|
origin: {
|
|
scheme: 'postgres',
|
|
host: 'public-nestri-pg-1-atdogthbymao.db.upclouddatabases.com',
|
|
port: 11569,
|
|
database,
|
|
user: 'upadmin',
|
|
password: Redacted.make(process.env.DATABASE_PASSWORD!)
|
|
},
|
|
dev: {
|
|
scheme: 'postgres',
|
|
host: 'localhost',
|
|
port: 5432,
|
|
database: 'nestri',
|
|
user: 'postgres',
|
|
sslmode: 'disable',
|
|
password: Redacted.make('postgres')
|
|
}
|
|
});
|
|
});
|
|
|
|
export const Auth = Effect.gen(function* () {
|
|
const { stage } = yield* Alchemy.Stack;
|
|
const isPermanent = ['production', 'sandbox', 'dev'].includes(stage);
|
|
return yield* Cloudflare.Worker('auth', {
|
|
main: 'apps/auth/src/index.ts',
|
|
compatibility: { flags: ['nodejs_compat'] },
|
|
env: {
|
|
AuthStorage,
|
|
HYPERDRIVE: Database,
|
|
STEAM_API_KEY: steamApiKey,
|
|
SSH_AUTH_KEY: sshAuthKey
|
|
},
|
|
...(isPermanent ? { observability: { enabled: true } } : {})
|
|
});
|
|
});
|
|
|
|
export const Api = Effect.gen(function* () {
|
|
const { stage } = yield* Alchemy.Stack;
|
|
const isPermanent = ['production', 'sandbox', 'dev'].includes(stage);
|
|
const prefix = stage === 'production' ? '' : `${stage}.`;
|
|
const authDomain = ['production', 'sandbox'].includes(stage)
|
|
? `${prefix}auth.nestri.io`
|
|
: undefined;
|
|
return yield* Cloudflare.Worker('api', {
|
|
main: 'apps/api/app/index.ts',
|
|
compatibility: { flags: ['nodejs_compat'] },
|
|
env: {
|
|
AUTH: Auth,
|
|
AUTH_ISSUER_URL: authDomain ? `https://${authDomain}` : 'http://localhost:1337',
|
|
HYPERDRIVE: Database,
|
|
STEAM_API_KEY: steamApiKey,
|
|
ADMIN_SHARED_SECRET: adminSharedSecret
|
|
},
|
|
...(isPermanent ? { observability: { enabled: true } } : {})
|
|
});
|
|
});
|
|
|
|
export default Alchemy.Stack(
|
|
'nestri',
|
|
{
|
|
providers: Cloudflare.providers(),
|
|
state: Alchemy.localState()
|
|
},
|
|
Effect.gen(function* () {
|
|
const { stage } = yield* Alchemy.Stack;
|
|
|
|
yield* Database;
|
|
const auth = yield* Auth;
|
|
const api = yield* Api;
|
|
|
|
if (stage === 'production' || stage === 'sandbox') {
|
|
const zone = yield* Cloudflare.Zone.Zone('zone', {
|
|
name: 'nestri.io'
|
|
}).pipe(adopt(true));
|
|
|
|
const prefix = stage === 'production' ? '' : `${stage}.`;
|
|
|
|
yield* Cloudflare.DNS.Record('auth-dns', {
|
|
zoneId: zone.zoneId,
|
|
name: `${prefix}auth.nestri.io`,
|
|
type: 'AAAA',
|
|
content: '100::',
|
|
proxied: true
|
|
});
|
|
|
|
yield* Cloudflare.DNS.Record('api-dns', {
|
|
zoneId: zone.zoneId,
|
|
name: `${prefix}api.nestri.io`,
|
|
type: 'AAAA',
|
|
content: '100::',
|
|
proxied: true
|
|
});
|
|
|
|
yield* Cloudflare.Workers.WorkerRoute('auth-route', {
|
|
zoneId: zone.zoneId,
|
|
pattern: `${prefix}auth.nestri.io/*`,
|
|
script: auth.workerName
|
|
});
|
|
|
|
yield* Cloudflare.Workers.WorkerRoute('api-route', {
|
|
zoneId: zone.zoneId,
|
|
pattern: `${prefix}api.nestri.io/*`,
|
|
script: api.workerName
|
|
});
|
|
}
|
|
|
|
return {
|
|
authUrl: auth.url.as<string>(),
|
|
apiUrl: api.url.as<string>()
|
|
};
|
|
})
|
|
);
|