| 69 | * ``` |
| 70 | */ |
| 71 | export function service( |
| 72 | serviceInterface?: ServiceInterface, |
| 73 | metadata?: InjectionMetadata, |
| 74 | ) { |
| 75 | return inject( |
| 76 | '', |
| 77 | {decorator: '@service', ...metadata}, |
| 78 | (ctx, injection, session) => { |
| 79 | let serviceType = serviceInterface; |
| 80 | if (!serviceType) { |
| 81 | if (typeof injection.methodDescriptorOrParameterIndex === 'number') { |
| 82 | serviceType = MetadataInspector.getDesignTypeForMethod( |
| 83 | injection.target, |
| 84 | injection.member!, |
| 85 | )?.parameterTypes[injection.methodDescriptorOrParameterIndex]; |
| 86 | } else { |
| 87 | serviceType = MetadataInspector.getDesignTypeForProperty( |
| 88 | injection.target, |
| 89 | injection.member!, |
| 90 | ); |
| 91 | } |
| 92 | } |
| 93 | if (serviceType === undefined) { |
| 94 | const targetName = DecoratorFactory.getTargetName( |
| 95 | injection.target, |
| 96 | injection.member, |
| 97 | injection.methodDescriptorOrParameterIndex, |
| 98 | ); |
| 99 | const msg = |
| 100 | `No design-time type metadata found while inspecting ${targetName}. ` + |
| 101 | 'You can either use `@service(ServiceClass)` or ensure `emitDecoratorMetadata` is enabled in your TypeScript configuration. ' + |
| 102 | 'Run `tsc --showConfig` to print the final TypeScript configuration of your project.'; |
| 103 | throw new Error(msg); |
| 104 | } |
| 105 | |
| 106 | if (serviceType === Object || serviceType === Array) { |
| 107 | throw new Error( |
| 108 | 'Service class cannot be inferred from design type. Use @service(ServiceClass).', |
| 109 | ); |
| 110 | } |
| 111 | const view = new ContextView(ctx, filterByServiceInterface(serviceType)); |
| 112 | const result = view.resolve({ |
| 113 | optional: metadata?.optional, |
| 114 | asProxyWithInterceptors: metadata?.asProxyWithInterceptors, |
| 115 | session, |
| 116 | }); |
| 117 | |
| 118 | const serviceTypeName = |
| 119 | typeof serviceType === 'string' |
| 120 | ? serviceType |
| 121 | : typeof serviceType === 'symbol' |
| 122 | ? serviceType.toString() |
| 123 | : serviceType.name; |
| 124 | return transformValueOrPromise(result, values => { |
| 125 | if (values.length === 1) return values[0]; |
| 126 | if (values.length >= 1) { |
| 127 | throw new Error( |
| 128 | `More than one bindings found for ${serviceTypeName}`, |