@ojiepermana/angular 22.1.11 → 22.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -26
- package/chart/README.md +272 -0
- package/component/README.md +89 -0
- package/component/accordion/README.md +195 -0
- package/component/alert/README.md +184 -0
- package/component/alert-dialog/README.md +255 -0
- package/component/aspect-ratio/README.md +116 -0
- package/component/avatar/README.md +182 -0
- package/component/badge/README.md +143 -0
- package/component/breadcrumb/README.md +223 -0
- package/component/button/README.md +141 -0
- package/component/button-group/README.md +214 -0
- package/component/calendar/README.md +137 -0
- package/component/card/README.md +232 -0
- package/component/carousel/README.md +276 -0
- package/component/checkbox/README.md +153 -0
- package/component/collapsible/README.md +216 -0
- package/component/combobox/README.md +202 -0
- package/component/command/README.md +287 -0
- package/component/composer/README.md +241 -0
- package/component/context-menu/README.md +268 -0
- package/component/date-picker/README.md +202 -0
- package/component/dialog/README.md +276 -0
- package/component/drawer/README.md +147 -0
- package/component/dropdown-menu/README.md +336 -0
- package/component/editor/README.md +152 -0
- package/component/empty/README.md +193 -0
- package/component/form/README.md +216 -0
- package/component/hover-card/README.md +150 -0
- package/component/icon/README.md +25 -0
- package/component/input/README.md +160 -0
- package/component/input-group/README.md +245 -0
- package/component/input-otp/README.md +331 -0
- package/component/item/README.md +254 -0
- package/component/kanban/README.md +81 -0
- package/component/kbd/README.md +141 -0
- package/component/label/README.md +137 -0
- package/component/menubar/README.md +270 -0
- package/component/native-select/README.md +176 -0
- package/component/navigation-menu/README.md +165 -0
- package/component/pagination/README.md +151 -0
- package/component/pillbox/README.md +68 -0
- package/component/popover/README.md +54 -0
- package/component/progress/README.md +160 -0
- package/component/radio/README.md +212 -0
- package/component/resizable/README.md +178 -0
- package/component/scroll-area/README.md +150 -0
- package/component/select/README.md +228 -0
- package/component/separator/README.md +175 -0
- package/component/sheet/README.md +190 -0
- package/component/skeleton/README.md +158 -0
- package/component/slider/README.md +207 -0
- package/component/spinner/README.md +160 -0
- package/component/switch/README.md +170 -0
- package/component/table/README.md +292 -0
- package/component/tabs/README.md +220 -0
- package/component/textarea/README.md +169 -0
- package/component/timeline/README.md +94 -0
- package/component/toast/README.md +173 -0
- package/component/toggle/README.md +133 -0
- package/component/toggle-group/README.md +234 -0
- package/component/tooltip/README.md +230 -0
- package/fesm2022/ojiepermana-angular-chart-area.mjs +289 -3
- package/fesm2022/ojiepermana-angular-chart-bar.mjs +722 -3
- package/fesm2022/ojiepermana-angular-chart-core.mjs +1482 -3
- package/fesm2022/ojiepermana-angular-chart-line.mjs +294 -3
- package/fesm2022/ojiepermana-angular-chart-pie.mjs +291 -3
- package/fesm2022/ojiepermana-angular-chart-primitives.mjs +1301 -3
- package/fesm2022/ojiepermana-angular-chart-radar.mjs +421 -3
- package/fesm2022/ojiepermana-angular-chart-radial.mjs +295 -3
- package/fesm2022/ojiepermana-angular-chart-scatter.mjs +306 -3
- package/fesm2022/ojiepermana-angular-chart.mjs +12 -3
- package/fesm2022/ojiepermana-angular-component-accordion.mjs +267 -3
- package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs +359 -3
- package/fesm2022/ojiepermana-angular-component-alert.mjs +101 -3
- package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs +31 -3
- package/fesm2022/ojiepermana-angular-component-avatar.mjs +139 -3
- package/fesm2022/ojiepermana-angular-component-badge.mjs +57 -3
- package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs +192 -3
- package/fesm2022/ojiepermana-angular-component-button-group.mjs +95 -3
- package/fesm2022/ojiepermana-angular-component-button.mjs +73 -3
- package/fesm2022/ojiepermana-angular-component-calendar.mjs +718 -3
- package/fesm2022/ojiepermana-angular-component-card.mjs +167 -3
- package/fesm2022/ojiepermana-angular-component-carousel.mjs +326 -3
- package/fesm2022/ojiepermana-angular-component-checkbox.mjs +190 -3
- package/fesm2022/ojiepermana-angular-component-collapsible.mjs +117 -3
- package/fesm2022/ojiepermana-angular-component-combobox.mjs +327 -3
- package/fesm2022/ojiepermana-angular-component-command.mjs +351 -3
- package/fesm2022/ojiepermana-angular-component-composer.mjs +359 -3
- package/fesm2022/ojiepermana-angular-component-context-menu.mjs +158 -3
- package/fesm2022/ojiepermana-angular-component-date-picker.mjs +482 -3
- package/fesm2022/ojiepermana-angular-component-dialog.mjs +400 -3
- package/fesm2022/ojiepermana-angular-component-drawer.mjs +1 -3
- package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs +689 -3
- package/fesm2022/ojiepermana-angular-component-editor.mjs +511 -3
- package/fesm2022/ojiepermana-angular-component-empty.mjs +134 -3
- package/fesm2022/ojiepermana-angular-component-form.mjs +438 -3
- package/fesm2022/ojiepermana-angular-component-hover-card.mjs +273 -3
- package/fesm2022/ojiepermana-angular-component-icon.mjs +139 -3
- package/fesm2022/ojiepermana-angular-component-input-group.mjs +176 -3
- package/fesm2022/ojiepermana-angular-component-input-otp.mjs +550 -3
- package/fesm2022/ojiepermana-angular-component-input.mjs +52 -3
- package/fesm2022/ojiepermana-angular-component-item.mjs +264 -3
- package/fesm2022/ojiepermana-angular-component-kanban.mjs +310 -3
- package/fesm2022/ojiepermana-angular-component-kbd.mjs +48 -3
- package/fesm2022/ojiepermana-angular-component-label.mjs +27 -3
- package/fesm2022/ojiepermana-angular-component-menubar.mjs +327 -3
- package/fesm2022/ojiepermana-angular-component-native-select.mjs +62 -3
- package/fesm2022/ojiepermana-angular-component-navigation-menu.mjs +378 -3
- package/fesm2022/ojiepermana-angular-component-pagination.mjs +238 -3
- package/fesm2022/ojiepermana-angular-component-pillbox.mjs +999 -3
- package/fesm2022/ojiepermana-angular-component-popover.mjs +201 -3
- package/fesm2022/ojiepermana-angular-component-progress.mjs +57 -3
- package/fesm2022/ojiepermana-angular-component-radio.mjs +180 -3
- package/fesm2022/ojiepermana-angular-component-resizable.mjs +493 -3
- package/fesm2022/ojiepermana-angular-component-scroll-area.mjs +51 -3
- package/fesm2022/ojiepermana-angular-component-segmented-control.mjs +227 -3
- package/fesm2022/ojiepermana-angular-component-select.mjs +609 -3
- package/fesm2022/ojiepermana-angular-component-separator.mjs +31 -3
- package/fesm2022/ojiepermana-angular-component-sheet.mjs +407 -3
- package/fesm2022/ojiepermana-angular-component-skeleton.mjs +25 -3
- package/fesm2022/ojiepermana-angular-component-slider.mjs +456 -3
- package/fesm2022/ojiepermana-angular-component-spinner.mjs +56 -3
- package/fesm2022/ojiepermana-angular-component-switch.mjs +145 -3
- package/fesm2022/ojiepermana-angular-component-table.mjs +155 -3
- package/fesm2022/ojiepermana-angular-component-tabs.mjs +315 -3
- package/fesm2022/ojiepermana-angular-component-textarea.mjs +46 -3
- package/fesm2022/ojiepermana-angular-component-timeline.mjs +237 -3
- package/fesm2022/ojiepermana-angular-component-toast.mjs +241 -3
- package/fesm2022/ojiepermana-angular-component-toggle-group.mjs +290 -3
- package/fesm2022/ojiepermana-angular-component-toggle.mjs +76 -3
- package/fesm2022/ojiepermana-angular-component-tooltip.mjs +519 -3
- package/fesm2022/ojiepermana-angular-component-utils-core.mjs +310 -3
- package/fesm2022/ojiepermana-angular-component-utils-overlay.mjs +62 -3
- package/fesm2022/ojiepermana-angular-component-utils-scale.mjs +34 -3
- package/fesm2022/ojiepermana-angular-component-utils.mjs +3 -2
- package/fesm2022/ojiepermana-angular-component.mjs +4 -4
- package/fesm2022/ojiepermana-angular-navigation-core.mjs +21 -3
- package/fesm2022/ojiepermana-angular-navigation-icon.mjs +20 -3
- package/fesm2022/ojiepermana-angular-navigation-navigation-badge-count.component-CDBxQ8rk.mjs +91 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-dockbar-menu.component-DBQHdvGa.mjs +512 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-entry-grid.component-Cd-jh6tg.mjs +623 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-flyout-menu.component-BCGvhoYj.mjs +404 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-horizontal.component-Dk_03e-6.mjs +466 -0
- package/fesm2022/ojiepermana-angular-navigation-ojiepermana-angular-navigation-DNKU6viC.mjs +2642 -0
- package/fesm2022/ojiepermana-angular-navigation-service.mjs +725 -3
- package/fesm2022/ojiepermana-angular-navigation-types.mjs +65 -4
- package/fesm2022/ojiepermana-angular-navigation.mjs +4 -10
- package/fesm2022/ojiepermana-angular-sdk.mjs +204 -4
- package/fesm2022/ojiepermana-angular-theme-component-settings.mjs +1387 -3
- package/fesm2022/ojiepermana-angular-theme-layout-services.mjs +331 -3
- package/fesm2022/ojiepermana-angular-theme-layout-types.mjs +45 -4
- package/fesm2022/ojiepermana-angular-theme-layout-wrapper.mjs +1044 -3
- package/fesm2022/ojiepermana-angular-theme-layout.mjs +729 -3
- package/fesm2022/ojiepermana-angular-theme-page-core.mjs +381 -3
- package/fesm2022/ojiepermana-angular-theme-page-filter.mjs +267 -3
- package/fesm2022/ojiepermana-angular-theme-page-root.mjs +361 -3
- package/fesm2022/ojiepermana-angular-theme-page-side.mjs +198 -3
- package/fesm2022/ojiepermana-angular-theme-page-slots.mjs +110 -3
- package/fesm2022/ojiepermana-angular-theme-page.mjs +7 -2
- package/fesm2022/ojiepermana-angular-theme-shell-services.mjs +338 -3
- package/fesm2022/ojiepermana-angular-theme-shell-types.mjs +160 -4
- package/fesm2022/ojiepermana-angular-theme-shell.mjs +811 -3
- package/fesm2022/ojiepermana-angular-theme-styles.mjs +783 -3
- package/fesm2022/ojiepermana-angular-theme.mjs +4 -4
- package/fesm2022/ojiepermana-angular.mjs +6 -11
- package/navigation/README.md +374 -0
- package/package.json +81 -20
- package/sdk/README.md +212 -0
- package/sdk/schematics/collection.json +20 -0
- package/sdk/schematics/init/index.js +83 -0
- package/sdk/schematics/init/schema.json +19 -0
- package/sdk/schematics/ng-add/index.js +147 -0
- package/sdk/schematics/ng-add/schema.json +14 -0
- package/sdk/schematics/package.json +3 -0
- package/sdk/schematics/sdk/index.js +175 -0
- package/sdk/schematics/sdk/schema.json +19 -0
- package/sdk/sdk.config.example.json +24 -0
- package/sdk/src/config/loader.js +43 -0
- package/sdk/src/config/schema.js +59 -0
- package/sdk/src/emit/client.js +251 -0
- package/sdk/src/emit/metadata.js +310 -0
- package/sdk/src/emit/models.js +104 -0
- package/sdk/src/emit/navigation.js +56 -0
- package/sdk/src/emit/operations.js +118 -0
- package/sdk/src/emit/public-api.js +54 -0
- package/sdk/src/emit/services.js +110 -0
- package/sdk/src/engine.js +67 -0
- package/sdk/src/layout/per-domain.js +360 -0
- package/sdk/src/package.json +3 -0
- package/sdk/src/parser/bundle.js +25 -0
- package/sdk/src/parser/ir.js +429 -0
- package/sdk/src/parser/types.js +7 -0
- package/sdk/src/render/template.js +152 -0
- package/sdk/src/writer/index.js +286 -0
- package/theme/README.md +126 -0
- package/theme/component/settings/README.md +135 -0
- package/theme/layout/README.md +539 -0
- package/theme/page/README.md +453 -0
- package/theme/shell/README.md +340 -0
- package/theme/styles/README.md +178 -0
- package/theme/styles/css/base/components.css +553 -0
- package/theme/styles/css/base/index.css +14 -0
- package/theme/styles/css/base/package.css +9 -0
- package/theme/styles/css/base/prefers-dark.css +86 -0
- package/theme/styles/css/base/print.css +62 -0
- package/theme/styles/css/base/status.css +38 -0
- package/theme/styles/css/base/tailwind.css +165 -0
- package/theme/styles/css/base/theme.css +374 -0
- package/theme/styles/css/base/tokens.css +361 -0
- package/theme/styles/css/color/amber.css +72 -0
- package/theme/styles/css/color/blue.css +72 -0
- package/theme/styles/css/color/brand.css +38 -0
- package/theme/styles/css/color/cyan.css +72 -0
- package/theme/styles/css/color/emerald.css +72 -0
- package/theme/styles/css/color/fuchsia.css +72 -0
- package/theme/styles/css/color/green.css +72 -0
- package/theme/styles/css/color/index.css +19 -0
- package/theme/styles/css/color/indigo.css +72 -0
- package/theme/styles/css/color/lime.css +72 -0
- package/theme/styles/css/color/orange.css +72 -0
- package/theme/styles/css/color/pink.css +72 -0
- package/theme/styles/css/color/purple.css +72 -0
- package/theme/styles/css/color/red.css +72 -0
- package/theme/styles/css/color/rose.css +72 -0
- package/theme/styles/css/color/sky.css +72 -0
- package/theme/styles/css/color/teal.css +72 -0
- package/theme/styles/css/color/violet.css +72 -0
- package/theme/styles/css/color/yellow.css +72 -0
- package/theme/styles/css/index.css +18 -0
- package/theme/styles/css/neutral/gray.css +63 -0
- package/theme/styles/css/neutral/index.css +11 -0
- package/theme/styles/css/neutral/mauve.css +63 -0
- package/theme/styles/css/neutral/mist.css +63 -0
- package/theme/styles/css/neutral/neutral.css +63 -0
- package/theme/styles/css/neutral/olive.css +63 -0
- package/theme/styles/css/neutral/slate.css +63 -0
- package/theme/styles/css/neutral/stone.css +63 -0
- package/theme/styles/css/neutral/taupe.css +63 -0
- package/theme/styles/css/neutral/zinc.css +63 -0
- package/theme/styles/css/radius/index.css +30 -0
- package/theme/styles/css/space/index.css +20 -0
- package/types/ojiepermana-angular-chart-area.d.ts +76 -1
- package/types/ojiepermana-angular-chart-bar.d.ts +201 -1
- package/types/ojiepermana-angular-chart-core.d.ts +811 -1
- package/types/ojiepermana-angular-chart-line.d.ts +75 -1
- package/types/ojiepermana-angular-chart-pie.d.ts +131 -1
- package/types/ojiepermana-angular-chart-primitives.d.ts +291 -1
- package/types/ojiepermana-angular-chart-radar.d.ts +116 -1
- package/types/ojiepermana-angular-chart-radial.d.ts +116 -1
- package/types/ojiepermana-angular-chart-scatter.d.ts +125 -1
- package/types/ojiepermana-angular-chart.d.ts +2 -1
- package/types/ojiepermana-angular-component-accordion.d.ts +85 -1
- package/types/ojiepermana-angular-component-alert-dialog.d.ts +140 -1
- package/types/ojiepermana-angular-component-alert.d.ts +42 -1
- package/types/ojiepermana-angular-component-aspect-ratio.d.ts +12 -1
- package/types/ojiepermana-angular-component-avatar.d.ts +56 -1
- package/types/ojiepermana-angular-component-badge.d.ts +24 -1
- package/types/ojiepermana-angular-component-breadcrumb.d.ts +46 -1
- package/types/ojiepermana-angular-component-button-group.d.ts +26 -1
- package/types/ojiepermana-angular-component-button.d.ts +27 -1
- package/types/ojiepermana-angular-component-calendar.d.ts +111 -1
- package/types/ojiepermana-angular-component-card.d.ts +69 -1
- package/types/ojiepermana-angular-component-carousel.d.ts +86 -1
- package/types/ojiepermana-angular-component-checkbox.d.ts +42 -1
- package/types/ojiepermana-angular-component-collapsible.d.ts +42 -1
- package/types/ojiepermana-angular-component-combobox.d.ts +60 -1
- package/types/ojiepermana-angular-component-command.d.ts +130 -1
- package/types/ojiepermana-angular-component-composer.d.ts +90 -1
- package/types/ojiepermana-angular-component-context-menu.d.ts +54 -1
- package/types/ojiepermana-angular-component-date-picker.d.ts +109 -1
- package/types/ojiepermana-angular-component-dialog.d.ts +136 -1
- package/types/ojiepermana-angular-component-drawer.d.ts +1 -1
- package/types/ojiepermana-angular-component-dropdown-menu.d.ts +248 -1
- package/types/ojiepermana-angular-component-editor.d.ts +135 -1
- package/types/ojiepermana-angular-component-empty.d.ts +50 -1
- package/types/ojiepermana-angular-component-form.d.ts +159 -1
- package/types/ojiepermana-angular-component-hover-card.d.ts +75 -1
- package/types/ojiepermana-angular-component-icon.d.ts +89 -1
- package/types/ojiepermana-angular-component-input-group.d.ts +51 -1
- package/types/ojiepermana-angular-component-input-otp.d.ts +155 -1
- package/types/ojiepermana-angular-component-input.d.ts +21 -1
- package/types/ojiepermana-angular-component-item.d.ts +93 -1
- package/types/ojiepermana-angular-component-kanban.d.ts +70 -1
- package/types/ojiepermana-angular-component-kbd.d.ts +16 -1
- package/types/ojiepermana-angular-component-label.d.ts +11 -1
- package/types/ojiepermana-angular-component-menubar.d.ts +93 -1
- package/types/ojiepermana-angular-component-native-select.d.ts +26 -1
- package/types/ojiepermana-angular-component-navigation-menu.d.ts +104 -1
- package/types/ojiepermana-angular-component-pagination.d.ts +33 -1
- package/types/ojiepermana-angular-component-pillbox.d.ts +222 -1
- package/types/ojiepermana-angular-component-popover.d.ts +66 -1
- package/types/ojiepermana-angular-component-progress.d.ts +17 -1
- package/types/ojiepermana-angular-component-radio.d.ts +60 -1
- package/types/ojiepermana-angular-component-resizable.d.ts +117 -1
- package/types/ojiepermana-angular-component-scroll-area.d.ts +19 -1
- package/types/ojiepermana-angular-component-segmented-control.d.ts +58 -1
- package/types/ojiepermana-angular-component-select.d.ts +122 -1
- package/types/ojiepermana-angular-component-separator.d.ts +14 -1
- package/types/ojiepermana-angular-component-sheet.d.ts +130 -1
- package/types/ojiepermana-angular-component-skeleton.d.ts +10 -1
- package/types/ojiepermana-angular-component-slider.d.ts +83 -1
- package/types/ojiepermana-angular-component-spinner.d.ts +13 -1
- package/types/ojiepermana-angular-component-switch.d.ts +44 -1
- package/types/ojiepermana-angular-component-table.d.ts +57 -1
- package/types/ojiepermana-angular-component-tabs.d.ts +124 -1
- package/types/ojiepermana-angular-component-textarea.d.ts +17 -1
- package/types/ojiepermana-angular-component-timeline.d.ts +64 -1
- package/types/ojiepermana-angular-component-toast.d.ts +64 -1
- package/types/ojiepermana-angular-component-toggle-group.d.ts +90 -1
- package/types/ojiepermana-angular-component-toggle.d.ts +25 -1
- package/types/ojiepermana-angular-component-tooltip.d.ts +143 -1
- package/types/ojiepermana-angular-component-utils-core.d.ts +184 -1
- package/types/ojiepermana-angular-component-utils-overlay.d.ts +21 -1
- package/types/ojiepermana-angular-component-utils-scale.d.ts +19 -1
- package/types/ojiepermana-angular-component-utils.d.ts +2 -1
- package/types/ojiepermana-angular-component.d.ts +2 -1
- package/types/ojiepermana-angular-navigation-core.d.ts +59 -1
- package/types/ojiepermana-angular-navigation-icon.d.ts +12 -1
- package/types/ojiepermana-angular-navigation-service.d.ts +116 -1
- package/types/ojiepermana-angular-navigation-types.d.ts +144 -1
- package/types/ojiepermana-angular-navigation.d.ts +507 -1
- package/types/ojiepermana-angular-sdk.d.ts +89 -1
- package/types/ojiepermana-angular-theme-component-settings.d.ts +154 -1
- package/types/ojiepermana-angular-theme-layout-services.d.ts +147 -1
- package/types/ojiepermana-angular-theme-layout-types.d.ts +40 -1
- package/types/ojiepermana-angular-theme-layout-wrapper.d.ts +299 -1
- package/types/ojiepermana-angular-theme-layout.d.ts +129 -1
- package/types/ojiepermana-angular-theme-page-core.d.ts +157 -1
- package/types/ojiepermana-angular-theme-page-filter.d.ts +77 -1
- package/types/ojiepermana-angular-theme-page-root.d.ts +88 -1
- package/types/ojiepermana-angular-theme-page-side.d.ts +50 -1
- package/types/ojiepermana-angular-theme-page-slots.d.ts +40 -1
- package/types/ojiepermana-angular-theme-page.d.ts +5 -1
- package/types/ojiepermana-angular-theme-shell-services.d.ts +193 -1
- package/types/ojiepermana-angular-theme-shell-types.d.ts +105 -1
- package/types/ojiepermana-angular-theme-shell.d.ts +100 -1
- package/types/ojiepermana-angular-theme-styles.d.ts +319 -1
- package/types/ojiepermana-angular-theme.d.ts +2 -1
- package/types/ojiepermana-angular.d.ts +5 -5
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildIR = buildIR;
|
|
4
|
+
const HTTP_METHODS = [
|
|
5
|
+
'get',
|
|
6
|
+
'post',
|
|
7
|
+
'put',
|
|
8
|
+
'patch',
|
|
9
|
+
'delete',
|
|
10
|
+
'head',
|
|
11
|
+
'options',
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Build the Intermediate Representation from a bundled OpenAPI document.
|
|
15
|
+
*
|
|
16
|
+
* Expectations about input:
|
|
17
|
+
* - `$ref` strings in the form `#/components/<section>/<Name>`, where the
|
|
18
|
+
* section (`schemas`, `parameters`, `requestBodies`, `responses`) decides how
|
|
19
|
+
* the reference is resolved.
|
|
20
|
+
* - OpenAPI 3.0.x / 3.1.x / 3.2.x (nullable via `type: ['string', 'null']` or
|
|
21
|
+
* `nullable: true`).
|
|
22
|
+
*/
|
|
23
|
+
function buildIR(doc) {
|
|
24
|
+
const root = asRecord(doc) ?? {};
|
|
25
|
+
const info = asRecord(root['info']) ?? {};
|
|
26
|
+
const components = asRecord(root['components']);
|
|
27
|
+
const servers = asArray(root['servers']).map((value) => {
|
|
28
|
+
const server = asRecord(value) ?? {};
|
|
29
|
+
return {
|
|
30
|
+
url: String(server['url'] ?? ''),
|
|
31
|
+
description: optionalString(server['description']),
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
const tags = asArray(root['tags']).map((value) => {
|
|
35
|
+
const tag = asRecord(value) ?? {};
|
|
36
|
+
return {
|
|
37
|
+
name: String(tag['name']),
|
|
38
|
+
parent: optionalString(tag['parent']),
|
|
39
|
+
kind: optionalString(tag['kind']),
|
|
40
|
+
xIcon: optionalString(tag['x-icon']),
|
|
41
|
+
description: optionalString(tag['description']),
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
const schemas = buildSchemas(components?.['schemas']);
|
|
45
|
+
const operations = buildOperations(root['paths'], components);
|
|
46
|
+
const security = buildSecuritySchemes(asRecord(components?.['securitySchemes']));
|
|
47
|
+
return {
|
|
48
|
+
title: String(info['title'] ?? 'API'),
|
|
49
|
+
version: String(info['version'] ?? '0.0.0'),
|
|
50
|
+
description: optionalString(info['description']),
|
|
51
|
+
servers,
|
|
52
|
+
tags,
|
|
53
|
+
navigation: buildNavigation(tags),
|
|
54
|
+
schemas,
|
|
55
|
+
operations,
|
|
56
|
+
security,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Schemas
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
function buildSchemas(rawSchemasInput) {
|
|
63
|
+
const rawSchemas = asRecord(rawSchemasInput);
|
|
64
|
+
if (!rawSchemas)
|
|
65
|
+
return [];
|
|
66
|
+
const names = Object.keys(rawSchemas).sort();
|
|
67
|
+
return names.map((name) => buildSchema(name, rawSchemas[name]));
|
|
68
|
+
}
|
|
69
|
+
function buildSchema(name, rawInput) {
|
|
70
|
+
const raw = asRecord(rawInput) ?? {};
|
|
71
|
+
const required = stringArray(raw['required']);
|
|
72
|
+
const properties = {};
|
|
73
|
+
// allOf: merge inline properties + required lists into the parent.
|
|
74
|
+
const mergedProps = { ...(asRecord(raw['properties']) ?? {}) };
|
|
75
|
+
for (const part of recordArray(raw['allOf'])) {
|
|
76
|
+
const partProperties = asRecord(part['properties']);
|
|
77
|
+
if (partProperties)
|
|
78
|
+
Object.assign(mergedProps, partProperties);
|
|
79
|
+
for (const requirement of stringArray(part['required'])) {
|
|
80
|
+
if (!required.includes(requirement))
|
|
81
|
+
required.push(requirement);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
for (const [propName, propSchema] of Object.entries(mergedProps)) {
|
|
85
|
+
properties[propName] = buildFieldRule(propSchema, required.includes(propName));
|
|
86
|
+
}
|
|
87
|
+
// Primitive enum schemas emit as alias types.
|
|
88
|
+
const primitiveType = resolvePrimitiveType(raw);
|
|
89
|
+
const enumValues = literalArray(raw['enum']);
|
|
90
|
+
if (primitiveType && enumValues) {
|
|
91
|
+
return {
|
|
92
|
+
name,
|
|
93
|
+
description: optionalString(raw['description']),
|
|
94
|
+
required: [],
|
|
95
|
+
properties: {},
|
|
96
|
+
enumValues,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// Array alias schemas.
|
|
100
|
+
const items = asRecord(raw['items']);
|
|
101
|
+
if (resolvedTypeIs(raw, 'array') && items) {
|
|
102
|
+
const itemRef = schemaRefName(items['$ref']);
|
|
103
|
+
const itemType = itemRef ? undefined : resolvePrimitiveType(items);
|
|
104
|
+
return {
|
|
105
|
+
name,
|
|
106
|
+
description: optionalString(raw['description']),
|
|
107
|
+
required: [],
|
|
108
|
+
properties: {},
|
|
109
|
+
arrayItemRef: itemRef ?? undefined,
|
|
110
|
+
arrayItemType: itemType ?? undefined,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
name,
|
|
115
|
+
description: optionalString(raw['description']),
|
|
116
|
+
required,
|
|
117
|
+
properties,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function buildFieldRule(rawInput, required) {
|
|
121
|
+
const raw = asRecord(rawInput) ?? {};
|
|
122
|
+
const rule = { required };
|
|
123
|
+
// $ref -> named reference.
|
|
124
|
+
const ref = schemaRefName(raw['$ref']);
|
|
125
|
+
if (ref) {
|
|
126
|
+
rule.ref = ref;
|
|
127
|
+
return rule;
|
|
128
|
+
}
|
|
129
|
+
// Array with items.
|
|
130
|
+
const items = asRecord(raw['items']);
|
|
131
|
+
if (resolvedTypeIs(raw, 'array') && items) {
|
|
132
|
+
rule.type = 'array';
|
|
133
|
+
const itemsRef = schemaRefName(items['$ref']);
|
|
134
|
+
if (itemsRef)
|
|
135
|
+
rule.itemsRef = itemsRef;
|
|
136
|
+
else
|
|
137
|
+
rule.itemsType = resolvePrimitiveType(items) ?? 'unknown';
|
|
138
|
+
const itemEnum = literalArray(items['enum']);
|
|
139
|
+
if (itemEnum)
|
|
140
|
+
rule.enumValues = itemEnum;
|
|
141
|
+
const description = optionalString(raw['description']);
|
|
142
|
+
if (description)
|
|
143
|
+
rule.description = description;
|
|
144
|
+
rule.nullable = isNullable(raw);
|
|
145
|
+
return rule;
|
|
146
|
+
}
|
|
147
|
+
// Primitive / object.
|
|
148
|
+
rule.type = resolvePrimitiveType(raw) ?? 'unknown';
|
|
149
|
+
rule.nullable = isNullable(raw);
|
|
150
|
+
const format = optionalString(raw['format']);
|
|
151
|
+
const description = optionalString(raw['description']);
|
|
152
|
+
const pattern = optionalString(raw['pattern']);
|
|
153
|
+
const enumValues = literalArray(raw['enum']);
|
|
154
|
+
if (format)
|
|
155
|
+
rule.format = format;
|
|
156
|
+
if (description)
|
|
157
|
+
rule.description = description;
|
|
158
|
+
if (typeof raw['minLength'] === 'number')
|
|
159
|
+
rule.minLength = raw['minLength'];
|
|
160
|
+
if (typeof raw['maxLength'] === 'number')
|
|
161
|
+
rule.maxLength = raw['maxLength'];
|
|
162
|
+
if (typeof raw['minimum'] === 'number')
|
|
163
|
+
rule.minimum = raw['minimum'];
|
|
164
|
+
if (typeof raw['maximum'] === 'number')
|
|
165
|
+
rule.maximum = raw['maximum'];
|
|
166
|
+
if (pattern)
|
|
167
|
+
rule.pattern = pattern;
|
|
168
|
+
if (enumValues)
|
|
169
|
+
rule.enumValues = enumValues;
|
|
170
|
+
return rule;
|
|
171
|
+
}
|
|
172
|
+
function resolvePrimitiveType(rawInput) {
|
|
173
|
+
const raw = asRecord(rawInput);
|
|
174
|
+
if (!raw)
|
|
175
|
+
return undefined;
|
|
176
|
+
const type = raw['type'];
|
|
177
|
+
if (Array.isArray(type)) {
|
|
178
|
+
const nonNull = type.find((value) => typeof value === 'string' && value !== 'null');
|
|
179
|
+
return nonNull ?? undefined;
|
|
180
|
+
}
|
|
181
|
+
if (typeof type === 'string')
|
|
182
|
+
return type;
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
function resolvedTypeIs(raw, target) {
|
|
186
|
+
return resolvePrimitiveType(raw) === target;
|
|
187
|
+
}
|
|
188
|
+
function isNullable(rawInput) {
|
|
189
|
+
const raw = asRecord(rawInput);
|
|
190
|
+
if (!raw)
|
|
191
|
+
return false;
|
|
192
|
+
if (raw['nullable'] === true)
|
|
193
|
+
return true;
|
|
194
|
+
const type = raw['type'];
|
|
195
|
+
return Array.isArray(type) && type.includes('null');
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Component references are resolved by their section, never by their last path
|
|
199
|
+
* segment: `#/components/requestBodies/CreateItemBody` names a request body,
|
|
200
|
+
* not a schema, and only `components.schemas` becomes a generated model.
|
|
201
|
+
*/
|
|
202
|
+
function componentRefName(ref, section) {
|
|
203
|
+
if (typeof ref !== 'string')
|
|
204
|
+
return undefined;
|
|
205
|
+
const prefix = `#/components/${section}/`;
|
|
206
|
+
return ref.startsWith(prefix) && ref.length > prefix.length
|
|
207
|
+
? ref.slice(prefix.length)
|
|
208
|
+
: undefined;
|
|
209
|
+
}
|
|
210
|
+
function schemaRefName(ref) {
|
|
211
|
+
return componentRefName(ref, 'schemas');
|
|
212
|
+
}
|
|
213
|
+
/** Follow a `#/components/<section>/<name>` chain to the object it names. */
|
|
214
|
+
function dereferenceComponent(value, section, components) {
|
|
215
|
+
const pool = asRecord(components?.[section]);
|
|
216
|
+
let record = asRecord(value);
|
|
217
|
+
const seen = new Set();
|
|
218
|
+
while (record && typeof record['$ref'] === 'string') {
|
|
219
|
+
const name = componentRefName(record['$ref'], section);
|
|
220
|
+
if (!name || seen.has(name))
|
|
221
|
+
return undefined;
|
|
222
|
+
seen.add(name);
|
|
223
|
+
record = asRecord(pool?.[name]);
|
|
224
|
+
}
|
|
225
|
+
return record;
|
|
226
|
+
}
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
// Operations
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
function buildOperations(pathsInput, componentsInput) {
|
|
231
|
+
const paths = asRecord(pathsInput);
|
|
232
|
+
if (!paths)
|
|
233
|
+
return [];
|
|
234
|
+
const components = asRecord(componentsInput);
|
|
235
|
+
const operations = [];
|
|
236
|
+
for (const [pathKey, pathItemInput] of Object.entries(paths)) {
|
|
237
|
+
const pathItem = asRecord(pathItemInput);
|
|
238
|
+
if (!pathItem)
|
|
239
|
+
continue;
|
|
240
|
+
const pathLevelParams = asArray(pathItem['parameters']);
|
|
241
|
+
for (const method of HTTP_METHODS) {
|
|
242
|
+
const op = asRecord(pathItem[method]);
|
|
243
|
+
if (!op)
|
|
244
|
+
continue;
|
|
245
|
+
operations.push(buildOperation(pathKey, method, op, pathLevelParams, components));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return operations.sort((a, b) => a.operationId.localeCompare(b.operationId));
|
|
249
|
+
}
|
|
250
|
+
function buildOperation(path, method, op, pathLevelParams, components) {
|
|
251
|
+
const rawTags = stringArray(op['tags']);
|
|
252
|
+
const tags = rawTags.length ? rawTags : ['Default'];
|
|
253
|
+
const params = mergeParams(pathLevelParams, op['parameters'], asRecord(components?.['parameters']));
|
|
254
|
+
const body = dereferenceComponent(op['requestBody'], 'requestBodies', components);
|
|
255
|
+
const bodySchemaRef = jsonSchemaRef(body);
|
|
256
|
+
const responses = {};
|
|
257
|
+
let successStatus;
|
|
258
|
+
let successRef;
|
|
259
|
+
for (const [status, resp] of Object.entries(asRecord(op['responses']) ?? {})) {
|
|
260
|
+
const response = dereferenceComponent(resp, 'responses', components);
|
|
261
|
+
const ref = jsonSchemaRef(response);
|
|
262
|
+
responses[status] = ref;
|
|
263
|
+
if (!successStatus && status.startsWith('2')) {
|
|
264
|
+
successStatus = status;
|
|
265
|
+
successRef = ref;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
const securitySchemes = [];
|
|
269
|
+
for (const security of asArray(op['security'])) {
|
|
270
|
+
const schemeRecord = asRecord(security);
|
|
271
|
+
if (!schemeRecord)
|
|
272
|
+
continue;
|
|
273
|
+
for (const key of Object.keys(schemeRecord)) {
|
|
274
|
+
if (!securitySchemes.includes(key))
|
|
275
|
+
securitySchemes.push(key);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const operationId = optionalString(op['operationId']) ?? synthesizeOperationId(method, path);
|
|
279
|
+
return {
|
|
280
|
+
operationId,
|
|
281
|
+
method,
|
|
282
|
+
path,
|
|
283
|
+
tag: tags[0] ?? 'Default',
|
|
284
|
+
tags,
|
|
285
|
+
summary: optionalString(op['summary']),
|
|
286
|
+
description: optionalString(op['description']),
|
|
287
|
+
params,
|
|
288
|
+
bodySchemaRef,
|
|
289
|
+
bodyRequired: body?.['required'] === true,
|
|
290
|
+
responses,
|
|
291
|
+
successStatus,
|
|
292
|
+
successRef,
|
|
293
|
+
securitySchemes,
|
|
294
|
+
requiredPermissions: stringArray(op['x-required-permissions']),
|
|
295
|
+
authorizationNotes: stringArray(op['x-authorization-notes']),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
function mergeParams(pathLevelParams, opParams, sharedParams) {
|
|
299
|
+
const out = [];
|
|
300
|
+
const slotByKey = new Map();
|
|
301
|
+
const ownedByOperation = new Set();
|
|
302
|
+
// The OpenAPI specification makes an operation-level parameter override a
|
|
303
|
+
// path-level one with the same name and location, so the operation pass
|
|
304
|
+
// replaces the entry in place rather than being dropped as a duplicate. The
|
|
305
|
+
// path-level position is kept so parameter order stays stable, and the first
|
|
306
|
+
// declaration wins within each level.
|
|
307
|
+
const collect = (raws, fromOperation) => {
|
|
308
|
+
for (const raw of raws) {
|
|
309
|
+
const resolved = resolveParamRef(raw, sharedParams);
|
|
310
|
+
const name = optionalString(resolved?.['name']);
|
|
311
|
+
const rawLocation = optionalString(resolved?.['in']);
|
|
312
|
+
if (!resolved || !name || !rawLocation)
|
|
313
|
+
continue;
|
|
314
|
+
const key = `${rawLocation}:${name}`;
|
|
315
|
+
const slot = slotByKey.get(key);
|
|
316
|
+
if (slot !== undefined && (!fromOperation || ownedByOperation.has(key)))
|
|
317
|
+
continue;
|
|
318
|
+
const loc = rawLocation === 'path' || rawLocation === 'query' || rawLocation === 'header'
|
|
319
|
+
? rawLocation
|
|
320
|
+
: 'query';
|
|
321
|
+
const param = {
|
|
322
|
+
name,
|
|
323
|
+
in: loc,
|
|
324
|
+
required: resolved['required'] === true,
|
|
325
|
+
rule: buildFieldRule(resolved['schema'] ?? {}, resolved['required'] === true),
|
|
326
|
+
};
|
|
327
|
+
if (fromOperation)
|
|
328
|
+
ownedByOperation.add(key);
|
|
329
|
+
if (slot === undefined) {
|
|
330
|
+
slotByKey.set(key, out.length);
|
|
331
|
+
out.push(param);
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
out[slot] = param;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
collect(pathLevelParams, false);
|
|
339
|
+
collect(asArray(opParams), true);
|
|
340
|
+
return out;
|
|
341
|
+
}
|
|
342
|
+
function resolveParamRef(rawInput, sharedParams) {
|
|
343
|
+
const raw = asRecord(rawInput);
|
|
344
|
+
if (!raw)
|
|
345
|
+
return undefined;
|
|
346
|
+
const ref = componentRefName(raw['$ref'], 'parameters');
|
|
347
|
+
if (!ref || !sharedParams)
|
|
348
|
+
return raw;
|
|
349
|
+
return asRecord(sharedParams[ref]) ?? raw;
|
|
350
|
+
}
|
|
351
|
+
function synthesizeOperationId(method, path) {
|
|
352
|
+
const cleaned = path
|
|
353
|
+
.replace(/\/+/g, '/')
|
|
354
|
+
.split('/')
|
|
355
|
+
.filter(Boolean)
|
|
356
|
+
.map((seg) => seg.replace(/^\{/, 'by-').replace(/\}$/, ''))
|
|
357
|
+
.join('-');
|
|
358
|
+
return `${method}-${cleaned || 'root'}`;
|
|
359
|
+
}
|
|
360
|
+
function jsonSchemaRef(value) {
|
|
361
|
+
const record = asRecord(value);
|
|
362
|
+
const content = asRecord(record?.['content']);
|
|
363
|
+
const json = asRecord(content?.['application/json']);
|
|
364
|
+
const schema = asRecord(json?.['schema']);
|
|
365
|
+
return schemaRefName(schema?.['$ref']);
|
|
366
|
+
}
|
|
367
|
+
// ---------------------------------------------------------------------------
|
|
368
|
+
// Security & navigation
|
|
369
|
+
// ---------------------------------------------------------------------------
|
|
370
|
+
function buildSecuritySchemes(raw) {
|
|
371
|
+
if (!raw)
|
|
372
|
+
return [];
|
|
373
|
+
return Object.entries(raw).map(([name, value]) => {
|
|
374
|
+
const scheme = asRecord(value) ?? {};
|
|
375
|
+
return {
|
|
376
|
+
name,
|
|
377
|
+
type: String(scheme['type'] ?? 'unknown'),
|
|
378
|
+
scheme: optionalString(scheme['scheme']),
|
|
379
|
+
bearerFormat: optionalString(scheme['bearerFormat']),
|
|
380
|
+
in: optionalString(scheme['in']),
|
|
381
|
+
};
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
function buildNavigation(tags) {
|
|
385
|
+
const byName = new Map();
|
|
386
|
+
for (const t of tags) {
|
|
387
|
+
byName.set(t.name, { name: t.name, xIcon: t.xIcon, description: t.description, children: [] });
|
|
388
|
+
}
|
|
389
|
+
const roots = [];
|
|
390
|
+
for (const t of tags) {
|
|
391
|
+
const node = byName.get(t.name);
|
|
392
|
+
if (t.parent && byName.has(t.parent)) {
|
|
393
|
+
byName.get(t.parent).children.push(node);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
roots.push(node);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return roots;
|
|
400
|
+
}
|
|
401
|
+
function asRecord(value) {
|
|
402
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
403
|
+
return undefined;
|
|
404
|
+
}
|
|
405
|
+
return value;
|
|
406
|
+
}
|
|
407
|
+
function asArray(value) {
|
|
408
|
+
return Array.isArray(value) ? value : [];
|
|
409
|
+
}
|
|
410
|
+
function recordArray(value) {
|
|
411
|
+
return asArray(value).flatMap((item) => {
|
|
412
|
+
const record = asRecord(item);
|
|
413
|
+
return record ? [record] : [];
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
function stringArray(value) {
|
|
417
|
+
return asArray(value).map(String);
|
|
418
|
+
}
|
|
419
|
+
function optionalString(value) {
|
|
420
|
+
return value == null ? undefined : String(value);
|
|
421
|
+
}
|
|
422
|
+
function literalArray(value) {
|
|
423
|
+
if (!Array.isArray(value))
|
|
424
|
+
return undefined;
|
|
425
|
+
const literals = value.filter((item) => {
|
|
426
|
+
return typeof item === 'string' || typeof item === 'number';
|
|
427
|
+
});
|
|
428
|
+
return literals.length ? literals : undefined;
|
|
429
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Intermediate Representation (IR) that emitters consume. Keeping this thin +
|
|
4
|
+
* plain-object makes emitters trivial to unit test without pulling in an OpenAPI
|
|
5
|
+
* parser in the test path.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tiny rendering helpers. We use template literals + small utilities rather
|
|
4
|
+
* than a template engine to keep the generator dependency-free and the
|
|
5
|
+
* emitter output predictable.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.kebabCase = kebabCase;
|
|
9
|
+
exports.pascalCase = pascalCase;
|
|
10
|
+
exports.camelCase = camelCase;
|
|
11
|
+
exports.safeIdentifier = safeIdentifier;
|
|
12
|
+
exports.quote = quote;
|
|
13
|
+
exports.propertyKey = propertyKey;
|
|
14
|
+
exports.propertyAccess = propertyAccess;
|
|
15
|
+
exports.finalize = finalize;
|
|
16
|
+
exports.comment = comment;
|
|
17
|
+
exports.joinBlocks = joinBlocks;
|
|
18
|
+
/** kebab-case (preserving digits) — matches the naming style in `old/api/`. */
|
|
19
|
+
function kebabCase(input) {
|
|
20
|
+
return String(input)
|
|
21
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
22
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
|
|
23
|
+
.replace(/[^a-zA-Z0-9]+/g, '-')
|
|
24
|
+
.replace(/^-+|-+$/g, '')
|
|
25
|
+
.toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
/** PascalCase — used for class/interface names when sanitizing tags. */
|
|
28
|
+
function pascalCase(input) {
|
|
29
|
+
const words = String(input)
|
|
30
|
+
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
|
31
|
+
.trim()
|
|
32
|
+
.split(/\s+/)
|
|
33
|
+
.filter(Boolean)
|
|
34
|
+
.map((w) => w[0].toUpperCase() + w.slice(1))
|
|
35
|
+
.join('');
|
|
36
|
+
return words ? safeIdentifier(words) : '';
|
|
37
|
+
}
|
|
38
|
+
/** camelCase — used for variable / method / fn names. */
|
|
39
|
+
function camelCase(input) {
|
|
40
|
+
const pc = pascalCase(input);
|
|
41
|
+
return pc ? safeIdentifier(pc[0].toLowerCase() + pc.slice(1)) : '';
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Reserved words plus the identifiers a strict-mode module may not bind. An
|
|
45
|
+
* `operationId` is arbitrary text from the OpenAPI document, so `delete` or
|
|
46
|
+
* `2faVerify` reach the emitters as-is and would otherwise be written straight
|
|
47
|
+
* into `export function <name>(`.
|
|
48
|
+
*/
|
|
49
|
+
const RESERVED_WORDS = new Set([
|
|
50
|
+
'arguments',
|
|
51
|
+
'await',
|
|
52
|
+
'break',
|
|
53
|
+
'case',
|
|
54
|
+
'catch',
|
|
55
|
+
'class',
|
|
56
|
+
'const',
|
|
57
|
+
'continue',
|
|
58
|
+
'debugger',
|
|
59
|
+
'default',
|
|
60
|
+
'delete',
|
|
61
|
+
'do',
|
|
62
|
+
'else',
|
|
63
|
+
'enum',
|
|
64
|
+
'eval',
|
|
65
|
+
'export',
|
|
66
|
+
'extends',
|
|
67
|
+
'false',
|
|
68
|
+
'finally',
|
|
69
|
+
'for',
|
|
70
|
+
'function',
|
|
71
|
+
'if',
|
|
72
|
+
'implements',
|
|
73
|
+
'import',
|
|
74
|
+
'in',
|
|
75
|
+
'instanceof',
|
|
76
|
+
'interface',
|
|
77
|
+
'let',
|
|
78
|
+
'new',
|
|
79
|
+
'null',
|
|
80
|
+
'package',
|
|
81
|
+
'private',
|
|
82
|
+
'protected',
|
|
83
|
+
'public',
|
|
84
|
+
'return',
|
|
85
|
+
'static',
|
|
86
|
+
'super',
|
|
87
|
+
'switch',
|
|
88
|
+
'this',
|
|
89
|
+
'throw',
|
|
90
|
+
'true',
|
|
91
|
+
'try',
|
|
92
|
+
'typeof',
|
|
93
|
+
'undefined',
|
|
94
|
+
'var',
|
|
95
|
+
'void',
|
|
96
|
+
'while',
|
|
97
|
+
'with',
|
|
98
|
+
'yield',
|
|
99
|
+
]);
|
|
100
|
+
/**
|
|
101
|
+
* Make an unquoted identifier legal: prefix a leading digit, suffix a reserved
|
|
102
|
+
* word. Every generated function, class, interface and variable name goes
|
|
103
|
+
* through here, so a name and every reference to it stay in step.
|
|
104
|
+
*/
|
|
105
|
+
function safeIdentifier(name) {
|
|
106
|
+
const prefixed = /^[0-9]/.test(name) ? `_${name}` : name;
|
|
107
|
+
return RESERVED_WORDS.has(prefixed) ? `${prefixed}_` : prefixed;
|
|
108
|
+
}
|
|
109
|
+
const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
110
|
+
/**
|
|
111
|
+
* A single-quoted TypeScript string literal. Every quoted identifier the
|
|
112
|
+
* emitters produce must go through here — a schema property, a parameter name,
|
|
113
|
+
* or a path template is arbitrary text from the OpenAPI document, and an
|
|
114
|
+
* apostrophe in it would otherwise close the literal and emit broken source.
|
|
115
|
+
*/
|
|
116
|
+
function quote(value) {
|
|
117
|
+
const escaped = String(value)
|
|
118
|
+
.replace(/\\/g, '\\\\')
|
|
119
|
+
.replace(/'/g, "\\'")
|
|
120
|
+
.replace(/\r/g, '\\r')
|
|
121
|
+
.replace(/\n/g, '\\n');
|
|
122
|
+
return `'${escaped}'`;
|
|
123
|
+
}
|
|
124
|
+
/** A property key for an interface or object literal — bare when safe, quoted otherwise. */
|
|
125
|
+
function propertyKey(name) {
|
|
126
|
+
return IDENTIFIER.test(name) ? name : quote(name);
|
|
127
|
+
}
|
|
128
|
+
/** A property access suffix — dotted when safe, bracketed otherwise. */
|
|
129
|
+
function propertyAccess(name) {
|
|
130
|
+
return IDENTIFIER.test(name) ? `.${name}` : `[${quote(name)}]`;
|
|
131
|
+
}
|
|
132
|
+
/** Trim trailing whitespace on every line and ensure a single trailing newline. */
|
|
133
|
+
function finalize(text) {
|
|
134
|
+
const trimmed = text
|
|
135
|
+
.split('\n')
|
|
136
|
+
.map((line) => line.replace(/\s+$/g, ''))
|
|
137
|
+
.join('\n')
|
|
138
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
139
|
+
.replace(/^\s*\n/, '');
|
|
140
|
+
return trimmed.endsWith('\n') ? trimmed : trimmed + '\n';
|
|
141
|
+
}
|
|
142
|
+
/** Render an indented block-comment (1-line friendly). */
|
|
143
|
+
function comment(text) {
|
|
144
|
+
if (!text)
|
|
145
|
+
return '';
|
|
146
|
+
const safe = text.replace(/\*\//g, '*\\/');
|
|
147
|
+
return `/** ${safe} */`;
|
|
148
|
+
}
|
|
149
|
+
/** Join non-empty blocks with a blank line between them. */
|
|
150
|
+
function joinBlocks(blocks) {
|
|
151
|
+
return blocks.filter(Boolean).join('\n\n');
|
|
152
|
+
}
|