Skip to content

feat(all-services): add openapi documentation files to arc-saas services#123

Merged
yeshamavani merged 2 commits into
masterfrom
GH-122
Jun 16, 2026
Merged

feat(all-services): add openapi documentation files to arc-saas services#123
yeshamavani merged 2 commits into
masterfrom
GH-122

Conversation

@Sourav-kashyap

@Sourav-kashyap Sourav-kashyap commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

add openapi documentation files to arc-saas services

GH-122

Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Fixes # (issue)

Checklist:

  • Performed a self-review of my own code
  • npm test passes on your machine

Build:

Screenshot 2026-06-15 at 11 00 30 AM

Test:

Screenshot 2026-06-15 at 11 00 35 AM

add openapi documentation files to arc-saas services

GH-122

@yeshamavani yeshamavani left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop node 20

remove node js 20 support

BREAKING CHANGE:
yes

GH-122
@sonarqubecloud

Copy link
Copy Markdown

"preopenapi-spec": "npm run build",
"preopenapi-spec": "lb-tsc",
"openapi-spec": "node ./dist/openapi-spec",
"apidocs": "npx widdershins --language_tabs 'javascript:JavaScript:request' 'javascript--nodejs:Node.JS' --summary openapi.json -o openapi.md",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things on the doc generation here (same applies to subscription-service and tenant-management-service — identical scripts):

  1. npx widdershins resolves and downloads widdershins from the registry at build time — non-deterministic (picks up new releases), network-dependent (fails on offline/air-gapped CI or a registry blip), and slow on a clean environment. Since build now calls apidocs, a bad widdershins release would break every build of every service. Pin it as a devDependency and call the local bin:
"devDependencies": { "widdershins": "4.0.1" },
"scripts": {
  "apidocs": "widdershins --language_tabs 'javascript:JavaScript:request' 'javascript--nodejs:Node.JS' --summary openapi.json -o openapi.md"
}
  1. build: lb-tsc && npm run openapi-spec && npm run apidocs couples doc generation into the standard build that Docker/deploy run, and since preopenapi-spec is lb-tsc, the compile runs twice per build. Consider keeping build as just lb-tsc, moving docs to a dedicated script, and adding a CI step that regenerates and fails if the committed spec drifted:
"build": "lb-tsc",
"docs": "npm run openapi-spec && npm run apidocs"
// CI: npm run docs && git diff --exit-code services/**/openapi.*

Keeps deploy builds offline-safe and avoids the double compile while still guaranteeing the committed spec matches the code.

@rohit-sourcefuse rohit-sourcefuse left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid, low-risk PR — OpenAPI spec + markdown across all three services, Node 20 dropped consistently (CI matrix + engines), and the Trivy action is now pinned to a commit SHA. Nice incidental fixes too: the Audit ServiceTenant Management Service title correction across the three components, the openapi.json output-path fix, and preopenapi-spec: lb-tsc to avoid the build recursion. Checks are green.

One thing worth doing before merge: pin widdershins as a devDependency instead of npx so doc generation (now part of build) doesn't depend on a registry fetch at build time — details inline. Couple of non-blocking nits there too (decoupling docs from build, and the "22 || 24" engines being an exact allow-list rather than >=22).

Approving — the inline points are improvements, not blockers.

@rohit-sourcefuse rohit-sourcefuse left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a closer pass on the hand-written bits — a few things worth a look beyond the widdershins comment above. None are hard blockers, but the first two are worth deciding on before merge.

1. The orchestrator OpenAPI doc documents nothing real. services/orchestrator-service/openapi.json has only paths: /ping, / and components.schemas: [], and info.title is the package name @sourceloop/ctrl-plane-orchestrator-service. The orchestrator only has the boilerplate ping/home-page controllers — it's a component consumed by other apps, not a standalone REST API. For comparison subscription documents 45 paths and tenant 24. So we're adding a new application.ts + shipping an openapi.json/.md that advertise an essentially empty contract. Either orchestrator genuinely has no standalone API (then skip the doc for it, or clearly label it), or the real controllers/components aren't being registered in the new application.ts. Also worth fixing info.title to a human title like the tenant fix did.

2. npm test now boots the app and fetches widdershins over the network. pretest → rebuild → build, and build now runs openapi-spec (app.boot) + apidocs (npx widdershins). So a boot hang or a widdershins/registry failure now fails the test job (misleading signal), and Dockerfile RUN npm run build is gated on a network fetch. Pinning widdershins (comment above) fixes the network half; decoupling docs from build fixes the rest.

3. Orchestrator's exporter can hang the build silently. services/orchestrator-service/src/openapi-spec.ts uses .catch(()=>process.exit(1)) with no .then(()=>process.exit(0)), while subscription and tenant force process.exit(0) on success. If app.boot() leaves open handles (event-stream/message-bus listeners), the orchestrator step keeps the process alive with no error — a silent stall. Standardize all three on .then(()=>process.exit(0)).catch(err=>{console.error(...);process.exit(1)}), ideally with await app.stop() before exit.

Smaller / nits

  • Stale Copyright (c) 2023 header on the brand-new 2026 files (application.ts, openapi-spec.ts).
  • The three openapi-spec.ts are gratuitously divergent (license header only on orchestrator, PORT vs DEFAULT_PORT, different success handler, //NOSONAR on only one) — worth normalizing them to byte-identical.
  • orchestrator application.ts imports node:path while the peers use path; and export {ApplicationConfig} is dead here (the exporter imports it from @loopback/core).
  • subscription-service is missing the posttest: npm run lint the other two have; tenant/subscription docker:push:dev use a literal :undefined tag (pre-existing, but broken).
  • Nice-to-have: a CI drift-guard — regenerate the spec and git diff --exit-code services/**/openapi.* so the committed docs can't silently go stale.

Happy to hop on a quick call if it's easier to walk through the orchestrator-spec question.

@rohit-sourcefuse rohit-sourcefuse left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick clarification on ownership so the earlier comments are fair — splitting "this PR's changes" from "inherited / expected":

  • The OpenAPI exporter pattern (openapi-spec.tsnode ./dist/openapi-spec) already existed in subscription/tenant; this PR replicates it for orchestrator and adds markdown generation. So the exporter structure isn't a design choice to defend here.
  • What is new in this PR (all three services) is wiring docs into build and the npx widdershins step. That part is in scope and is the one worth tightening.
  • The orchestrator "empty spec" is an expected consequence of orchestrator being a component (only ping/home-page controllers), not a bug — see below.

Concrete, working changes:

1. Pin widdershins, drop npx (all three services). This is the one clear win and it's small. widdershins isn't a declared dep, so npx fetches it from the registry on every build (non-deterministic + breaks offline/Docker). Pin to the version that generated these docs (Generator: Widdershins v4.0.1):

// services/<svc>/package.json
"devDependencies": {
  "widdershins": "4.0.1"
},
"scripts": {
  "apidocs": "widdershins --language_tabs 'javascript:JavaScript:request' 'javascript--nodejs:Node.JS' --summary openapi.json -o openapi.md"
}

Then npm install to lock it. (No npx, no network at build time.)

2. Optional but recommended — keep docs out of build. Because pretest → rebuild → build, the doc step now runs during npm test and RUN npm run build in the Dockerfile. Move it to its own script + a CI drift-guard so docs stay fresh without coupling to compile/test:

"scripts": {
  "build": "lb-tsc",
  "openapi-spec": "node ./dist/openapi-spec",
  "preopenapi-spec": "lb-tsc",
  "apidocs": "widdershins --language_tabs 'javascript:JavaScript:request' 'javascript--nodejs:Node.JS' --summary openapi.json -o openapi.md",
  "docs": "npm run openapi-spec && npm run apidocs"
}

CI step (one place, catches stale specs):

- run: npm run docs --workspaces && git diff --exit-code services/**/openapi.{json,md}

3. Normalize the orchestrator exporter so the build can't hang. orchestrator's openapi-spec.ts only does .catch(exit 1); subscription/tenant force exit(0). If app.boot() leaves an open handle, the orchestrator step stalls with no error. Match the other two and stop the app:

exportOpenApiSpec()
  .then(() => process.exit(0))
  .catch(err => {
    console.error(`Failed to export OpenAPI spec to ${outFile}:`, err); //NOSONAR
    process.exit(1);
  });

(and await app.stop() before returning, if boot starts any listeners.)

4. Orchestrator spec — just confirm intent. Since orchestrator only exposes ping/home-page, its openapi.json will always be near-empty — that's expected for a component, not something you did wrong. If a doc is still wanted for it (the "all three services" ask), set a human info.title (it currently shows the package name) the way tenant's component title was fixed. If it isn't actually consumed, it's fine to skip generating one for orchestrator.

Everything else I flagged (2023 headers, the three openapi-spec.ts being slightly different) is cosmetic — fine as follow-ups. #1 is the only thing I'd genuinely do before merge.

@yeshamavani yeshamavani merged commit 9c0296e into master Jun 16, 2026
6 checks passed
@yeshamavani yeshamavani deleted the GH-122 branch June 16, 2026 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add OpenAPI Documentation Files to arc-saas Services

3 participants