@whook/gcp-functions 8.3.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 (45) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +187 -0
  3. package/dist/commands/testHTTPFunction.d.ts +12 -0
  4. package/dist/commands/testHTTPFunction.js +156 -0
  5. package/dist/commands/testHTTPFunction.js.map +1 -0
  6. package/dist/commands/testHTTPFunction.mjs +136 -0
  7. package/dist/commands/testHTTPFunction.mjs.map +1 -0
  8. package/dist/index.d.ts +18 -0
  9. package/dist/index.js +299 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index.mjs +265 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/dist/libs/utils.d.ts +5 -0
  14. package/dist/libs/utils.js +39 -0
  15. package/dist/libs/utils.js.map +1 -0
  16. package/dist/libs/utils.mjs +27 -0
  17. package/dist/libs/utils.mjs.map +1 -0
  18. package/dist/services/_autoload.d.ts +17 -0
  19. package/dist/services/_autoload.js +121 -0
  20. package/dist/services/_autoload.js.map +1 -0
  21. package/dist/services/_autoload.mjs +107 -0
  22. package/dist/services/_autoload.mjs.map +1 -0
  23. package/dist/services/log.d.ts +2 -0
  24. package/dist/services/log.js +14 -0
  25. package/dist/services/log.js.map +1 -0
  26. package/dist/services/log.mjs +4 -0
  27. package/dist/services/log.mjs.map +1 -0
  28. package/dist/services/log.test.d.ts +1 -0
  29. package/dist/services/log.test.js +12 -0
  30. package/dist/services/log.test.js.map +1 -0
  31. package/dist/services/log.test.mjs +7 -0
  32. package/dist/services/log.test.mjs.map +1 -0
  33. package/dist/wrappers/googleHTTPFunction.d.ts +22 -0
  34. package/dist/wrappers/googleHTTPFunction.js +310 -0
  35. package/dist/wrappers/googleHTTPFunction.js.map +1 -0
  36. package/dist/wrappers/googleHTTPFunction.mjs +289 -0
  37. package/dist/wrappers/googleHTTPFunction.mjs.map +1 -0
  38. package/package.json +215 -0
  39. package/src/commands/testHTTPFunction.ts +181 -0
  40. package/src/index.ts +443 -0
  41. package/src/libs/utils.ts +43 -0
  42. package/src/services/_autoload.ts +161 -0
  43. package/src/services/log.test.ts +7 -0
  44. package/src/services/log.ts +4 -0
  45. package/src/wrappers/googleHTTPFunction.ts +468 -0
package/src/index.ts ADDED
@@ -0,0 +1,443 @@
1
+ /* eslint global-require:0 */
2
+ import fs from 'fs';
3
+ import util from 'util';
4
+ import path from 'path';
5
+ import mkdirp from 'mkdirp';
6
+ import cpr from 'cpr';
7
+ import YError from 'yerror';
8
+ import Knifecycle, {
9
+ SPECIAL_PROPS,
10
+ constant,
11
+ initInitializerBuilder,
12
+ } from 'knifecycle';
13
+ import { DEFAULT_BUILD_OPTIONS, initCompiler } from '@whook/whook';
14
+ import initBuildAutoloader from './services/_autoload';
15
+ import {
16
+ dereferenceOpenAPIOperations,
17
+ getOpenAPIOperations,
18
+ } from '@whook/http-router';
19
+ import type { Autoloader, Dependencies, BuildInitializer } from 'knifecycle';
20
+ import type {
21
+ WhookOperation,
22
+ WhookCompilerOptions,
23
+ WhookCompilerService,
24
+ } from '@whook/whook';
25
+ import type { OpenAPIV3 } from 'openapi-types';
26
+ import type { LogService } from 'common-services';
27
+ import type { CprOptions } from 'cpr';
28
+ import type { BuildOptions } from 'knifecycle/dist/build';
29
+
30
+ export const DEFAULT_BUILD_PARALLELISM = 10;
31
+
32
+ export type WhookBuildConfig = {
33
+ BUILD_OPTIONS?: BuildOptions;
34
+ BUILD_PARALLELISM?: number;
35
+ };
36
+ export type WhookAPIOperationGCPFunctionConfig = {
37
+ type?: 'http';
38
+ sourceOperationId?: string;
39
+ staticFiles?: string[];
40
+ compilerOptions?: WhookCompilerOptions;
41
+ suffix?: string;
42
+ };
43
+
44
+ const readFileAsync = util.promisify(fs.readFile) as (
45
+ path: string,
46
+ encoding: string,
47
+ ) => Promise<string>;
48
+ const writeFileAsync = util.promisify(fs.writeFile) as (
49
+ path: string,
50
+ content: string,
51
+ encoding: string,
52
+ ) => Promise<void>;
53
+ const cprAsync = util.promisify(cpr) as (
54
+ source: string,
55
+ destination: string,
56
+ options: CprOptions,
57
+ ) => Promise<string[]>;
58
+
59
+ const BUILD_DEFINITIONS: Record<
60
+ WhookAPIOperationGCPFunctionConfig['type'],
61
+ {
62
+ type: string;
63
+ wrapper: { name: string; path: string };
64
+ suffix?: string;
65
+ }
66
+ > = {
67
+ http: {
68
+ type: 'HTTP',
69
+ wrapper: {
70
+ name: 'wrapHandlerForGoogleHTTPFunction',
71
+ path: path.join(__dirname, 'wrappers', 'googleHTTPFunction'),
72
+ },
73
+ suffix: 'Wrapped',
74
+ },
75
+ };
76
+
77
+ export async function prepareBuildEnvironment<
78
+ T extends Knifecycle<Dependencies>,
79
+ >($: T = new Knifecycle() as T): Promise<T> {
80
+ $.register(
81
+ constant('INITIALIZER_PATH_MAP', {
82
+ ENV: '@whook/whook/dist/services/ProxyedENV',
83
+ log: __dirname + '/services/log',
84
+ time: 'common-services/dist/time',
85
+ delay: 'common-services/dist/delay',
86
+ }),
87
+ );
88
+ $.register(initInitializerBuilder);
89
+ $.register(initBuildAutoloader);
90
+ $.register(initCompiler);
91
+ $.register(constant('PORT', 1337));
92
+ $.register(constant('HOST', 'localhost'));
93
+
94
+ return $;
95
+ }
96
+
97
+ export async function runBuild(
98
+ aPrepareBuildEnvironment: typeof prepareBuildEnvironment,
99
+ ): Promise<void> {
100
+ try {
101
+ const handlerName = process.argv[2];
102
+ const $ = await aPrepareBuildEnvironment();
103
+ const {
104
+ NODE_ENV,
105
+ BUILD_PARALLELISM,
106
+ BUILD_OPTIONS,
107
+ PROJECT_DIR,
108
+ compiler,
109
+ log,
110
+ $autoload,
111
+ API,
112
+ buildInitializer,
113
+ }: WhookBuildConfig & {
114
+ NODE_ENV: string;
115
+ PROJECT_DIR: string;
116
+ compiler: WhookCompilerService;
117
+ log: LogService;
118
+ $autoload: Autoloader;
119
+ API: OpenAPIV3.Document;
120
+ buildInitializer: BuildInitializer;
121
+ } = await $.run([
122
+ 'NODE_ENV',
123
+ '?BUILD_PARALLELISM',
124
+ '?BUILD_OPTIONS',
125
+ 'PROJECT_DIR',
126
+ 'process',
127
+ 'compiler',
128
+ 'log',
129
+ '$autoload',
130
+ 'API',
131
+ 'buildInitializer',
132
+ ]);
133
+
134
+ log('info', 'Environment initialized 🚀🌕');
135
+
136
+ const operations = (
137
+ await dereferenceOpenAPIOperations(
138
+ API,
139
+ getOpenAPIOperations<WhookAPIOperationGCPFunctionConfig>(API),
140
+ )
141
+ ).filter((operation) => {
142
+ if (handlerName) {
143
+ const sourceOperationId =
144
+ operation['x-whook'] && operation['x-whook'].sourceOperationId;
145
+
146
+ return (
147
+ handlerName === operation.operationId ||
148
+ handlerName === sourceOperationId
149
+ );
150
+ }
151
+ return true;
152
+ });
153
+
154
+ log('warning', `${operations.length} operations to process.`);
155
+ await processOperations(
156
+ {
157
+ NODE_ENV,
158
+ BUILD_OPTIONS: BUILD_OPTIONS || DEFAULT_BUILD_OPTIONS,
159
+ BUILD_PARALLELISM: BUILD_PARALLELISM || DEFAULT_BUILD_PARALLELISM,
160
+ PROJECT_DIR,
161
+ compiler,
162
+ log,
163
+ $autoload,
164
+ buildInitializer,
165
+ },
166
+ operations,
167
+ );
168
+ await $.destroy();
169
+ } catch (err) {
170
+ // eslint-disable-next-line
171
+ console.error(
172
+ '💀 - Cannot launch the build:',
173
+ err.stack,
174
+ JSON.stringify(err.params, null, 2),
175
+ );
176
+ process.exit(1);
177
+ }
178
+ }
179
+
180
+ async function processOperations(
181
+ {
182
+ NODE_ENV,
183
+ BUILD_PARALLELISM,
184
+ BUILD_OPTIONS,
185
+ PROJECT_DIR,
186
+ compiler,
187
+ log,
188
+ $autoload,
189
+ buildInitializer,
190
+ }: {
191
+ NODE_ENV: string;
192
+ BUILD_PARALLELISM: number;
193
+ BUILD_OPTIONS: BuildOptions;
194
+ PROJECT_DIR: string;
195
+ compiler: WhookCompilerService;
196
+ log: LogService;
197
+ $autoload: Autoloader;
198
+ buildInitializer: BuildInitializer;
199
+ },
200
+ operations: WhookOperation<WhookAPIOperationGCPFunctionConfig>[],
201
+ ): Promise<void> {
202
+ const operationsLeft = operations.slice(BUILD_PARALLELISM);
203
+
204
+ await Promise.all(
205
+ operations.slice(0, BUILD_PARALLELISM).map((operation) =>
206
+ buildAnyLambda(
207
+ {
208
+ NODE_ENV,
209
+ PROJECT_DIR,
210
+ BUILD_OPTIONS,
211
+ compiler,
212
+ log,
213
+ $autoload,
214
+ buildInitializer,
215
+ },
216
+ operation,
217
+ ),
218
+ ),
219
+ );
220
+
221
+ if (operationsLeft.length) {
222
+ log('info', operationsLeft.length, ' operations left.');
223
+ return processOperations(
224
+ {
225
+ NODE_ENV,
226
+ BUILD_PARALLELISM,
227
+ BUILD_OPTIONS,
228
+ PROJECT_DIR,
229
+ compiler,
230
+ log,
231
+ $autoload,
232
+ buildInitializer,
233
+ },
234
+ operationsLeft,
235
+ );
236
+ }
237
+ log('info', 'No more operations.');
238
+ }
239
+
240
+ async function buildAnyLambda(
241
+ {
242
+ NODE_ENV,
243
+ PROJECT_DIR,
244
+ BUILD_OPTIONS,
245
+ compiler,
246
+ log,
247
+ $autoload,
248
+ buildInitializer,
249
+ }: {
250
+ NODE_ENV: string;
251
+ PROJECT_DIR: string;
252
+ BUILD_OPTIONS: BuildOptions;
253
+ compiler: WhookCompilerService;
254
+ log: LogService;
255
+ $autoload: Autoloader;
256
+ buildInitializer: BuildInitializer;
257
+ },
258
+ operation: WhookOperation<WhookAPIOperationGCPFunctionConfig>,
259
+ ): Promise<void> {
260
+ const { operationId } = operation;
261
+
262
+ try {
263
+ const whookConfig: WhookAPIOperationGCPFunctionConfig =
264
+ operation['x-whook'] || {};
265
+ const operationType = whookConfig.type || 'http';
266
+ const sourceOperationId = whookConfig.sourceOperationId;
267
+ const entryPoint = operationId;
268
+ const finalEntryPoint =
269
+ (sourceOperationId ? sourceOperationId : operationId) +
270
+ ((operation['x-whook'] || {}).suffix || '');
271
+ log('warning', `Building ${operationType} "${finalEntryPoint}"...`);
272
+ const buildDefinition = BUILD_DEFINITIONS[operationType];
273
+ // eslint-disable-next-line
274
+ const applyWrapper = require(buildDefinition.wrapper.path).default;
275
+ const rootNode = await $autoload(
276
+ entryPoint + (buildDefinition.suffix || ''),
277
+ );
278
+ const lambdaPath = path.join(
279
+ PROJECT_DIR,
280
+ 'builds',
281
+ NODE_ENV,
282
+ finalEntryPoint,
283
+ );
284
+ const finalHandlerInitializer = applyWrapper(rootNode.initializer);
285
+
286
+ const initializerContent = await buildInitializer(
287
+ finalHandlerInitializer[SPECIAL_PROPS.INJECT].map((name) =>
288
+ name === 'OPERATION_API'
289
+ ? `OPERATION_API>OPERATION_API_${finalEntryPoint}`
290
+ : name,
291
+ ),
292
+ BUILD_OPTIONS,
293
+ );
294
+ const indexContent = await buildLambdaIndex(
295
+ rootNode,
296
+ {
297
+ name: buildDefinition.wrapper.name,
298
+ path: buildDefinition.wrapper.path,
299
+ },
300
+ BUILD_OPTIONS,
301
+ );
302
+
303
+ await mkdirp(lambdaPath);
304
+ await Promise.all([
305
+ copyStaticFiles(
306
+ { PROJECT_DIR, log },
307
+ lambdaPath,
308
+ whookConfig.staticFiles || [],
309
+ ),
310
+ ensureFileAsync(
311
+ { log },
312
+ path.join(lambdaPath, 'initialize.js'),
313
+ initializerContent,
314
+ ),
315
+ ensureFileAsync({ log }, path.join(lambdaPath, 'main.js'), indexContent),
316
+ ]);
317
+ await buildFinalLambda({ compiler, log }, lambdaPath, whookConfig);
318
+ } catch (err) {
319
+ log('error', `Error building "${operationId}"...`);
320
+ log('stack', err.stack);
321
+ log('debug', JSON.stringify(err.params, null, 2));
322
+ throw YError.wrap(err, 'E_LAMBDA_BUILD', operationId);
323
+ }
324
+ }
325
+
326
+ async function buildLambdaIndex(
327
+ rootNode: { path: string },
328
+ buildWrapper: { name: string; path: string },
329
+ options: BuildOptions,
330
+ ): Promise<string> {
331
+ return `${
332
+ options.modules === 'commonjs'
333
+ ? `const pickModule = (m) => { return m && m.default || m; }
334
+ const initHandler = pickModule(require('${rootNode.path}'));
335
+ const ${buildWrapper.name} = pickModule(require('${buildWrapper.path}'));
336
+ const { initialize } = require('./initialize');`
337
+ : `import initHandler from '${rootNode.path}';
338
+ import ${buildWrapper.name} from '${buildWrapper.path}';
339
+ import { initialize } from './initialize';`
340
+ }
341
+
342
+ const handlerInitializer = ${buildWrapper.name}(
343
+ initHandler
344
+ );
345
+
346
+ const handlerPromise = initialize()
347
+ .then(handlerInitializer);
348
+
349
+ ${
350
+ options.modules === 'commonjs'
351
+ ? 'module.exports = {}; module.exports.default = '
352
+ : 'export default '
353
+ }function handler (req, res) {
354
+ return handlerPromise
355
+ .then(handler => handler(req, res));
356
+ };
357
+ `;
358
+ }
359
+
360
+ async function buildFinalLambda(
361
+ { compiler, log }: { compiler: WhookCompilerService; log: LogService },
362
+ lambdaPath: string,
363
+ whookConfig: WhookAPIOperationGCPFunctionConfig,
364
+ ): Promise<void> {
365
+ const entryPoint = `${lambdaPath}/main.js`;
366
+ const { contents, mappings } = await compiler(
367
+ entryPoint,
368
+ whookConfig.compilerOptions,
369
+ );
370
+
371
+ await Promise.all([
372
+ ensureFileAsync({ log }, `${lambdaPath}/index.js`, contents, 'utf-8'),
373
+ mappings
374
+ ? ensureFileAsync(
375
+ { log },
376
+ `${lambdaPath}/index.js.map`,
377
+ mappings,
378
+ 'utf-8',
379
+ )
380
+ : Promise.resolve(),
381
+ ]);
382
+ }
383
+
384
+ async function copyStaticFiles(
385
+ { PROJECT_DIR, log }: { PROJECT_DIR: string; log: LogService },
386
+ lambdaPath: string,
387
+ staticFiles: string[] = [],
388
+ ): Promise<void> {
389
+ await Promise.all(
390
+ staticFiles.map(
391
+ async (staticFile) =>
392
+ await copyFiles(
393
+ { log },
394
+ path.join(PROJECT_DIR, 'node_modules', staticFile),
395
+ path.join(lambdaPath, 'node_modules', staticFile),
396
+ ),
397
+ ),
398
+ );
399
+ }
400
+
401
+ async function copyFiles(
402
+ { log }: { log: LogService },
403
+ source: string,
404
+ destination: string,
405
+ ): Promise<void> {
406
+ let theError;
407
+ try {
408
+ await mkdirp(destination);
409
+ const data = await readFileAsync(source, 'utf-8');
410
+ await ensureFileAsync({ log }, destination, data, 'utf-8');
411
+ } catch (err) {
412
+ theError = err;
413
+ }
414
+ if (theError) {
415
+ if ('EISDIR' !== theError.code) {
416
+ throw theError;
417
+ }
418
+ await cprAsync(source, destination, {
419
+ overwrite: true,
420
+ });
421
+ }
422
+ }
423
+
424
+ async function ensureFileAsync(
425
+ { log }: { log: LogService },
426
+ path: string,
427
+ content: string,
428
+ encoding = 'utf-8',
429
+ ): Promise<void> {
430
+ try {
431
+ const oldContent = await readFileAsync(path, encoding);
432
+
433
+ if (oldContent === content) {
434
+ log('debug', `Ignore unchanged file: "${path}".`);
435
+ return;
436
+ }
437
+ } catch (err) {
438
+ log('debug', `Write new file: "${path}".`);
439
+ return await writeFileAsync(path, content, encoding);
440
+ }
441
+ log('debug', `Write changed file: "${path}".`);
442
+ return await writeFileAsync(path, content, encoding);
443
+ }
@@ -0,0 +1,43 @@
1
+ import YError from 'yerror';
2
+ import path from 'path';
3
+ import type { LogService } from 'common-services';
4
+
5
+ export async function loadLambda(
6
+ {
7
+ PROJECT_DIR,
8
+ log,
9
+ }: {
10
+ PROJECT_DIR: string;
11
+ log: LogService;
12
+ },
13
+ target: string,
14
+ operationId: string,
15
+ type: string,
16
+ ): Promise<any> {
17
+ const modulePath = path.join(
18
+ PROJECT_DIR,
19
+ 'builds',
20
+ target,
21
+ operationId,
22
+ type,
23
+ );
24
+
25
+ log('debug', `⛏️ - Loading lambda module at path "${modulePath}".`);
26
+
27
+ try {
28
+ // eslint-disable-next-line
29
+ const module = require(modulePath);
30
+
31
+ if (!module) {
32
+ throw new YError('E_MODULE_NOT_FOUND', module);
33
+ }
34
+
35
+ if (!module.default) {
36
+ throw new YError('E_LAMBDA_NOT_FOUND', module, Object.keys(module));
37
+ }
38
+
39
+ return module.default;
40
+ } catch (err) {
41
+ throw YError.wrap(err, 'E_LAMBDA_LOAD');
42
+ }
43
+ }
@@ -0,0 +1,161 @@
1
+ import { initAutoload, noop, cleanupOpenAPI } from '@whook/whook';
2
+ import Knifecycle, {
3
+ SPECIAL_PROPS,
4
+ wrapInitializer,
5
+ constant,
6
+ alsoInject,
7
+ } from 'knifecycle';
8
+ import YError from 'yerror';
9
+ import {
10
+ dereferenceOpenAPIOperations,
11
+ getOpenAPIOperations,
12
+ } from '@whook/http-router';
13
+ import type {
14
+ Injector,
15
+ Autoloader,
16
+ Initializer,
17
+ Dependencies,
18
+ Service,
19
+ } from 'knifecycle';
20
+ import type { WhookBuildConstantsService } from '@whook/whook';
21
+ import type { WhookRawOperation } from '@whook/http-router';
22
+ import type { LogService } from 'common-services';
23
+ import type { OpenAPIV3 } from 'openapi-types';
24
+ import type { WhookAPIOperationGCPFunctionConfig } from '..';
25
+
26
+ /**
27
+ * Wrap the _autoload service in order to build AWS
28
+ * Lambda compatible code.
29
+ * @param {Object} services
30
+ * The services ENV depends on
31
+ * @param {Object} services.NODE_ENV
32
+ * The injected NODE_ENV value to add it to the build env
33
+ * @param {Object} [services.PROXYED_ENV_VARS={}]
34
+ * A list of environment variable names to proxy
35
+ * @param {Object} [services.log=noop]
36
+ * An optional logging service
37
+ * @return {Promise<Object>}
38
+ * A promise of an object containing the reshaped env vars.
39
+ */
40
+ export default alsoInject(
41
+ ['?BUILD_CONSTANTS', '$instance', '$injector', '?log'],
42
+ wrapInitializer(
43
+ async (
44
+ {
45
+ BUILD_CONSTANTS = {},
46
+ $injector,
47
+ $instance,
48
+ log = noop,
49
+ }: {
50
+ BUILD_CONSTANTS?: WhookBuildConstantsService;
51
+ $injector: Injector<Service>;
52
+ $instance: Knifecycle<Dependencies>;
53
+ log: LogService;
54
+ },
55
+ $autoload: Autoloader,
56
+ ): Promise<
57
+ (serviceName: string) => Promise<{
58
+ initializer: Initializer<Dependencies, Service>;
59
+ path: string;
60
+ }>
61
+ > => {
62
+ let API: OpenAPIV3.Document;
63
+ let OPERATION_APIS: WhookRawOperation<WhookAPIOperationGCPFunctionConfig>[];
64
+ const getAPIOperation = (() => {
65
+ return async (serviceName) => {
66
+ // eslint-disable-next-line
67
+ API = API || (await $injector(['API'])).API;
68
+ // eslint-disable-next-line
69
+ OPERATION_APIS =
70
+ OPERATION_APIS ||
71
+ getOpenAPIOperations<WhookAPIOperationGCPFunctionConfig>(API);
72
+
73
+ const OPERATION = OPERATION_APIS.find(
74
+ (operation) =>
75
+ serviceName ===
76
+ (((operation['x-whook'] || {}).sourceOperationId &&
77
+ 'OPERATION_API_' +
78
+ (operation['x-whook'] || {}).sourceOperationId) ||
79
+ 'OPERATION_API_' + operation.operationId) +
80
+ ((operation['x-whook'] || {}).suffix || ''),
81
+ );
82
+
83
+ if (!OPERATION) {
84
+ log('error', '💥 - Unable to find a lambda operation definition!');
85
+ throw new YError('E_OPERATION_NOT_FOUND', serviceName);
86
+ }
87
+
88
+ // eslint-disable-next-line
89
+ const OPERATION_API = cleanupOpenAPI({
90
+ ...API,
91
+ paths: {
92
+ [OPERATION.path]: {
93
+ [OPERATION.method]: API.paths[OPERATION.path][OPERATION.method],
94
+ },
95
+ },
96
+ });
97
+
98
+ return {
99
+ ...OPERATION_API,
100
+ paths: {
101
+ [OPERATION.path]: {
102
+ [OPERATION.method]: (
103
+ await dereferenceOpenAPIOperations(OPERATION_API, [
104
+ {
105
+ path: OPERATION.path,
106
+ method: OPERATION.method,
107
+ ...OPERATION_API.paths[OPERATION.path][OPERATION.method],
108
+ parameters: OPERATION.parameters,
109
+ },
110
+ ])
111
+ )[0],
112
+ },
113
+ },
114
+ };
115
+ };
116
+ })();
117
+
118
+ log('debug', '🤖 - Initializing the `$autoload` build wrapper.');
119
+
120
+ return async (serviceName) => {
121
+ try {
122
+ // TODO: add initializer map to knifecycle public API
123
+ const initializer = ($instance as any)._initializers.get(serviceName);
124
+
125
+ if (initializer && initializer[SPECIAL_PROPS.TYPE] === 'constant') {
126
+ log(
127
+ 'debug',
128
+ `🤖 - Reusing a constant initializer directly from the Knifecycle instance: "${serviceName}".`,
129
+ );
130
+ return {
131
+ initializer,
132
+ path: `instance://${serviceName}`,
133
+ };
134
+ }
135
+
136
+ if (serviceName.startsWith('OPERATION_API_')) {
137
+ const OPERATION_API = await getAPIOperation(serviceName);
138
+
139
+ return {
140
+ initializer: constant(serviceName, OPERATION_API),
141
+ path: `api://${serviceName}`,
142
+ };
143
+ }
144
+
145
+ if (BUILD_CONSTANTS[serviceName]) {
146
+ return {
147
+ initializer: constant(serviceName, BUILD_CONSTANTS[serviceName]),
148
+ path: `constant://${serviceName}`,
149
+ };
150
+ }
151
+
152
+ return $autoload(serviceName);
153
+ } catch (err) {
154
+ log('error', `Build error while loading "${serviceName}".`);
155
+ log('stack', err.stack);
156
+ }
157
+ };
158
+ },
159
+ initAutoload,
160
+ ),
161
+ );
@@ -0,0 +1,7 @@
1
+ import initLogService from './log';
2
+
3
+ describe('initLogService', () => {
4
+ it('should work', async () => {
5
+ await initLogService();
6
+ });
7
+ });
@@ -0,0 +1,4 @@
1
+ import { service } from 'knifecycle';
2
+
3
+ // eslint-disable-next-line
4
+ export default service(async () => console.log.bind(console), 'log');