Skip to content

Commit

Permalink
Switch to ES modules
Browse files Browse the repository at this point in the history
Change-type: major
  • Loading branch information
Page- committed Feb 15, 2024
1 parent 6a84368 commit 54b5f54
Show file tree
Hide file tree
Showing 178 changed files with 820 additions and 778 deletions.
8 changes: 4 additions & 4 deletions config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { ConfigLoader } from '@balena/pinejs';
import * as balenaModel from './src/balena';
import { model as balenaModel } from './src/balena.js';
import {
v6AbstractSqlModel,
getV6Translations,
} from './src/translations/v6/v6';
import { getFileUploadHandler } from './src/fileupload-handler';
} from './src/translations/v6/v6.js';
import { getFileUploadHandler } from './src/fileupload-handler.js';

export = {
export default {
models: [
balenaModel,
{
Expand Down
4 changes: 2 additions & 2 deletions entry.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/bin/bash

if [ "$PRODUCTION_MODE" == "true" ]; then
exec node index.js
exec node --loader ts-node/esm/transpile-only index.js
else
exec ./node_modules/.bin/supervisor \
--no-restart-on error \
--extensions js,node,coffee,sbvr,json,sql,pegjs,ts \
--watch src \
--exec node index.js
--exec node --loader ts-node/esm/transpile-only index.js
fi
37 changes: 19 additions & 18 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const numWorkers = process.env.NUM_WORKERS || require('os').cpus().length;
const start = async () => {
// Set the desired es version for downstream modules that support it
(await import('@balena/es-version')).set('es2022');

// Support import of *.cts files
(await import('ts-node')).register({ transpileOnly: true });

await import('./init.js');
};

const numWorkers =
parseInt(process.env.NUM_WORKERS ?? '0', 10) ||
(await import('os')).cpus().length;
if (numWorkers > 1) {
const cluster = require('cluster');
const { default: cluster } = await import('cluster');
if (cluster.isPrimary) {
// Setup the RateLimiterCluster store on the master worker
const { RateLimiterClusterMaster } = require('rate-limiter-flexible');
const { RateLimiterClusterMaster } = await import('rate-limiter-flexible');
new RateLimiterClusterMaster();

console.log(`Forking ${numWorkers} workers`);
Expand All @@ -17,19 +28,9 @@ if (numWorkers > 1) {
console.log('Worker ' + worker.id + ' died, replacing it');
cluster.fork(process.env);
});
return;
} else {
await start();
}
} else {
await start();
}

// Use fast-boot to cache require lookups, speeding up startup
require('fast-boot2').start({
cacheFile: '.fast-boot.json',
});

// Set the desired es version for downstream modules that support it
require('@balena/es-version').set('es2022');

// Support `require()` of *.ts files
require('ts-node/register/transpile-only');

require('./init.ts');
60 changes: 29 additions & 31 deletions init.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import type { ApplicationType } from './src';
import type { ApplicationType } from './src/index.js';
import type { types } from '@balena/pinejs';
import { sbvrUtils, errors } from '@balena/pinejs';
import express from 'express';
import _ from 'lodash';
import config = require('./config');
import packageJson from './package.json';
import config from './config.js';
import packageJson from './package.json' assert { type: 'json' };
import { promises as fs } from 'fs';
import { TRUST_PROXY, PORT } from './src/lib/config';
import { TRUST_PROXY, PORT } from './src/lib/config.js';

const getUrl = (req: express.Request) => req.url;

async function onInitModel() {
const { updateOrInsertModel } = (
await import('./src/infra/pinejs-client-helpers/index.js')
).default;
const appTypes = (
await import('./src/features/application-types/application-types.js')
).default;
const { updateOrInsertModel } = await import(
'./src/infra/pinejs-client-helpers/index.js'
);
const appTypes = await import(
'./src/features/application-types/application-types.js'
);
const insert: types.OptionalField<ApplicationType, 'slug'> = _.cloneDeep(
appTypes.DefaultApplicationType,
);
Expand All @@ -34,20 +34,18 @@ async function onInitModel() {
}

async function onInitHooks() {
const { createAllPermissions: createAll } = (
await import('./src/infra/auth/permissions.js')
).default;
const auth = (await import('./src/lib/auth.js')).default;
const { createAllPermissions: createAll } = await import(
'./src/infra/auth/permissions.js'
);
const auth = await import('./src/lib/auth.js');
const permissionNames = _.union(
_.flatMap(auth.ROLES),
_.flatMap(auth.KEYS, 'permissions'),
);
const { setSyncSettings } = (
await import('./src/features/contracts/index.js')
).default;
const { getAccessibleDeviceTypes } = (
await import('./src/features/device-types/device-types.js')
).default;
const { setSyncSettings } = await import('./src/features/contracts/index.js');
const { getAccessibleDeviceTypes } = await import(
'./src/features/device-types/device-types.js'
);

setSyncSettings({
'hw.device-type': {
Expand Down Expand Up @@ -141,23 +139,23 @@ async function onInitHooks() {
}

async function createSuperuser() {
const { SUPERUSER_EMAIL, SUPERUSER_PASSWORD } = (
await import('./src/lib/config.js')
).default;
const { SUPERUSER_EMAIL, SUPERUSER_PASSWORD } = await import(
'./src/lib/config.js'
);

if (!SUPERUSER_EMAIL || !SUPERUSER_PASSWORD) {
return;
}

console.log('Creating superuser account...');

const { getOrInsertModelId } = (
await import('./src/infra/pinejs-client-helpers/index.js')
).default;
const { getOrInsertModelId } = await import(
'./src/infra/pinejs-client-helpers/index.js'
);

const { findUser, registerUser, updatePasswordIfNeeded } = (
await import('./src/infra/auth/auth.js')
).default;
const { findUser, registerUser, updatePasswordIfNeeded } = await import(
'./src/infra/auth/auth.js'
);
const { ConflictError } = errors;

const data = {
Expand Down Expand Up @@ -223,15 +221,15 @@ const init = async () => {

const doRunTests =
(process.env.RUN_TESTS || '').trim() === '1'
? (await import('./test/test-lib/init-tests.js')).default
? await import('./test/test-lib/init-tests.js')
: undefined;

// we have to load some mocks before the app starts...
if (doRunTests) {
console.log('Loading mocks...');
await doRunTests.preInit();
}
const { setup } = (await import('./src/index.js')).default;
const { setup } = await import('./src/index.js');
const { startServer } = await setup(app, {
config,
version: packageJson.version,
Expand Down
9 changes: 0 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/balena-io/open-balena-api"
},
"type": "commonjs",
"type": "module",
"main": "dist/index",
"exports": {
".": "./dist/index.js",
Expand Down Expand Up @@ -97,7 +97,6 @@
"escape-html": "^1.0.3",
"eventemitter3": "^5.0.1",
"express": "^4.18.2",
"fast-boot2": "^1.1.3",
"fast-glob": "^3.3.2",
"ioredis": "^5.3.2",
"ipaddr.js": "^2.1.0",
Expand Down
26 changes: 17 additions & 9 deletions src/balena.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { fileURLToPath } from 'node:url';
import {
aliasTable,
generateAbstractSqlModel,
renameVarResourcesName,
optimizeSchema,
} from './abstract-sql-utils';
} from './abstract-sql-utils.js';

import * as userHasDirectAccessToApplication from './features/applications/models/user__has_direct_access_to__application';
import * as deviceAdditions from './features/devices/models/device-additions';
import * as releaseAdditions from './features/ci-cd/models/release-additions';
import * as userHasDirectAccessToApplication from './features/applications/models/user__has_direct_access_to__application.js';
import * as deviceAdditions from './features/devices/models/device-additions.js';
import * as releaseAdditions from './features/ci-cd/models/release-additions.js';
import type { ConfigLoader } from '@balena/pinejs';

export const apiRoot = 'resin';
export const modelName = 'balena';
export const migrationsPath = __dirname + '/migrations/';
export const initSqlPath = __dirname + '/balena-init.sql';
export const abstractSql = generateAbstractSqlModel(__dirname + '/balena.sbvr');
const abstractSql = generateAbstractSqlModel(
new URL('balena.sbvr', import.meta.url),
);

export const model = {
apiRoot: 'resin',
modelName: 'balena',
migrationsPath: fileURLToPath(new URL('migrations/', import.meta.url)),
initSqlPath: fileURLToPath(new URL('balena-init.sql', import.meta.url)),
abstractSql,
} satisfies ConfigLoader.Model;

aliasTable(abstractSql, 'application', 'my application', {
binds: [],
Expand Down
7 changes: 5 additions & 2 deletions src/exports/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export { setSyncSettings, synchronizeContracts } from '../features/contracts';
export type { RepositoryInfo } from '../features/contracts';
export {
setSyncSettings,
synchronizeContracts,
} from '../features/contracts/index.js';
export type { RepositoryInfo } from '../features/contracts/index.js';
10 changes: 5 additions & 5 deletions src/exports/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { resolveOrDenyDevicesWithStatus } from '../features/device-state/middleware';
export type { ResolveDeviceInfoCustomObject } from '../features/device-state/middleware';
export * from '../infra/auth/middleware';
export { loginRateLimiter } from '../features/auth';
export { skipLogging } from '../features/request-logging';
export { resolveOrDenyDevicesWithStatus } from '../features/device-state/middleware.js';
export type { ResolveDeviceInfoCustomObject } from '../features/device-state/middleware.js';
export * from '../infra/auth/middleware.js';
export { loginRateLimiter } from '../features/auth/index.js';
export { skipLogging } from '../features/request-logging/index.js';
4 changes: 2 additions & 2 deletions src/features/api-keys/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { Application } from 'express';

import { middleware } from '../../infra/auth';
import { middleware } from '../../infra/auth/index.js';
import {
createDeviceApiKey,
createGenericApiKey,
createNamedUserApiKey,
createProvisioningApiKey,
createUserApiKey,
} from './routes';
} from './routes.js';

export const setup = (app: Application) => {
/**
Expand Down
6 changes: 3 additions & 3 deletions src/features/api-keys/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import type {
Device,
Role,
User,
} from '../../balena-model';
import { multiCacheMemoizee } from '../../infra/cache';
import { API_KEY_ROLE_CACHE_TIMEOUT } from '../../lib/config';
} from '../../balena-model.js';
import { multiCacheMemoizee } from '../../infra/cache/index.js';
import { API_KEY_ROLE_CACHE_TIMEOUT } from '../../lib/config.js';

const { api } = sbvrUtils;
const { BadRequestError } = errors;
Expand Down
8 changes: 4 additions & 4 deletions src/features/api-keys/routes.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { errors, sbvrUtils } from '@balena/pinejs';
import type { RequestHandler } from 'express';

import { getUser } from '../../infra/auth/auth';
import { getUser } from '../../infra/auth/auth.js';
import {
captureException,
handleHttpErrors,
translateError,
} from '../../infra/error-handling';
} from '../../infra/error-handling/index.js';

import type { ApiKeyParameters } from './lib';
import type { ApiKeyParameters } from './lib.js';
import {
createGenericApiKey as $createGenericApiKey,
createDeviceApiKey as $createDeviceApiKey,
createNamedUserApiKey as $createNamedUserApiKey,
createProvisioningApiKey as $createProvisioningApiKey,
createUserApiKey as $createUserApiKey,
} from './lib';
} from './lib.js';

export const createGenericApiKey: RequestHandler = async (req, res) => {
const body = req.body as ApiKeyParameters;
Expand Down
2 changes: 1 addition & 1 deletion src/features/application-types/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { hooks } from '@balena/pinejs';
import { checkDeviceCanBeInApplication } from './application-types';
import { checkDeviceCanBeInApplication } from './application-types.js';

hooks.addPureHook('POST', 'resin', 'device', {
POSTRUN: async ({ api, request }) => {
Expand Down
4 changes: 2 additions & 2 deletions src/features/applications/hooks/defaults.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { hooks, errors } from '@balena/pinejs';
import { randomUUID } from 'crypto';
import { randomUUID } from 'node:crypto';
import * as uuid from 'uuid';
import { DefaultApplicationType } from '../../application-types/application-types';
import { DefaultApplicationType } from '../../application-types/application-types.js';

// reconstitute the value into a properly formatted UUID...
const toUuid = (strippedUuid: string): string => {
Expand Down
12 changes: 6 additions & 6 deletions src/features/applications/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import './backwards-compatible-delete-error';
import './change-default-device-type';
import './defaults';
import './unpin-release-before-delete';
import './rename';
import './slug';
import './backwards-compatible-delete-error.js';
import './change-default-device-type.js';
import './defaults.js';
import './unpin-release-before-delete.js';
import './rename.js';
import './slug.js';
4 changes: 2 additions & 2 deletions src/features/applications/hooks/slug.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { hooks, permissions } from '@balena/pinejs';
import { getApplicationSlug } from '..';
import type { Application, Organization } from '../../../balena-model';
import { getApplicationSlug } from '../index.js';
import type { Application, Organization } from '../../../balena-model.js';

hooks.addPureHook('POST', 'resin', 'application', {
POSTPARSE: ({ request }) => {
Expand Down
4 changes: 2 additions & 2 deletions src/features/auth/hooks/assign-default-user-role.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { sbvrUtils, hooks, permissions, errors } from '@balena/pinejs';

import { getRegistrationRole } from '../../../infra/auth/auth';
import { assignUserRole } from '../../../infra/auth/permissions';
import { getRegistrationRole } from '../../../infra/auth/auth.js';
import { assignUserRole } from '../../../infra/auth/permissions.js';

const { InternalRequestError } = errors;
const { api } = sbvrUtils;
Expand Down
Loading

0 comments on commit 54b5f54

Please sign in to comment.