File size: 3,433 Bytes
03cdf80
 
 
 
 
 
 
 
 
 
3d8743c
 
 
 
 
 
 
 
 
 
 
 
 
 
03cdf80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f61d6ba
 
03cdf80
 
 
f61d6ba
 
 
 
03cdf80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d8743c
 
03cdf80
 
 
 
 
 
 
 
 
3d8743c
 
 
03cdf80
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
require('dotenv').config();
const Fastify = require('fastify');
const cors = require('@fastify/cors');
const swagger = require('@fastify/swagger');
const swaggerUi = require('@fastify/swagger-ui');

const accountRoutes = require('./routes/accounts');
const domainRoutes = require('./routes/domains');
const dnsRoutes = require('./routes/dns');
const { startTokenScheduler } = require('../lib/token-scheduler');
const { startWorker } = require('../lib/job-worker');
const { execSync } = require('child_process');

async function setupDatabase() {
  console.log('Setting up database...');
  try {
    execSync('npx prisma generate', { stdio: 'inherit' });
    execSync('npx prisma db push --accept-data-loss', { stdio: 'inherit' });
    console.log('Database setup complete');
  } catch (err) {
    console.error('Database setup failed:', err.message);
    throw err;
  }
}

const fastify = Fastify({
  logger: true
});

async function build() {
  await fastify.register(cors, {
    origin: true
  });

  await fastify.register(swagger, {
    openapi: {
      info: {
        title: 'Zone.ID Domain Registration API',
        description: 'API for managing zone.id and nett.to domain registrations and DNS records',
        version: '1.0.0'
      },
      servers: [
        { url: 'http://localhost:5000', description: 'Development server' }
      ],
      components: {
        securitySchemes: {
          apiKey: {
            type: 'apiKey',
            name: 'X-API-Key',
            in: 'header'
          }
        }
      }
    }
  });

  await fastify.register(swaggerUi, {
    routePrefix: '/docs',
    uiConfig: {
      docExpansion: 'list',
      deepLinking: false
    }
  });

  fastify.addHook('onRequest', async (request, reply) => {
    const publicRoutes = ['/docs', '/docs/', '/docs/json', '/docs/yaml', '/health', '/'];
    const isPublic = publicRoutes.some(route => request.url.startsWith(route));
    
    if (isPublic) return;

    const expectedApiKey = process.env.API_KEY;
    if (!expectedApiKey) {
      return;
    }

    const apiKey = request.headers['x-api-key'];
    if (!apiKey || apiKey !== expectedApiKey) {
      reply.code(401).send({ error: 'Invalid or missing API key' });
      return;
    }
  });

  fastify.get('/', {
    schema: {
      hide: true
    }
  }, async () => {
    return {
      name: 'Zone.ID Domain Registration API',
      version: '1.0.0',
      docs: '/docs'
    };
  });

  fastify.get('/health', {
    schema: {
      hide: true
    }
  }, async () => {
    return { status: 'ok' };
  });

  await fastify.register(accountRoutes, { prefix: '/api/accounts' });
  await fastify.register(domainRoutes, { prefix: '/api/domains' });
  await fastify.register(dnsRoutes, { prefix: '/api/dns' });

  return fastify;
}

async function start() {
  try {
    await setupDatabase();
    
    const port = parseInt(process.env.PORT) || 5000;
    const host = process.env.HOST || '0.0.0.0';
    const server = await build();
    await server.listen({ port, host });
    console.log(`Server running at http://${host}:${port}`);
    console.log(`API Documentation at http://${host}:${port}/docs`);
    
    startTokenScheduler();
    console.log('Token auto-refresh scheduler started (checks every 6 hours)');
    
    startWorker();
    console.log('Domain job worker started (polling every 5 seconds)');
  } catch (err) {
    console.error(err);
    process.exit(1);
  }
}

start();