Repository: spotify/backstage
File: packages/backend-app-api/src/wiring/BackendInitializer.ts (TypeScript)

Code before:
      }
      return [];
    })
    .flat();
  return createServiceFactory({
    service: instanceMetadataServiceRef,
    deps: {
      httpRouter: coreServices.rootHttpRouter,
      logger: coreServices.rootLogger,
    },
    factory: async ({ logger, httpRouter }) => {
      const instanceMetadata = {
        getInstalledFeatures: () => installedFeatures,
      };

      logger.info(
        `Installed features on this instance: ${instanceMetadata
          .getInstalledFeatures()
          .join(', ')}`,
      );

      const router = Router();

      router.get('/features/installed', (_, res) => {
        res.json({ items: instanceMetadata.getInstalledFeatures() });
      });

      httpRouter.use('/.backstage/instanceMetadata/v1', router);

      return instanceMetadata;
    },
  });
}

export class BackendInitializer {
  #startPromise?: Promise<void>;
  #stopPromise?: Promise<void>;
  #registrations = new Array<InternalBackendRegistrations>();
  #extensionPoints = new Map<string, { impl: unknown; pluginId: string }>();
  #serviceRegistry: ServiceRegistry;
  #registeredFeatures = new Array<Promise<BackendFeature>>();
  #registeredFeatureLoaders = new Array<InternalBackendFeatureLoader>();

  constructor(defaultApiFactories: ServiceFactory[]) {
    this.#serviceRegistry = ServiceRegistry.create([...defaultApiFactories]);
  }

  async #getInitDeps(
    deps: { [name: string]: ServiceOrExtensionPoint },
    pluginId: string,
    moduleId?: string,

Review comment (suggestion):
Random though: I think it might be useful to also include the timestamp of when the instance was started, to help resolve conflicts in the metadata. That in turn made me think that maybe this is best designed as a single "fat" one-stop-shop endpoint where we put anything one might want to know. Just `/info` or something.

Code after:
      return instanceMetadata;
    },
  });
}

export class BackendInitializer {
  #startPromise?: Promise<{ result: BackendStartupResult }>;
  #stopPromise?: Promise<void>;
  #registrations = new Array<InternalBackendRegistrations>();
  #extensionPoints = new Map<string, { impl: unknown; pluginId: string }>();
  #serviceRegistry: ServiceRegistry;
  #registeredFeatures = new Array<Promise<BackendFeature>>();
  #registeredFeatureLoaders = new Array<InternalBackendFeatureLoader>();

  constructor(defaultApiFactories: ServiceFactory[]) {
    this.#serviceRegistry = ServiceRegistry.create([...defaultApiFactories]);
  }

  async #getInitDeps(
    deps: { [name: string]: ServiceOrExtensionPoint },
    pluginId: string,
    moduleId?: string,
  ) {
    const result = new Map<string, unknown>();
    const missingRefs = new Set<ServiceOrExtensionPoint>();

    for (const [name, ref] of Object.entries(deps)) {
      const ep = this.#extensionPoints.get(ref.id);
      if (ep) {
        if (ep.pluginId !== pluginId) {
          throw new Error(
            `Illegal dependency: Module '${moduleId}' for plugin '${pluginId}' attempted to depend on extension point '${ref.id}' for plugin '${ep.pluginId}'. Extension points can only be used within their plugin's scope.`,
          );
        }
        result.set(name, ep.impl);
      } else {
        const impl = await this.#serviceRegistry.get(
          ref as ServiceRef<unknown>,
          pluginId,
        );
        if (impl) {
          result.set(name, impl);
        } else {
          missingRefs.add(ref);
        }
      }
    }

    if (missingRefs.size > 0) {
      const missing = Array.from(missingRefs).join(', ');
      const target = moduleId