@backstage/backend-defaults 0.11.1 → 0.12.0

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.
Files changed (125) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/config.d.ts +195 -0
  3. package/dist/CreateBackend.cjs.js.map +1 -1
  4. package/dist/PackageDiscoveryService.cjs.js +13 -3
  5. package/dist/PackageDiscoveryService.cjs.js.map +1 -1
  6. package/dist/alpha/entrypoints/actions/DefaultActionsService.cjs.js.map +1 -1
  7. package/dist/alpha/entrypoints/actions/actionsServiceFactory.cjs.js.map +1 -1
  8. package/dist/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.cjs.js.map +1 -1
  9. package/dist/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js.map +1 -1
  10. package/dist/cache.d.ts +20 -1
  11. package/dist/database.d.ts +1 -1
  12. package/dist/discovery.d.ts +1 -1
  13. package/dist/discoveryFeatureLoader.cjs.js.map +1 -1
  14. package/dist/entrypoints/auditor/DefaultAuditorService.cjs.js.map +1 -1
  15. package/dist/entrypoints/auditor/WinstonRootAuditorService.cjs.js.map +1 -1
  16. package/dist/entrypoints/auditor/auditorServiceFactory.cjs.js.map +1 -1
  17. package/dist/entrypoints/auditor/types.cjs.js.map +1 -1
  18. package/dist/entrypoints/auditor/utils.cjs.js.map +1 -1
  19. package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -1
  20. package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -1
  21. package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -1
  22. package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js.map +1 -1
  23. package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -1
  24. package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -1
  25. package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -1
  26. package/dist/entrypoints/auth/external/static.cjs.js.map +1 -1
  27. package/dist/entrypoints/auth/helpers.cjs.js.map +1 -1
  28. package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -1
  29. package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -1
  30. package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -1
  31. package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -1
  32. package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -1
  33. package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -1
  34. package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -1
  35. package/dist/entrypoints/cache/CacheManager.cjs.js +112 -7
  36. package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -1
  37. package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -1
  38. package/dist/entrypoints/cache/providers/infinispan/InfinispanKeyvStore.cjs.js +141 -0
  39. package/dist/entrypoints/cache/providers/infinispan/InfinispanKeyvStore.cjs.js.map +1 -0
  40. package/dist/entrypoints/cache/providers/infinispan/InfinispanOptionsMapper.cjs.js +129 -0
  41. package/dist/entrypoints/cache/providers/infinispan/InfinispanOptionsMapper.cjs.js.map +1 -0
  42. package/dist/entrypoints/cache/types.cjs.js.map +1 -1
  43. package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -1
  44. package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -1
  45. package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js.map +1 -1
  46. package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -1
  47. package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -1
  48. package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -1
  49. package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -1
  50. package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -1
  51. package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -1
  52. package/dist/entrypoints/discovery/SrvResolvers.cjs.js.map +1 -1
  53. package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -1
  54. package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -1
  55. package/dist/entrypoints/httpRouter/http/createAuthIntegrationRouter.cjs.js.map +1 -1
  56. package/dist/entrypoints/httpRouter/http/createCookieAuthRefreshMiddleware.cjs.js.map +1 -1
  57. package/dist/entrypoints/httpRouter/http/createCredentialsBarrier.cjs.js.map +1 -1
  58. package/dist/entrypoints/httpRouter/http/createLifecycleMiddleware.cjs.js.map +1 -1
  59. package/dist/entrypoints/httpRouter/http/createRateLimitMiddleware.cjs.js.map +1 -1
  60. package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -1
  61. package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -1
  62. package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -1
  63. package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -1
  64. package/dist/entrypoints/permissionsRegistry/permissionsRegistryServiceFactory.cjs.js.map +1 -1
  65. package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -1
  66. package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -1
  67. package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -1
  68. package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -1
  69. package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -1
  70. package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -1
  71. package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -1
  72. package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -1
  73. package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -1
  74. package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -1
  75. package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -1
  76. package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -1
  77. package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -1
  78. package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -1
  79. package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js +3 -0
  80. package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -1
  81. package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -1
  82. package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -1
  83. package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -1
  84. package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -1
  85. package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -1
  86. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -1
  87. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -1
  88. package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -1
  89. package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -1
  90. package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -1
  91. package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -1
  92. package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -1
  93. package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -1
  94. package/dist/entrypoints/urlReader/lib/AzureBlobStorageUrlReader.cjs.js.map +1 -1
  95. package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -1
  96. package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -1
  97. package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -1
  98. package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js.map +1 -1
  99. package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -1
  100. package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -1
  101. package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -1
  102. package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -1
  103. package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -1
  104. package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -1
  105. package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -1
  106. package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -1
  107. package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -1
  108. package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -1
  109. package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -1
  110. package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -1
  111. package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -1
  112. package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -1
  113. package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -1
  114. package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -1
  115. package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -1
  116. package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -1
  117. package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -1
  118. package/dist/httpAuth.d.ts +1 -1
  119. package/dist/lib/RateLimitStoreFactory.cjs.js.map +1 -1
  120. package/dist/lib/escapeRegExp.cjs.js.map +1 -1
  121. package/dist/lib/rateLimitMiddleware.cjs.js.map +1 -1
  122. package/dist/package.json.cjs.js +2 -269
  123. package/dist/package.json.cjs.js.map +1 -1
  124. package/dist/urlReader.d.ts +1 -1
  125. package/package.json +12 -11
package/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # @backstage/backend-defaults
2
2
 
3
+ ## 0.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 133519b: feat: new cache manager `Infinispan Data Grid`
8
+
9
+ ### Patch Changes
10
+
11
+ - caee2eb: Fixed WinstonLogger throwing when redactions were null or undefined
12
+ - ed74af5: Fixed bug in PackageDiscoveryService where packages with "exports" field caused ERR_PACKAGE_PATH_NOT_EXPORTED error during backend startup.
13
+ - 3a7dad9: Updated `better-sqlite3` to v12
14
+ - Updated dependencies
15
+ - @backstage/cli-node@0.2.14
16
+ - @backstage/backend-app-api@1.2.6
17
+ - @backstage/plugin-auth-node@0.6.6
18
+ - @backstage/plugin-permission-node@0.10.3
19
+ - @backstage/backend-plugin-api@1.4.2
20
+ - @backstage/plugin-events-node@0.4.14
21
+
22
+ ## 0.11.2-next.0
23
+
24
+ ### Patch Changes
25
+
26
+ - caee2eb: Fixed WinstonLogger throwing when redactions were null or undefined
27
+ - 3a7dad9: Updated `better-sqlite3` to v12
28
+ - Updated dependencies
29
+ - @backstage/backend-app-api@1.2.6-next.0
30
+ - @backstage/plugin-auth-node@0.6.6-next.0
31
+ - @backstage/plugin-permission-node@0.10.3-next.0
32
+ - @backstage/backend-plugin-api@1.4.2-next.0
33
+ - @backstage/cli-node@0.2.13
34
+ - @backstage/config-loader@1.10.2
35
+ - @backstage/plugin-events-node@0.4.14-next.0
36
+ - @backstage/backend-dev-utils@0.1.5
37
+ - @backstage/config@1.3.3
38
+ - @backstage/errors@1.2.7
39
+ - @backstage/integration@1.17.1
40
+ - @backstage/integration-aws-node@0.1.17
41
+ - @backstage/types@1.2.1
42
+
3
43
  ## 0.11.1
4
44
 
5
45
  ### Patch Changes
package/config.d.ts CHANGED
@@ -750,6 +750,201 @@ export interface Config {
750
750
  connection: string;
751
751
  /** An optional default TTL (in milliseconds). */
752
752
  defaultTtl?: number | HumanDuration | string;
753
+ }
754
+ | {
755
+ /**
756
+ * Infinispan cache store configuration.
757
+ * @see https://docs.jboss.org/infinispan/hotrod-clients/javascript/1.0/apidocs/module-infinispan.html
758
+ */
759
+ store: 'infinispan';
760
+
761
+ /**
762
+ * An optional default TTL (in milliseconds).
763
+ */
764
+ defaultTtl?: number | HumanDuration | string;
765
+
766
+ /**
767
+ * Configuration for the Infinispan cache store.
768
+ */
769
+ infinispan?: {
770
+ /**
771
+ * Version of client/server protocol.
772
+ * @default '2.9' is the latest version.
773
+ */
774
+ version?: '2.9' | '2.5' | '2.2';
775
+
776
+ /**
777
+ * Infinispan Cache Name if not provided default is `cache` recommended to set this.
778
+ */
779
+ cacheName?: string;
780
+
781
+ /**
782
+ * Optional number of retries for operation.
783
+ * Defaults to 3.
784
+ */
785
+ maxRetries?: number;
786
+
787
+ /**
788
+ * Optional flag to controls whether the client deals with topology updates or not.
789
+ * @default true
790
+ */
791
+ topologyUpdates?: boolean;
792
+
793
+ /**
794
+ * Media type of the cache contents.
795
+ * @default 'text/plain'
796
+ */
797
+ mediaType?: 'text/plain' | 'application/json';
798
+
799
+ /**
800
+ * Optional data format configuration.
801
+ * If not provided, defaults to text/plain for both key and value.
802
+ */
803
+ dataFormat?: {
804
+ /**
805
+ * Type of the key in the cache.
806
+ * @default 'text/plain'
807
+ */
808
+ keyType?: 'text/plain' | 'application/json';
809
+ /**
810
+ * Type of the value in the cache.
811
+ * @default 'text/plain'
812
+ */
813
+ valueType?: 'text/plain' | 'application/json';
814
+ };
815
+ /**
816
+ * Infinispan server host and port configuration.
817
+ * If this is an array, the client will connect to all servers in the list based on TOPOLOGY_AWARE routing.
818
+ * If this is a single object, it will be used as the default server.
819
+ */
820
+ servers?:
821
+ | Array<{
822
+ /**
823
+ * Infinispan server host.
824
+ */
825
+ host: string;
826
+ /**
827
+ * Infinispan server port (Hot Rod protocol). Defaults to `11222`.
828
+ */
829
+ port?: number;
830
+ }>
831
+ | {
832
+ /**
833
+ * Infinispan server host. Defaults to `127.0.0.1`.
834
+ */
835
+ host?: string;
836
+ /**
837
+ * Infinispan server port (Hot Rod protocol). Defaults to `11222`.
838
+ */
839
+ port?: number;
840
+ };
841
+ authentication?: {
842
+ /**
843
+ * Enable authentication. Defaults to `false`.
844
+ */
845
+ enabled?: boolean;
846
+ /**
847
+ * Select the SASL mechanism to use. Can be one of PLAIN, DIGEST-MD5, SCRAM-SHA-1, SCRAM-SHA-256, SCRAM-SHA-384, SCRAM-SHA-512, EXTERNAL, OAUTHBEARER
848
+ */
849
+ saslMechanism?: string;
850
+ /**
851
+ * userName for authentication.
852
+ */
853
+ userName?: string;
854
+ /**
855
+ * Password for authentication.
856
+ * @visibility secret
857
+ */
858
+ password?: string;
859
+ /**
860
+ * The OAuth token. Required by the OAUTHBEARER mechanism.
861
+ * @visibility secret
862
+ */
863
+ token?: string;
864
+ /**
865
+ * The SASL authorization ID.
866
+ */
867
+ authzid?: string;
868
+ };
869
+
870
+ /**
871
+ * TLS/SSL configuration.
872
+ */
873
+ ssl?: {
874
+ /**
875
+ * Enable ssl connection. Defaults to `false`.
876
+ * @default false
877
+ */
878
+ enabled?: boolean;
879
+
880
+ /**
881
+ * Optional field with secure protocol in use.
882
+ * @default TLSv1_2_method
883
+ */
884
+ secureProtocol?: string;
885
+
886
+ /**
887
+ * Optional paths of trusted SSL certificates.
888
+ */
889
+ trustCerts?: Array<string>;
890
+
891
+ clientAuth?: {
892
+ /**
893
+ * Optional path to client authentication key
894
+ */
895
+ key?: string;
896
+ /**
897
+ * Optional password for client key
898
+ */
899
+ passphrase?: string;
900
+ /**
901
+ * Optional client certificate
902
+ */
903
+ cert?: string;
904
+ };
905
+
906
+ /**
907
+ * Optional SNI host name.
908
+ */
909
+ sniHostName?: string;
910
+
911
+ /**
912
+ * Optional crypto store configuration.
913
+ */
914
+ cryptoStore?: {
915
+ /** Optional crypto store path. */
916
+ path?: string;
917
+ /** Optional password for crypto store. */
918
+ passphrase?: string;
919
+ };
920
+ };
921
+
922
+ /**
923
+ * Optional additional clusters for cross-site failovers.
924
+ * Array.<Cluster>
925
+ */
926
+ clusters?: Array<{
927
+ /**
928
+ * Optional Cluster name
929
+ */
930
+ name?: string;
931
+
932
+ /**
933
+ * Cluster servers details.
934
+ * Array.<ServerAddress>
935
+ */
936
+ servers: Array<{
937
+ /**
938
+ * Infinispan cluster server host.
939
+ */
940
+ host: string;
941
+ /**
942
+ * Infinispan server port (Hot Rod protocol). Defaults to `11222`.
943
+ */
944
+ port?: number;
945
+ }>;
946
+ }>;
947
+ };
753
948
  };
754
949
 
755
950
  cors?: {
@@ -1 +1 @@
1
- {"version":3,"file":"CreateBackend.cjs.js","sources":["../src/CreateBackend.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Backend, createSpecializedBackend } from '@backstage/backend-app-api';\nimport { auditorServiceFactory } from '@backstage/backend-defaults/auditor';\nimport { authServiceFactory } from '@backstage/backend-defaults/auth';\nimport { cacheServiceFactory } from '@backstage/backend-defaults/cache';\nimport { databaseServiceFactory } from '@backstage/backend-defaults/database';\nimport { discoveryServiceFactory } from '@backstage/backend-defaults/discovery';\nimport { httpAuthServiceFactory } from '@backstage/backend-defaults/httpAuth';\nimport { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';\nimport { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';\nimport { loggerServiceFactory } from '@backstage/backend-defaults/logger';\nimport { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';\nimport { permissionsRegistryServiceFactory } from '@backstage/backend-defaults/permissionsRegistry';\nimport { rootConfigServiceFactory } from '@backstage/backend-defaults/rootConfig';\nimport { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';\nimport { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';\nimport { rootLoggerServiceFactory } from '@backstage/backend-defaults/rootLogger';\nimport { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';\nimport { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader';\nimport { userInfoServiceFactory } from '@backstage/backend-defaults/userInfo';\nimport { eventsServiceFactory } from '@backstage/plugin-events-node';\nimport {\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n} from '@backstage/backend-defaults/alpha';\n\nexport const defaultServiceFactories = [\n auditorServiceFactory,\n authServiceFactory,\n cacheServiceFactory,\n rootConfigServiceFactory,\n databaseServiceFactory,\n discoveryServiceFactory,\n httpAuthServiceFactory,\n httpRouterServiceFactory,\n lifecycleServiceFactory,\n loggerServiceFactory,\n permissionsServiceFactory,\n permissionsRegistryServiceFactory,\n rootHealthServiceFactory,\n rootHttpRouterServiceFactory,\n rootLifecycleServiceFactory,\n rootLoggerServiceFactory,\n schedulerServiceFactory,\n userInfoServiceFactory,\n urlReaderServiceFactory,\n eventsServiceFactory,\n\n // alpha services\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n];\n\n/**\n * @public\n */\nexport function createBackend(): Backend {\n return createSpecializedBackend({ defaultServiceFactories });\n}\n"],"names":["auditorServiceFactory","authServiceFactory","cacheServiceFactory","rootConfigServiceFactory","databaseServiceFactory","discoveryServiceFactory","httpAuthServiceFactory","httpRouterServiceFactory","lifecycleServiceFactory","loggerServiceFactory","permissionsServiceFactory","permissionsRegistryServiceFactory","rootHealthServiceFactory","rootHttpRouterServiceFactory","rootLifecycleServiceFactory","rootLoggerServiceFactory","schedulerServiceFactory","userInfoServiceFactory","urlReaderServiceFactory","eventsServiceFactory","actionsRegistryServiceFactory","actionsServiceFactory","createSpecializedBackend"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA0CO,MAAM,uBAA0B,GAAA;AAAA,EACrCA,6BAAA;AAAA,EACAC,uBAAA;AAAA,EACAC,yBAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,2BAAA;AAAA,EACAC,qCAAA;AAAA,EACAC,qDAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,2CAAA;AAAA,EACAC,yCAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,qCAAA;AAAA;AAAA,EAGAC,mCAAA;AAAA,EACAC;AACF;AAKO,SAAS,aAAyB,GAAA;AACvC,EAAO,OAAAC,sCAAA,CAAyB,EAAE,uBAAA,EAAyB,CAAA;AAC7D;;;;;"}
1
+ {"version":3,"file":"CreateBackend.cjs.js","sources":["../src/CreateBackend.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Backend, createSpecializedBackend } from '@backstage/backend-app-api';\nimport { auditorServiceFactory } from '@backstage/backend-defaults/auditor';\nimport { authServiceFactory } from '@backstage/backend-defaults/auth';\nimport { cacheServiceFactory } from '@backstage/backend-defaults/cache';\nimport { databaseServiceFactory } from '@backstage/backend-defaults/database';\nimport { discoveryServiceFactory } from '@backstage/backend-defaults/discovery';\nimport { httpAuthServiceFactory } from '@backstage/backend-defaults/httpAuth';\nimport { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';\nimport { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';\nimport { loggerServiceFactory } from '@backstage/backend-defaults/logger';\nimport { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';\nimport { permissionsRegistryServiceFactory } from '@backstage/backend-defaults/permissionsRegistry';\nimport { rootConfigServiceFactory } from '@backstage/backend-defaults/rootConfig';\nimport { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';\nimport { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';\nimport { rootLoggerServiceFactory } from '@backstage/backend-defaults/rootLogger';\nimport { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';\nimport { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader';\nimport { userInfoServiceFactory } from '@backstage/backend-defaults/userInfo';\nimport { eventsServiceFactory } from '@backstage/plugin-events-node';\nimport {\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n} from '@backstage/backend-defaults/alpha';\n\nexport const defaultServiceFactories = [\n auditorServiceFactory,\n authServiceFactory,\n cacheServiceFactory,\n rootConfigServiceFactory,\n databaseServiceFactory,\n discoveryServiceFactory,\n httpAuthServiceFactory,\n httpRouterServiceFactory,\n lifecycleServiceFactory,\n loggerServiceFactory,\n permissionsServiceFactory,\n permissionsRegistryServiceFactory,\n rootHealthServiceFactory,\n rootHttpRouterServiceFactory,\n rootLifecycleServiceFactory,\n rootLoggerServiceFactory,\n schedulerServiceFactory,\n userInfoServiceFactory,\n urlReaderServiceFactory,\n eventsServiceFactory,\n\n // alpha services\n actionsRegistryServiceFactory,\n actionsServiceFactory,\n];\n\n/**\n * @public\n */\nexport function createBackend(): Backend {\n return createSpecializedBackend({ defaultServiceFactories });\n}\n"],"names":["auditorServiceFactory","authServiceFactory","cacheServiceFactory","rootConfigServiceFactory","databaseServiceFactory","discoveryServiceFactory","httpAuthServiceFactory","httpRouterServiceFactory","lifecycleServiceFactory","loggerServiceFactory","permissionsServiceFactory","permissionsRegistryServiceFactory","rootHealthServiceFactory","rootHttpRouterServiceFactory","rootLifecycleServiceFactory","rootLoggerServiceFactory","schedulerServiceFactory","userInfoServiceFactory","urlReaderServiceFactory","eventsServiceFactory","actionsRegistryServiceFactory","actionsServiceFactory","createSpecializedBackend"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA0CO,MAAM,uBAAA,GAA0B;AAAA,EACrCA,6BAAA;AAAA,EACAC,uBAAA;AAAA,EACAC,yBAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,2BAAA;AAAA,EACAC,qCAAA;AAAA,EACAC,qDAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,2CAAA;AAAA,EACAC,yCAAA;AAAA,EACAC,mCAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,+BAAA;AAAA,EACAC,iCAAA;AAAA,EACAC,qCAAA;AAAA;AAAA,EAGAC,mCAAA;AAAA,EACAC;AACF;AAKO,SAAS,aAAA,GAAyB;AACvC,EAAA,OAAOC,sCAAA,CAAyB,EAAE,uBAAA,EAAyB,CAAA;AAC7D;;;;;"}
@@ -2,6 +2,7 @@
2
2
 
3
3
  var fs = require('fs-extra');
4
4
  var platformPath = require('path');
5
+ var errors = require('@backstage/errors');
5
6
 
6
7
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
7
8
 
@@ -72,9 +73,18 @@ class PackageDiscoveryService {
72
73
  );
73
74
  const features = [];
74
75
  for (const name of dependencyNames) {
75
- const depPkg = require(require.resolve(`${name}/package.json`, {
76
- paths: [packageDir]
77
- }));
76
+ let depPkg;
77
+ try {
78
+ const packageJsonPath = require.resolve(`${name}/package.json`, {
79
+ paths: [packageDir]
80
+ });
81
+ depPkg = require(packageJsonPath);
82
+ } catch (error) {
83
+ if (errors.isError(error) && error.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
84
+ continue;
85
+ }
86
+ throw error;
87
+ }
78
88
  if (!depPkg?.backstage?.role || !DETECTED_PACKAGE_ROLES.includes(depPkg.backstage.role)) {
79
89
  continue;
80
90
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PackageDiscoveryService.cjs.js","sources":["../src/PackageDiscoveryService.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs-extra';\nimport { resolve as resolvePath, dirname } from 'path';\n\nimport {\n BackendFeature,\n RootConfigService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { BackstagePackageJson } from '@backstage/cli-node';\n\nconst DETECTED_PACKAGE_ROLES = [\n 'node-library',\n 'backend',\n 'backend-plugin',\n 'backend-plugin-module',\n];\n\n/** @internal */\nfunction isBackendFeature(value: unknown): value is BackendFeature {\n return (\n !!value &&\n ['object', 'function'].includes(typeof value) &&\n (value as BackendFeature).$$type === '@backstage/BackendFeature'\n );\n}\n\n/** @internal */\nfunction isBackendFeatureFactory(\n value: unknown,\n): value is () => BackendFeature {\n return (\n !!value &&\n typeof value === 'function' &&\n (value as any).$$type === '@backstage/BackendFeatureFactory'\n );\n}\n\n/** @internal */\nasync function findClosestPackageDir(\n searchDir: string,\n): Promise<string | undefined> {\n let path = searchDir;\n\n // Some confidence check to avoid infinite loop\n for (let i = 0; i < 1000; i++) {\n const packagePath = resolvePath(path, 'package.json');\n const exists = await fs.pathExists(packagePath);\n if (exists) {\n return path;\n }\n\n const newPath = dirname(path);\n if (newPath === path) {\n return undefined;\n }\n path = newPath;\n }\n\n throw new Error(\n `Iteration limit reached when searching for root package.json at ${searchDir}`,\n );\n}\n\n/** @internal */\nexport class PackageDiscoveryService {\n constructor(\n private readonly config: RootConfigService,\n private readonly logger: RootLoggerService,\n ) {}\n\n getDependencyNames(path: string) {\n const { dependencies } = require(path) as BackstagePackageJson;\n const packagesConfig = this.config.getOptional('backend.packages');\n\n const dependencyNames = Object.keys(dependencies || {});\n\n if (packagesConfig === 'all') {\n return dependencyNames;\n }\n\n const includedPackagesConfig = this.config.getOptionalStringArray(\n 'backend.packages.include',\n );\n\n const includedPackages = includedPackagesConfig\n ? new Set(includedPackagesConfig)\n : dependencyNames;\n const excludedPackagesSet = new Set(\n this.config.getOptionalStringArray('backend.packages.exclude'),\n );\n\n return [...includedPackages].filter(name => !excludedPackagesSet.has(name));\n }\n\n async getBackendFeatures(): Promise<{ features: Array<BackendFeature> }> {\n const packagesConfig = this.config.getOptional('backend.packages');\n if (!packagesConfig || Object.keys(packagesConfig).length === 0) {\n return { features: [] };\n }\n\n const packageDir = await findClosestPackageDir(process.argv[1]);\n if (!packageDir) {\n throw new Error('Package discovery failed to find package.json');\n }\n const dependencyNames = this.getDependencyNames(\n resolvePath(packageDir, 'package.json'),\n );\n\n const features: BackendFeature[] = [];\n\n for (const name of dependencyNames) {\n const depPkg = require(require.resolve(`${name}/package.json`, {\n paths: [packageDir],\n })) as BackstagePackageJson;\n if (\n !depPkg?.backstage?.role ||\n !DETECTED_PACKAGE_ROLES.includes(depPkg.backstage.role)\n ) {\n continue; // Not a backstage backend package, ignore\n }\n\n const exportedModulePaths = [\n require.resolve(name, {\n paths: [packageDir],\n }),\n ];\n\n // Find modules exported as alpha\n try {\n exportedModulePaths.push(\n require.resolve(`${name}/alpha`, { paths: [packageDir] }),\n );\n } catch {\n /* ignore */\n }\n\n for (const modulePath of exportedModulePaths) {\n const mod = require(modulePath);\n\n if (isBackendFeature(mod.default)) {\n this.logger.info(`Detected: ${name}`);\n features.push(mod.default);\n }\n if (isBackendFeatureFactory(mod.default)) {\n this.logger.info(`Detected: ${name}`);\n features.push(mod.default());\n }\n }\n }\n\n return { features };\n }\n}\n"],"names":["resolvePath","fs","dirname"],"mappings":"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"}
1
+ {"version":3,"file":"PackageDiscoveryService.cjs.js","sources":["../src/PackageDiscoveryService.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs-extra';\nimport { resolve as resolvePath, dirname } from 'path';\n\nimport {\n BackendFeature,\n RootConfigService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { BackstagePackageJson } from '@backstage/cli-node';\nimport { isError } from '@backstage/errors';\n\nconst DETECTED_PACKAGE_ROLES = [\n 'node-library',\n 'backend',\n 'backend-plugin',\n 'backend-plugin-module',\n];\n\n/** @internal */\nfunction isBackendFeature(value: unknown): value is BackendFeature {\n return (\n !!value &&\n ['object', 'function'].includes(typeof value) &&\n (value as BackendFeature).$$type === '@backstage/BackendFeature'\n );\n}\n\n/** @internal */\nfunction isBackendFeatureFactory(\n value: unknown,\n): value is () => BackendFeature {\n return (\n !!value &&\n typeof value === 'function' &&\n (value as any).$$type === '@backstage/BackendFeatureFactory'\n );\n}\n\n/** @internal */\nasync function findClosestPackageDir(\n searchDir: string,\n): Promise<string | undefined> {\n let path = searchDir;\n\n // Some confidence check to avoid infinite loop\n for (let i = 0; i < 1000; i++) {\n const packagePath = resolvePath(path, 'package.json');\n const exists = await fs.pathExists(packagePath);\n if (exists) {\n return path;\n }\n\n const newPath = dirname(path);\n if (newPath === path) {\n return undefined;\n }\n path = newPath;\n }\n\n throw new Error(\n `Iteration limit reached when searching for root package.json at ${searchDir}`,\n );\n}\n\n/** @internal */\nexport class PackageDiscoveryService {\n constructor(\n private readonly config: RootConfigService,\n private readonly logger: RootLoggerService,\n ) {}\n\n getDependencyNames(path: string) {\n const { dependencies } = require(path) as BackstagePackageJson;\n const packagesConfig = this.config.getOptional('backend.packages');\n\n const dependencyNames = Object.keys(dependencies || {});\n\n if (packagesConfig === 'all') {\n return dependencyNames;\n }\n\n const includedPackagesConfig = this.config.getOptionalStringArray(\n 'backend.packages.include',\n );\n\n const includedPackages = includedPackagesConfig\n ? new Set(includedPackagesConfig)\n : dependencyNames;\n const excludedPackagesSet = new Set(\n this.config.getOptionalStringArray('backend.packages.exclude'),\n );\n\n return [...includedPackages].filter(name => !excludedPackagesSet.has(name));\n }\n\n async getBackendFeatures(): Promise<{ features: Array<BackendFeature> }> {\n const packagesConfig = this.config.getOptional('backend.packages');\n if (!packagesConfig || Object.keys(packagesConfig).length === 0) {\n return { features: [] };\n }\n\n const packageDir = await findClosestPackageDir(process.argv[1]);\n if (!packageDir) {\n throw new Error('Package discovery failed to find package.json');\n }\n const dependencyNames = this.getDependencyNames(\n resolvePath(packageDir, 'package.json'),\n );\n\n const features: BackendFeature[] = [];\n\n for (const name of dependencyNames) {\n let depPkg: BackstagePackageJson;\n try {\n const packageJsonPath = require.resolve(`${name}/package.json`, {\n paths: [packageDir],\n });\n depPkg = require(packageJsonPath) as BackstagePackageJson;\n } catch (error) {\n // Handle packages with \"exports\" field that don't export ./package.json\n if (isError(error) && error.code === 'ERR_PACKAGE_PATH_NOT_EXPORTED') {\n continue; // Skip packages that don't export package.json - they can't be Backstage packages\n }\n throw error;\n }\n if (\n !depPkg?.backstage?.role ||\n !DETECTED_PACKAGE_ROLES.includes(depPkg.backstage.role)\n ) {\n continue; // Not a backstage backend package, ignore\n }\n\n const exportedModulePaths = [\n require.resolve(name, {\n paths: [packageDir],\n }),\n ];\n\n // Find modules exported as alpha\n try {\n exportedModulePaths.push(\n require.resolve(`${name}/alpha`, { paths: [packageDir] }),\n );\n } catch {\n /* ignore */\n }\n\n for (const modulePath of exportedModulePaths) {\n const mod = require(modulePath);\n\n if (isBackendFeature(mod.default)) {\n this.logger.info(`Detected: ${name}`);\n features.push(mod.default);\n }\n if (isBackendFeatureFactory(mod.default)) {\n this.logger.info(`Detected: ${name}`);\n features.push(mod.default());\n }\n }\n }\n\n return { features };\n }\n}\n"],"names":["resolvePath","fs","dirname","isError"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultActionsService.cjs.js","sources":["../../../../src/alpha/entrypoints/actions/DefaultActionsService.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n AuthService,\n BackstageCredentials,\n DiscoveryService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport {\n ActionsService,\n ActionsServiceAction,\n} from '@backstage/backend-plugin-api/alpha';\n\nexport class DefaultActionsService implements ActionsService {\n private constructor(\n private readonly discovery: DiscoveryService,\n private readonly config: RootConfigService,\n private readonly logger: LoggerService,\n private readonly auth: AuthService,\n ) {}\n\n static create({\n discovery,\n config,\n logger,\n auth,\n }: {\n discovery: DiscoveryService;\n config: RootConfigService;\n logger: LoggerService;\n auth: AuthService;\n }) {\n return new DefaultActionsService(discovery, config, logger, auth);\n }\n\n async list({ credentials }: { credentials: BackstageCredentials }) {\n const pluginSources =\n this.config.getOptionalStringArray('backend.actions.pluginSources') ?? [];\n\n const remoteActionsList = await Promise.all(\n pluginSources.map(async source => {\n try {\n const response = await this.makeRequest({\n path: `/.backstage/actions/v1/actions`,\n pluginId: source,\n credentials,\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n const { actions } = (await response.json()) as {\n actions: ActionsServiceAction;\n };\n\n return actions;\n } catch (error) {\n this.logger.warn(`Failed to fetch actions from ${source}`, error);\n return [];\n }\n }),\n );\n\n return { actions: remoteActionsList.flat() };\n }\n\n async invoke(opts: {\n id: string;\n input?: JsonObject;\n credentials: BackstageCredentials;\n }) {\n const pluginId = this.pluginIdFromActionId(opts.id);\n const response = await this.makeRequest({\n path: `/.backstage/actions/v1/actions/${encodeURIComponent(\n opts.id,\n )}/invoke`,\n pluginId,\n credentials: opts.credentials,\n options: {\n method: 'POST',\n body: JSON.stringify(opts.input),\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { output } = await response.json();\n return { output };\n }\n\n private async makeRequest(opts: {\n path: string;\n pluginId: string;\n options?: RequestInit;\n credentials: BackstageCredentials;\n }) {\n const { path, pluginId, credentials, options } = opts;\n const baseUrl = await this.discovery.getBaseUrl(pluginId);\n\n const { token } = await this.auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: opts.pluginId,\n });\n\n return fetch(`${baseUrl}${path}`, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${token}`,\n },\n });\n }\n\n private pluginIdFromActionId(id: string): string {\n const colonIndex = id.indexOf(':');\n if (colonIndex === -1) {\n throw new Error(`Invalid action id: ${id}`);\n }\n return id.substring(0, colonIndex);\n }\n}\n"],"names":["ResponseError"],"mappings":"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"}
1
+ {"version":3,"file":"DefaultActionsService.cjs.js","sources":["../../../../src/alpha/entrypoints/actions/DefaultActionsService.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n AuthService,\n BackstageCredentials,\n DiscoveryService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport {\n ActionsService,\n ActionsServiceAction,\n} from '@backstage/backend-plugin-api/alpha';\n\nexport class DefaultActionsService implements ActionsService {\n private constructor(\n private readonly discovery: DiscoveryService,\n private readonly config: RootConfigService,\n private readonly logger: LoggerService,\n private readonly auth: AuthService,\n ) {}\n\n static create({\n discovery,\n config,\n logger,\n auth,\n }: {\n discovery: DiscoveryService;\n config: RootConfigService;\n logger: LoggerService;\n auth: AuthService;\n }) {\n return new DefaultActionsService(discovery, config, logger, auth);\n }\n\n async list({ credentials }: { credentials: BackstageCredentials }) {\n const pluginSources =\n this.config.getOptionalStringArray('backend.actions.pluginSources') ?? [];\n\n const remoteActionsList = await Promise.all(\n pluginSources.map(async source => {\n try {\n const response = await this.makeRequest({\n path: `/.backstage/actions/v1/actions`,\n pluginId: source,\n credentials,\n });\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n const { actions } = (await response.json()) as {\n actions: ActionsServiceAction;\n };\n\n return actions;\n } catch (error) {\n this.logger.warn(`Failed to fetch actions from ${source}`, error);\n return [];\n }\n }),\n );\n\n return { actions: remoteActionsList.flat() };\n }\n\n async invoke(opts: {\n id: string;\n input?: JsonObject;\n credentials: BackstageCredentials;\n }) {\n const pluginId = this.pluginIdFromActionId(opts.id);\n const response = await this.makeRequest({\n path: `/.backstage/actions/v1/actions/${encodeURIComponent(\n opts.id,\n )}/invoke`,\n pluginId,\n credentials: opts.credentials,\n options: {\n method: 'POST',\n body: JSON.stringify(opts.input),\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const { output } = await response.json();\n return { output };\n }\n\n private async makeRequest(opts: {\n path: string;\n pluginId: string;\n options?: RequestInit;\n credentials: BackstageCredentials;\n }) {\n const { path, pluginId, credentials, options } = opts;\n const baseUrl = await this.discovery.getBaseUrl(pluginId);\n\n const { token } = await this.auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: opts.pluginId,\n });\n\n return fetch(`${baseUrl}${path}`, {\n ...options,\n headers: {\n ...options?.headers,\n Authorization: `Bearer ${token}`,\n },\n });\n }\n\n private pluginIdFromActionId(id: string): string {\n const colonIndex = id.indexOf(':');\n if (colonIndex === -1) {\n throw new Error(`Invalid action id: ${id}`);\n }\n return id.substring(0, colonIndex);\n }\n}\n"],"names":["ResponseError"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"actionsServiceFactory.cjs.js","sources":["../../../../src/alpha/entrypoints/actions/actionsServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createServiceFactory } from '@backstage/backend-plugin-api';\nimport { coreServices } from '@backstage/backend-plugin-api';\nimport { DefaultActionsService } from './DefaultActionsService';\nimport { actionsServiceRef } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const actionsServiceFactory = createServiceFactory({\n service: actionsServiceRef,\n deps: {\n discovery: coreServices.discovery,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n auth: coreServices.auth,\n },\n factory: ({ discovery, config, logger, auth }) =>\n DefaultActionsService.create({\n discovery,\n config,\n logger,\n auth,\n }),\n});\n"],"names":["createServiceFactory","actionsServiceRef","coreServices","DefaultActionsService"],"mappings":";;;;;;AAuBO,MAAM,wBAAwBA,qCAAqB,CAAA;AAAA,EACxD,OAAS,EAAAC,uBAAA;AAAA,EACT,IAAM,EAAA;AAAA,IACJ,WAAWC,6BAAa,CAAA,SAAA;AAAA,IACxB,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,QAAQA,6BAAa,CAAA,MAAA;AAAA,IACrB,MAAMA,6BAAa,CAAA;AAAA,GACrB;AAAA,EACA,OAAA,EAAS,CAAC,EAAE,SAAA,EAAW,QAAQ,MAAQ,EAAA,IAAA,EACrC,KAAAC,2CAAA,CAAsB,MAAO,CAAA;AAAA,IAC3B,SAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACD;AACL,CAAC;;;;"}
1
+ {"version":3,"file":"actionsServiceFactory.cjs.js","sources":["../../../../src/alpha/entrypoints/actions/actionsServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createServiceFactory } from '@backstage/backend-plugin-api';\nimport { coreServices } from '@backstage/backend-plugin-api';\nimport { DefaultActionsService } from './DefaultActionsService';\nimport { actionsServiceRef } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const actionsServiceFactory = createServiceFactory({\n service: actionsServiceRef,\n deps: {\n discovery: coreServices.discovery,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n auth: coreServices.auth,\n },\n factory: ({ discovery, config, logger, auth }) =>\n DefaultActionsService.create({\n discovery,\n config,\n logger,\n auth,\n }),\n});\n"],"names":["createServiceFactory","actionsServiceRef","coreServices","DefaultActionsService"],"mappings":";;;;;;AAuBO,MAAM,wBAAwBA,qCAAA,CAAqB;AAAA,EACxD,OAAA,EAASC,uBAAA;AAAA,EACT,IAAA,EAAM;AAAA,IACJ,WAAWC,6BAAA,CAAa,SAAA;AAAA,IACxB,QAAQA,6BAAA,CAAa,UAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa,MAAA;AAAA,IACrB,MAAMA,6BAAA,CAAa;AAAA,GACrB;AAAA,EACA,OAAA,EAAS,CAAC,EAAE,SAAA,EAAW,QAAQ,MAAA,EAAQ,IAAA,EAAK,KAC1CC,2CAAA,CAAsB,MAAA,CAAO;AAAA,IAC3B,SAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACD;AACL,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultActionsRegistryService.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n HttpAuthService,\n LoggerService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport PromiseRouter from 'express-promise-router';\nimport { Router, json } from 'express';\nimport { z, AnyZodObject } from 'zod';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport {\n ActionsRegistryActionOptions,\n ActionsRegistryService,\n} from '@backstage/backend-plugin-api/alpha';\nimport {\n ForwardedError,\n InputError,\n NotAllowedError,\n NotFoundError,\n} from '@backstage/errors';\n\nexport class DefaultActionsRegistryService implements ActionsRegistryService {\n private actions: Map<string, ActionsRegistryActionOptions<any, any>> =\n new Map();\n\n private constructor(\n private readonly logger: LoggerService,\n private readonly httpAuth: HttpAuthService,\n private readonly auth: AuthService,\n private readonly metadata: PluginMetadataService,\n ) {}\n\n static create({\n httpAuth,\n logger,\n auth,\n metadata,\n }: {\n httpAuth: HttpAuthService;\n logger: LoggerService;\n auth: AuthService;\n metadata: PluginMetadataService;\n }): DefaultActionsRegistryService {\n return new DefaultActionsRegistryService(logger, httpAuth, auth, metadata);\n }\n\n createRouter(): Router {\n const router = PromiseRouter();\n router.use(json());\n\n router.get('/.backstage/actions/v1/actions', (_, res) => {\n return res.json({\n actions: Array.from(this.actions.entries()).map(([id, action]) => ({\n id,\n ...action,\n attributes: {\n // Inspired by the @modelcontextprotocol/sdk defaults for the hints.\n // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812\n destructive: action.attributes?.destructive ?? true,\n idempotent: action.attributes?.idempotent ?? false,\n readOnly: action.attributes?.readOnly ?? false,\n },\n schema: {\n input: action.schema?.input\n ? zodToJsonSchema(action.schema.input(z))\n : zodToJsonSchema(z.object({})),\n output: action.schema?.output\n ? zodToJsonSchema(action.schema.output(z))\n : zodToJsonSchema(z.object({})),\n },\n })),\n });\n });\n\n router.post(\n '/.backstage/actions/v1/actions/:actionId/invoke',\n async (req, res) => {\n const credentials = await this.httpAuth.credentials(req);\n if (this.auth.isPrincipal(credentials, 'user')) {\n if (!credentials.principal.actor) {\n throw new NotAllowedError(\n `Actions must be invoked by a service, not a user`,\n );\n }\n } else if (this.auth.isPrincipal(credentials, 'none')) {\n throw new NotAllowedError(\n `Actions must be invoked by a service, not an anonymous request`,\n );\n }\n\n const action = this.actions.get(req.params.actionId);\n\n if (!action) {\n throw new NotFoundError(`Action \"${req.params.actionId}\" not found`);\n }\n\n const input = action.schema?.input\n ? action.schema.input(z).safeParse(req.body)\n : ({ success: true, data: undefined } as const);\n\n if (!input.success) {\n throw new InputError(\n `Invalid input to action \"${req.params.actionId}\"`,\n input.error,\n );\n }\n\n try {\n const result = await action.action({\n input: input.data,\n credentials,\n logger: this.logger,\n });\n\n const output = action.schema?.output\n ? action.schema.output(z).safeParse(result?.output)\n : ({ success: true, data: result?.output } as const);\n\n if (!output.success) {\n throw new InputError(\n `Invalid output from action \"${req.params.actionId}\"`,\n output.error,\n );\n }\n\n res.json({ output: output.data });\n } catch (error) {\n throw new ForwardedError(\n `Failed execution of action \"${req.params.actionId}\"`,\n error,\n );\n }\n },\n );\n return router;\n }\n\n register<\n TInputSchema extends AnyZodObject,\n TOutputSchema extends AnyZodObject,\n >(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema>): void {\n const id = `${this.metadata.getId()}:${options.name}`;\n\n if (this.actions.has(id)) {\n throw new Error(`Action with id \"${id}\" is already registered`);\n }\n\n this.actions.set(id, options);\n }\n}\n"],"names":["PromiseRouter","json","zodToJsonSchema","z","NotAllowedError","NotFoundError","InputError","ForwardedError"],"mappings":";;;;;;;;;;;;;AAqCO,MAAM,6BAAgE,CAAA;AAAA,EAInE,WACW,CAAA,MAAA,EACA,QACA,EAAA,IAAA,EACA,QACjB,EAAA;AAJiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA;AAChB,EARK,OAAA,uBACF,GAAI,EAAA;AAAA,EASV,OAAO,MAAO,CAAA;AAAA,IACZ,QAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GAMgC,EAAA;AAChC,IAAA,OAAO,IAAI,6BAAA,CAA8B,MAAQ,EAAA,QAAA,EAAU,MAAM,QAAQ,CAAA;AAAA;AAC3E,EAEA,YAAuB,GAAA;AACrB,IAAA,MAAM,SAASA,uBAAc,EAAA;AAC7B,IAAO,MAAA,CAAA,GAAA,CAAIC,cAAM,CAAA;AAEjB,IAAA,MAAA,CAAO,GAAI,CAAA,gCAAA,EAAkC,CAAC,CAAA,EAAG,GAAQ,KAAA;AACvD,MAAA,OAAO,IAAI,IAAK,CAAA;AAAA,QACd,OAAS,EAAA,KAAA,CAAM,IAAK,CAAA,IAAA,CAAK,OAAQ,CAAA,OAAA,EAAS,CAAA,CAAE,GAAI,CAAA,CAAC,CAAC,EAAA,EAAI,MAAM,CAAO,MAAA;AAAA,UACjE,EAAA;AAAA,UACA,GAAG,MAAA;AAAA,UACH,UAAY,EAAA;AAAA;AAAA;AAAA,YAGV,WAAA,EAAa,MAAO,CAAA,UAAA,EAAY,WAAe,IAAA,IAAA;AAAA,YAC/C,UAAA,EAAY,MAAO,CAAA,UAAA,EAAY,UAAc,IAAA,KAAA;AAAA,YAC7C,QAAA,EAAU,MAAO,CAAA,UAAA,EAAY,QAAY,IAAA;AAAA,WAC3C;AAAA,UACA,MAAQ,EAAA;AAAA,YACN,OAAO,MAAO,CAAA,MAAA,EAAQ,KAClB,GAAAC,gCAAA,CAAgB,OAAO,MAAO,CAAA,KAAA,CAAMC,KAAC,CAAC,IACtCD,gCAAgB,CAAAC,KAAA,CAAE,MAAO,CAAA,EAAE,CAAC,CAAA;AAAA,YAChC,QAAQ,MAAO,CAAA,MAAA,EAAQ,MACnB,GAAAD,gCAAA,CAAgB,OAAO,MAAO,CAAA,MAAA,CAAOC,KAAC,CAAC,IACvCD,gCAAgB,CAAAC,KAAA,CAAE,MAAO,CAAA,EAAE,CAAC;AAAA;AAClC,SACA,CAAA;AAAA,OACH,CAAA;AAAA,KACF,CAAA;AAED,IAAO,MAAA,CAAA,IAAA;AAAA,MACL,iDAAA;AAAA,MACA,OAAO,KAAK,GAAQ,KAAA;AAClB,QAAA,MAAM,WAAc,GAAA,MAAM,IAAK,CAAA,QAAA,CAAS,YAAY,GAAG,CAAA;AACvD,QAAA,IAAI,IAAK,CAAA,IAAA,CAAK,WAAY,CAAA,WAAA,EAAa,MAAM,CAAG,EAAA;AAC9C,UAAI,IAAA,CAAC,WAAY,CAAA,SAAA,CAAU,KAAO,EAAA;AAChC,YAAA,MAAM,IAAIC,sBAAA;AAAA,cACR,CAAA,gDAAA;AAAA,aACF;AAAA;AACF,mBACS,IAAK,CAAA,IAAA,CAAK,WAAY,CAAA,WAAA,EAAa,MAAM,CAAG,EAAA;AACrD,UAAA,MAAM,IAAIA,sBAAA;AAAA,YACR,CAAA,8DAAA;AAAA,WACF;AAAA;AAGF,QAAA,MAAM,SAAS,IAAK,CAAA,OAAA,CAAQ,GAAI,CAAA,GAAA,CAAI,OAAO,QAAQ,CAAA;AAEnD,QAAA,IAAI,CAAC,MAAQ,EAAA;AACX,UAAA,MAAM,IAAIC,oBAAc,CAAA,CAAA,QAAA,EAAW,GAAI,CAAA,MAAA,CAAO,QAAQ,CAAa,WAAA,CAAA,CAAA;AAAA;AAGrE,QAAA,MAAM,QAAQ,MAAO,CAAA,MAAA,EAAQ,KACzB,GAAA,MAAA,CAAO,OAAO,KAAM,CAAAF,KAAC,CAAE,CAAA,SAAA,CAAU,IAAI,IAAI,CAAA,GACxC,EAAE,OAAS,EAAA,IAAA,EAAM,MAAM,KAAU,CAAA,EAAA;AAEtC,QAAI,IAAA,CAAC,MAAM,OAAS,EAAA;AAClB,UAAA,MAAM,IAAIG,iBAAA;AAAA,YACR,CAAA,yBAAA,EAA4B,GAAI,CAAA,MAAA,CAAO,QAAQ,CAAA,CAAA,CAAA;AAAA,YAC/C,KAAM,CAAA;AAAA,WACR;AAAA;AAGF,QAAI,IAAA;AACF,UAAM,MAAA,MAAA,GAAS,MAAM,MAAA,CAAO,MAAO,CAAA;AAAA,YACjC,OAAO,KAAM,CAAA,IAAA;AAAA,YACb,WAAA;AAAA,YACA,QAAQ,IAAK,CAAA;AAAA,WACd,CAAA;AAED,UAAA,MAAM,SAAS,MAAO,CAAA,MAAA,EAAQ,SAC1B,MAAO,CAAA,MAAA,CAAO,OAAOH,KAAC,CAAA,CAAE,SAAU,CAAA,MAAA,EAAQ,MAAM,CAC/C,GAAA,EAAE,SAAS,IAAM,EAAA,IAAA,EAAM,QAAQ,MAAO,EAAA;AAE3C,UAAI,IAAA,CAAC,OAAO,OAAS,EAAA;AACnB,YAAA,MAAM,IAAIG,iBAAA;AAAA,cACR,CAAA,4BAAA,EAA+B,GAAI,CAAA,MAAA,CAAO,QAAQ,CAAA,CAAA,CAAA;AAAA,cAClD,MAAO,CAAA;AAAA,aACT;AAAA;AAGF,UAAA,GAAA,CAAI,IAAK,CAAA,EAAE,MAAQ,EAAA,MAAA,CAAO,MAAM,CAAA;AAAA,iBACzB,KAAO,EAAA;AACd,UAAA,MAAM,IAAIC,qBAAA;AAAA,YACR,CAAA,4BAAA,EAA+B,GAAI,CAAA,MAAA,CAAO,QAAQ,CAAA,CAAA,CAAA;AAAA,YAClD;AAAA,WACF;AAAA;AACF;AACF,KACF;AACA,IAAO,OAAA,MAAA;AAAA;AACT,EAEA,SAGE,OAA0E,EAAA;AAC1E,IAAM,MAAA,EAAA,GAAK,GAAG,IAAK,CAAA,QAAA,CAAS,OAAO,CAAA,CAAA,EAAI,QAAQ,IAAI,CAAA,CAAA;AAEnD,IAAA,IAAI,IAAK,CAAA,OAAA,CAAQ,GAAI,CAAA,EAAE,CAAG,EAAA;AACxB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAmB,gBAAA,EAAA,EAAE,CAAyB,uBAAA,CAAA,CAAA;AAAA;AAGhE,IAAK,IAAA,CAAA,OAAA,CAAQ,GAAI,CAAA,EAAA,EAAI,OAAO,CAAA;AAAA;AAEhC;;;;"}
1
+ {"version":3,"file":"DefaultActionsRegistryService.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n HttpAuthService,\n LoggerService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport PromiseRouter from 'express-promise-router';\nimport { Router, json } from 'express';\nimport { z, AnyZodObject } from 'zod';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport {\n ActionsRegistryActionOptions,\n ActionsRegistryService,\n} from '@backstage/backend-plugin-api/alpha';\nimport {\n ForwardedError,\n InputError,\n NotAllowedError,\n NotFoundError,\n} from '@backstage/errors';\n\nexport class DefaultActionsRegistryService implements ActionsRegistryService {\n private actions: Map<string, ActionsRegistryActionOptions<any, any>> =\n new Map();\n\n private constructor(\n private readonly logger: LoggerService,\n private readonly httpAuth: HttpAuthService,\n private readonly auth: AuthService,\n private readonly metadata: PluginMetadataService,\n ) {}\n\n static create({\n httpAuth,\n logger,\n auth,\n metadata,\n }: {\n httpAuth: HttpAuthService;\n logger: LoggerService;\n auth: AuthService;\n metadata: PluginMetadataService;\n }): DefaultActionsRegistryService {\n return new DefaultActionsRegistryService(logger, httpAuth, auth, metadata);\n }\n\n createRouter(): Router {\n const router = PromiseRouter();\n router.use(json());\n\n router.get('/.backstage/actions/v1/actions', (_, res) => {\n return res.json({\n actions: Array.from(this.actions.entries()).map(([id, action]) => ({\n id,\n ...action,\n attributes: {\n // Inspired by the @modelcontextprotocol/sdk defaults for the hints.\n // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812\n destructive: action.attributes?.destructive ?? true,\n idempotent: action.attributes?.idempotent ?? false,\n readOnly: action.attributes?.readOnly ?? false,\n },\n schema: {\n input: action.schema?.input\n ? zodToJsonSchema(action.schema.input(z))\n : zodToJsonSchema(z.object({})),\n output: action.schema?.output\n ? zodToJsonSchema(action.schema.output(z))\n : zodToJsonSchema(z.object({})),\n },\n })),\n });\n });\n\n router.post(\n '/.backstage/actions/v1/actions/:actionId/invoke',\n async (req, res) => {\n const credentials = await this.httpAuth.credentials(req);\n if (this.auth.isPrincipal(credentials, 'user')) {\n if (!credentials.principal.actor) {\n throw new NotAllowedError(\n `Actions must be invoked by a service, not a user`,\n );\n }\n } else if (this.auth.isPrincipal(credentials, 'none')) {\n throw new NotAllowedError(\n `Actions must be invoked by a service, not an anonymous request`,\n );\n }\n\n const action = this.actions.get(req.params.actionId);\n\n if (!action) {\n throw new NotFoundError(`Action \"${req.params.actionId}\" not found`);\n }\n\n const input = action.schema?.input\n ? action.schema.input(z).safeParse(req.body)\n : ({ success: true, data: undefined } as const);\n\n if (!input.success) {\n throw new InputError(\n `Invalid input to action \"${req.params.actionId}\"`,\n input.error,\n );\n }\n\n try {\n const result = await action.action({\n input: input.data,\n credentials,\n logger: this.logger,\n });\n\n const output = action.schema?.output\n ? action.schema.output(z).safeParse(result?.output)\n : ({ success: true, data: result?.output } as const);\n\n if (!output.success) {\n throw new InputError(\n `Invalid output from action \"${req.params.actionId}\"`,\n output.error,\n );\n }\n\n res.json({ output: output.data });\n } catch (error) {\n throw new ForwardedError(\n `Failed execution of action \"${req.params.actionId}\"`,\n error,\n );\n }\n },\n );\n return router;\n }\n\n register<\n TInputSchema extends AnyZodObject,\n TOutputSchema extends AnyZodObject,\n >(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema>): void {\n const id = `${this.metadata.getId()}:${options.name}`;\n\n if (this.actions.has(id)) {\n throw new Error(`Action with id \"${id}\" is already registered`);\n }\n\n this.actions.set(id, options);\n }\n}\n"],"names":["PromiseRouter","json","zodToJsonSchema","z","NotAllowedError","NotFoundError","InputError","ForwardedError"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"actionsRegistryServiceFactory.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { DefaultActionsRegistryService } from './DefaultActionsRegistryService';\nimport { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const actionsRegistryServiceFactory = createServiceFactory({\n service: actionsRegistryServiceRef,\n deps: {\n metadata: coreServices.pluginMetadata,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n logger: coreServices.logger,\n auth: coreServices.auth,\n },\n factory: ({ metadata, httpRouter, httpAuth, logger, auth }) => {\n const actionsRegistryService = DefaultActionsRegistryService.create({\n httpAuth,\n logger,\n auth,\n metadata,\n });\n\n httpRouter.use(actionsRegistryService.createRouter());\n\n return actionsRegistryService;\n },\n});\n"],"names":["createServiceFactory","actionsRegistryServiceRef","coreServices","DefaultActionsRegistryService"],"mappings":";;;;;;AA0BO,MAAM,gCAAgCA,qCAAqB,CAAA;AAAA,EAChE,OAAS,EAAAC,+BAAA;AAAA,EACT,IAAM,EAAA;AAAA,IACJ,UAAUC,6BAAa,CAAA,cAAA;AAAA,IACvB,YAAYA,6BAAa,CAAA,UAAA;AAAA,IACzB,UAAUA,6BAAa,CAAA,QAAA;AAAA,IACvB,QAAQA,6BAAa,CAAA,MAAA;AAAA,IACrB,MAAMA,6BAAa,CAAA;AAAA,GACrB;AAAA,EACA,OAAA,EAAS,CAAC,EAAE,QAAA,EAAU,YAAY,QAAU,EAAA,MAAA,EAAQ,MAAW,KAAA;AAC7D,IAAM,MAAA,sBAAA,GAAyBC,4DAA8B,MAAO,CAAA;AAAA,MAClE,QAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAW,UAAA,CAAA,GAAA,CAAI,sBAAuB,CAAA,YAAA,EAAc,CAAA;AAEpD,IAAO,OAAA,sBAAA;AAAA;AAEX,CAAC;;;;"}
1
+ {"version":3,"file":"actionsRegistryServiceFactory.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { DefaultActionsRegistryService } from './DefaultActionsRegistryService';\nimport { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const actionsRegistryServiceFactory = createServiceFactory({\n service: actionsRegistryServiceRef,\n deps: {\n metadata: coreServices.pluginMetadata,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n logger: coreServices.logger,\n auth: coreServices.auth,\n },\n factory: ({ metadata, httpRouter, httpAuth, logger, auth }) => {\n const actionsRegistryService = DefaultActionsRegistryService.create({\n httpAuth,\n logger,\n auth,\n metadata,\n });\n\n httpRouter.use(actionsRegistryService.createRouter());\n\n return actionsRegistryService;\n },\n});\n"],"names":["createServiceFactory","actionsRegistryServiceRef","coreServices","DefaultActionsRegistryService"],"mappings":";;;;;;AA0BO,MAAM,gCAAgCA,qCAAA,CAAqB;AAAA,EAChE,OAAA,EAASC,+BAAA;AAAA,EACT,IAAA,EAAM;AAAA,IACJ,UAAUC,6BAAA,CAAa,cAAA;AAAA,IACvB,YAAYA,6BAAA,CAAa,UAAA;AAAA,IACzB,UAAUA,6BAAA,CAAa,QAAA;AAAA,IACvB,QAAQA,6BAAA,CAAa,MAAA;AAAA,IACrB,MAAMA,6BAAA,CAAa;AAAA,GACrB;AAAA,EACA,OAAA,EAAS,CAAC,EAAE,QAAA,EAAU,YAAY,QAAA,EAAU,MAAA,EAAQ,MAAK,KAAM;AAC7D,IAAA,MAAM,sBAAA,GAAyBC,4DAA8B,MAAA,CAAO;AAAA,MAClE,QAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,UAAA,CAAW,GAAA,CAAI,sBAAA,CAAuB,YAAA,EAAc,CAAA;AAEpD,IAAA,OAAO,sBAAA;AAAA,EACT;AACF,CAAC;;;;"}
package/dist/cache.d.ts CHANGED
@@ -53,12 +53,14 @@ declare class CacheManager {
53
53
  * config section, specifically the `.cache` key.
54
54
  *
55
55
  * @param config - The loaded application configuration.
56
+ * @param options - Optional configuration for the CacheManager.
57
+ * @returns A new CacheManager instance.
56
58
  */
57
59
  static fromConfig(config: RootConfigService, options?: CacheManagerOptions): CacheManager;
58
60
  /**
59
61
  * Parse store-specific options from configuration.
60
62
  *
61
- * @param store - The cache store type ('redis', 'valkey', 'memcache', or 'memory')
63
+ * @param store - The cache store type ('redis', 'valkey', 'memcache', 'infinispan', or 'memory')
62
64
  * @param config - The configuration service
63
65
  * @param logger - Optional logger for warnings
64
66
  * @returns The parsed store options
@@ -80,6 +82,23 @@ declare class CacheManager {
80
82
  private createValkeyStoreFactory;
81
83
  private createMemcacheStoreFactory;
82
84
  private createMemoryStoreFactory;
85
+ private createInfinispanStoreFactory;
86
+ /**
87
+ * Creates an Infinispan client using dynamic import (production use).
88
+ * @returns Promise that resolves to an Infinispan client
89
+ */
90
+ private createInfinispanClientAsync;
91
+ /**
92
+ * Creates an Infinispan client using synchronous import (testing purposes).
93
+ * @returns Promise that resolves to an Infinispan client
94
+ */
95
+ private createInfinispanClientSync;
96
+ /**
97
+ * Creates an Infinispan client based on the provided configuration.
98
+ * @param useSync - Whether to use synchronous import (for testing) or dynamic import
99
+ * @returns Promise that resolves to an Infinispan client
100
+ */
101
+ private createInfinispanClient;
83
102
  }
84
103
 
85
104
  export { CacheManager, type CacheManagerOptions, cacheServiceFactory };
@@ -1,5 +1,5 @@
1
1
  import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
2
- import { DatabaseService, RootLoggerService, RootLifecycleService, RootConfigService, LoggerService, LifecycleService } from '@backstage/backend-plugin-api';
2
+ import { RootConfigService, DatabaseService, RootLoggerService, RootLifecycleService, LoggerService, LifecycleService } from '@backstage/backend-plugin-api';
3
3
 
4
4
  /**
5
5
  * Database access and management via `knex`.
@@ -1,5 +1,5 @@
1
1
  import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
2
- import { LoggerService, DiscoveryService, RootConfigService } from '@backstage/backend-plugin-api';
2
+ import { DiscoveryService, RootConfigService, LoggerService } from '@backstage/backend-plugin-api';
3
3
 
4
4
  /**
5
5
  * Service discovery for inter-plugin communication.
@@ -1 +1 @@
1
- {"version":3,"file":"discoveryFeatureLoader.cjs.js","sources":["../src/discoveryFeatureLoader.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendFeatureLoader,\n} from '@backstage/backend-plugin-api';\nimport { PackageDiscoveryService } from './PackageDiscoveryService';\n\n/**\n * A loader that discovers backend features from the current package.json and its dependencies.\n *\n * @public\n *\n * @example\n * Using the `discoveryFeatureLoader` loader in a backend instance:\n * ```ts\n * //...\n * import { createBackend } from '@backstage/backend-defaults';\n * import { discoveryFeatureLoader } from '@backstage/backend-defaults';\n *\n * const backend = createBackend();\n * backend.add(discoveryFeatureLoader);\n * //...\n * backend.start();\n * ```\n */\nexport const discoveryFeatureLoader = createBackendFeatureLoader({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.rootLogger,\n },\n async loader({ config, logger }) {\n const service = new PackageDiscoveryService(config, logger);\n const { features } = await service.getBackendFeatures();\n return features;\n },\n});\n"],"names":["createBackendFeatureLoader","coreServices","PackageDiscoveryService"],"mappings":";;;;;AAwCO,MAAM,yBAAyBA,2CAA2B,CAAA;AAAA,EAC/D,IAAM,EAAA;AAAA,IACJ,QAAQC,6BAAa,CAAA,UAAA;AAAA,IACrB,QAAQA,6BAAa,CAAA;AAAA,GACvB;AAAA,EACA,MAAM,MAAA,CAAO,EAAE,MAAA,EAAQ,QAAU,EAAA;AAC/B,IAAA,MAAM,OAAU,GAAA,IAAIC,+CAAwB,CAAA,MAAA,EAAQ,MAAM,CAAA;AAC1D,IAAA,MAAM,EAAE,QAAA,EAAa,GAAA,MAAM,QAAQ,kBAAmB,EAAA;AACtD,IAAO,OAAA,QAAA;AAAA;AAEX,CAAC;;;;"}
1
+ {"version":3,"file":"discoveryFeatureLoader.cjs.js","sources":["../src/discoveryFeatureLoader.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendFeatureLoader,\n} from '@backstage/backend-plugin-api';\nimport { PackageDiscoveryService } from './PackageDiscoveryService';\n\n/**\n * A loader that discovers backend features from the current package.json and its dependencies.\n *\n * @public\n *\n * @example\n * Using the `discoveryFeatureLoader` loader in a backend instance:\n * ```ts\n * //...\n * import { createBackend } from '@backstage/backend-defaults';\n * import { discoveryFeatureLoader } from '@backstage/backend-defaults';\n *\n * const backend = createBackend();\n * backend.add(discoveryFeatureLoader);\n * //...\n * backend.start();\n * ```\n */\nexport const discoveryFeatureLoader = createBackendFeatureLoader({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.rootLogger,\n },\n async loader({ config, logger }) {\n const service = new PackageDiscoveryService(config, logger);\n const { features } = await service.getBackendFeatures();\n return features;\n },\n});\n"],"names":["createBackendFeatureLoader","coreServices","PackageDiscoveryService"],"mappings":";;;;;AAwCO,MAAM,yBAAyBA,2CAAA,CAA2B;AAAA,EAC/D,IAAA,EAAM;AAAA,IACJ,QAAQC,6BAAA,CAAa,UAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa;AAAA,GACvB;AAAA,EACA,MAAM,MAAA,CAAO,EAAE,MAAA,EAAQ,QAAO,EAAG;AAC/B,IAAA,MAAM,OAAA,GAAU,IAAIC,+CAAA,CAAwB,MAAA,EAAQ,MAAM,CAAA;AAC1D,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,QAAQ,kBAAA,EAAmB;AACtD,IAAA,OAAO,QAAA;AAAA,EACT;AACF,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultAuditorService.cjs.js","sources":["../../../src/entrypoints/auditor/DefaultAuditorService.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n AuditorService,\n AuditorServiceCreateEventOptions,\n AuditorServiceEvent,\n AuditorServiceEventSeverityLevel,\n AuthService,\n BackstageCredentials,\n HttpAuthService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { ForwardedError } from '@backstage/errors';\nimport type { JsonObject } from '@backstage/types';\nimport type { Request } from 'express';\n\n/** @public */\nexport type AuditorEventActorDetails = {\n actorId?: string;\n ip?: string;\n hostname?: string;\n userAgent?: string;\n};\n\n/** @public */\nexport type AuditorEventRequest = {\n url: string;\n method: string;\n};\n\n/** @public */\nexport type AuditorEventStatus =\n | { status: 'initiated' }\n | { status: 'succeeded' }\n | {\n status: 'failed';\n error: Error;\n };\n\n/**\n * Options for creating an auditor event.\n *\n * @public\n */\nexport type AuditorEventOptions<TMeta extends JsonObject> = {\n /**\n * Use kebab-case to name audit events (e.g., \"user-login\", \"file-download\").\n *\n * The `pluginId` already provides plugin/module context, so avoid redundant prefixes in the `eventId`.\n */\n eventId: string;\n\n severityLevel?: AuditorServiceEventSeverityLevel;\n\n /** (Optional) The associated HTTP request, if applicable. */\n request?: Request<any, any, any, any, any>;\n\n /** (Optional) Additional metadata relevant to the event, structured as a JSON object. */\n meta?: TMeta;\n} & AuditorEventStatus;\n\n/**\n * Common fields of an audit event.\n *\n * @public\n */\nexport type AuditorEvent = {\n plugin: string;\n eventId: string;\n severityLevel: AuditorServiceEventSeverityLevel;\n actor: AuditorEventActorDetails;\n meta?: JsonObject;\n request?: AuditorEventRequest;\n} & AuditorEventStatus;\n\n/**\n * Logging function used by the auditor.\n * @public\n */\nexport type AuditorLogFunction = (event: AuditorEvent) => void | Promise<void>;\n\n/**\n * A {@link @backstage/backend-plugin-api#AuditorService} implementation that logs events using a provided callback.\n *\n * @public\n *\n * @example\n * ```ts\n * export const auditorServiceFactory = createServiceFactory({\n * service: coreServices.auditor,\n * deps: {\n * logger: coreServices.logger,\n * auth: coreServices.auth,\n * httpAuth: coreServices.httpAuth,\n * plugin: coreServices.pluginMetadata,\n * },\n * factory({ logger, plugin, auth, httpAuth }) {\n * const auditLogger = logger.child({ isAuditEvent: true });\n * return DefaultAuditorService.create(\n * event => auditLogger.info(`${event.plugin}.${event.eventId}`, event),\n * { plugin, auth, httpAuth },\n * );\n * },\n * });\n * ```\n */\nexport class DefaultAuditorService implements AuditorService {\n private readonly logFn: AuditorLogFunction;\n private readonly auth: AuthService;\n private readonly httpAuth: HttpAuthService;\n private readonly plugin: PluginMetadataService;\n\n private constructor(\n logFn: AuditorLogFunction,\n deps: {\n auth: AuthService;\n httpAuth: HttpAuthService;\n plugin: PluginMetadataService;\n },\n ) {\n this.logFn = logFn;\n this.auth = deps.auth;\n this.httpAuth = deps.httpAuth;\n this.plugin = deps.plugin;\n }\n\n /**\n * Creates a {@link DefaultAuditorService} instance.\n */\n static create(\n logFn: AuditorLogFunction,\n deps: {\n auth: AuthService;\n httpAuth: HttpAuthService;\n plugin: PluginMetadataService;\n },\n ): DefaultAuditorService {\n return new DefaultAuditorService(logFn, deps);\n }\n\n private async log<TMeta extends JsonObject>(\n options: AuditorEventOptions<TMeta>,\n ): Promise<void> {\n const { eventId, severityLevel = 'low', request, meta, ...rest } = options;\n\n await this.logFn({\n plugin: this.plugin.getId(),\n eventId,\n severityLevel,\n actor: {\n actorId: await this.getActorId(request),\n ip: request?.ip,\n hostname: request?.hostname,\n userAgent: request?.get('user-agent'),\n },\n request: request\n ? {\n url: request?.originalUrl,\n method: request?.method,\n }\n : undefined,\n meta: Object.keys(meta ?? {}).length === 0 ? undefined : meta,\n ...rest,\n });\n }\n\n async createEvent(\n options: AuditorServiceCreateEventOptions,\n ): Promise<AuditorServiceEvent> {\n await this.log({ ...options, status: 'initiated' });\n\n return {\n success: async params => {\n await this.log({\n ...options,\n meta: { ...options.meta, ...params?.meta },\n status: 'succeeded',\n });\n },\n fail: async params => {\n await this.log({\n ...options,\n ...params,\n error: params.error,\n meta: { ...options.meta, ...params?.meta },\n status: 'failed',\n });\n },\n };\n }\n\n private async getActorId(\n request?: Request<any, any, any, any, any>,\n ): Promise<string | undefined> {\n let credentials: BackstageCredentials =\n await this.auth.getOwnServiceCredentials();\n\n if (request) {\n try {\n credentials = await this.httpAuth.credentials(request);\n } catch (error) {\n throw new ForwardedError('Could not resolve credentials', error);\n }\n }\n\n if (this.auth.isPrincipal(credentials, 'user')) {\n return credentials.principal.userEntityRef;\n }\n\n if (this.auth.isPrincipal(credentials, 'service')) {\n return credentials.principal.subject;\n }\n\n return undefined;\n }\n}\n"],"names":["ForwardedError"],"mappings":"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"}
1
+ {"version":3,"file":"DefaultAuditorService.cjs.js","sources":["../../../src/entrypoints/auditor/DefaultAuditorService.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n AuditorService,\n AuditorServiceCreateEventOptions,\n AuditorServiceEvent,\n AuditorServiceEventSeverityLevel,\n AuthService,\n BackstageCredentials,\n HttpAuthService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { ForwardedError } from '@backstage/errors';\nimport type { JsonObject } from '@backstage/types';\nimport type { Request } from 'express';\n\n/** @public */\nexport type AuditorEventActorDetails = {\n actorId?: string;\n ip?: string;\n hostname?: string;\n userAgent?: string;\n};\n\n/** @public */\nexport type AuditorEventRequest = {\n url: string;\n method: string;\n};\n\n/** @public */\nexport type AuditorEventStatus =\n | { status: 'initiated' }\n | { status: 'succeeded' }\n | {\n status: 'failed';\n error: Error;\n };\n\n/**\n * Options for creating an auditor event.\n *\n * @public\n */\nexport type AuditorEventOptions<TMeta extends JsonObject> = {\n /**\n * Use kebab-case to name audit events (e.g., \"user-login\", \"file-download\").\n *\n * The `pluginId` already provides plugin/module context, so avoid redundant prefixes in the `eventId`.\n */\n eventId: string;\n\n severityLevel?: AuditorServiceEventSeverityLevel;\n\n /** (Optional) The associated HTTP request, if applicable. */\n request?: Request<any, any, any, any, any>;\n\n /** (Optional) Additional metadata relevant to the event, structured as a JSON object. */\n meta?: TMeta;\n} & AuditorEventStatus;\n\n/**\n * Common fields of an audit event.\n *\n * @public\n */\nexport type AuditorEvent = {\n plugin: string;\n eventId: string;\n severityLevel: AuditorServiceEventSeverityLevel;\n actor: AuditorEventActorDetails;\n meta?: JsonObject;\n request?: AuditorEventRequest;\n} & AuditorEventStatus;\n\n/**\n * Logging function used by the auditor.\n * @public\n */\nexport type AuditorLogFunction = (event: AuditorEvent) => void | Promise<void>;\n\n/**\n * A {@link @backstage/backend-plugin-api#AuditorService} implementation that logs events using a provided callback.\n *\n * @public\n *\n * @example\n * ```ts\n * export const auditorServiceFactory = createServiceFactory({\n * service: coreServices.auditor,\n * deps: {\n * logger: coreServices.logger,\n * auth: coreServices.auth,\n * httpAuth: coreServices.httpAuth,\n * plugin: coreServices.pluginMetadata,\n * },\n * factory({ logger, plugin, auth, httpAuth }) {\n * const auditLogger = logger.child({ isAuditEvent: true });\n * return DefaultAuditorService.create(\n * event => auditLogger.info(`${event.plugin}.${event.eventId}`, event),\n * { plugin, auth, httpAuth },\n * );\n * },\n * });\n * ```\n */\nexport class DefaultAuditorService implements AuditorService {\n private readonly logFn: AuditorLogFunction;\n private readonly auth: AuthService;\n private readonly httpAuth: HttpAuthService;\n private readonly plugin: PluginMetadataService;\n\n private constructor(\n logFn: AuditorLogFunction,\n deps: {\n auth: AuthService;\n httpAuth: HttpAuthService;\n plugin: PluginMetadataService;\n },\n ) {\n this.logFn = logFn;\n this.auth = deps.auth;\n this.httpAuth = deps.httpAuth;\n this.plugin = deps.plugin;\n }\n\n /**\n * Creates a {@link DefaultAuditorService} instance.\n */\n static create(\n logFn: AuditorLogFunction,\n deps: {\n auth: AuthService;\n httpAuth: HttpAuthService;\n plugin: PluginMetadataService;\n },\n ): DefaultAuditorService {\n return new DefaultAuditorService(logFn, deps);\n }\n\n private async log<TMeta extends JsonObject>(\n options: AuditorEventOptions<TMeta>,\n ): Promise<void> {\n const { eventId, severityLevel = 'low', request, meta, ...rest } = options;\n\n await this.logFn({\n plugin: this.plugin.getId(),\n eventId,\n severityLevel,\n actor: {\n actorId: await this.getActorId(request),\n ip: request?.ip,\n hostname: request?.hostname,\n userAgent: request?.get('user-agent'),\n },\n request: request\n ? {\n url: request?.originalUrl,\n method: request?.method,\n }\n : undefined,\n meta: Object.keys(meta ?? {}).length === 0 ? undefined : meta,\n ...rest,\n });\n }\n\n async createEvent(\n options: AuditorServiceCreateEventOptions,\n ): Promise<AuditorServiceEvent> {\n await this.log({ ...options, status: 'initiated' });\n\n return {\n success: async params => {\n await this.log({\n ...options,\n meta: { ...options.meta, ...params?.meta },\n status: 'succeeded',\n });\n },\n fail: async params => {\n await this.log({\n ...options,\n ...params,\n error: params.error,\n meta: { ...options.meta, ...params?.meta },\n status: 'failed',\n });\n },\n };\n }\n\n private async getActorId(\n request?: Request<any, any, any, any, any>,\n ): Promise<string | undefined> {\n let credentials: BackstageCredentials =\n await this.auth.getOwnServiceCredentials();\n\n if (request) {\n try {\n credentials = await this.httpAuth.credentials(request);\n } catch (error) {\n throw new ForwardedError('Could not resolve credentials', error);\n }\n }\n\n if (this.auth.isPrincipal(credentials, 'user')) {\n return credentials.principal.userEntityRef;\n }\n\n if (this.auth.isPrincipal(credentials, 'service')) {\n return credentials.principal.subject;\n }\n\n return undefined;\n }\n}\n"],"names":["ForwardedError"],"mappings":"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"}