@babelqueue/bullmq 0.1.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.
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # @babelqueue/bullmq
2
+
3
+ [![npm](https://img.shields.io/npm/v/@babelqueue/bullmq.svg)](https://www.npmjs.com/package/@babelqueue/bullmq)
4
+
5
+ > **Polyglot Queues, Simplified.** A [BullMQ](https://docs.bullmq.io) adapter for
6
+ > BabelQueue: your BullMQ jobs carry the canonical BabelQueue envelope and are
7
+ > routed by URN — the same contract the PHP/Laravel, Python, Go, Java and .NET SDKs
8
+ > speak.
9
+
10
+ ```bash
11
+ npm install @babelqueue/bullmq bullmq
12
+ ```
13
+
14
+ ## Produce
15
+
16
+ ```ts
17
+ import { Queue } from "bullmq";
18
+ import { publish } from "@babelqueue/bullmq";
19
+
20
+ const queue = new Queue("orders", { connection: { host: "localhost", port: 6379 } });
21
+ await publish(queue, "urn:babel:orders:created", { order_id: 1042 });
22
+ // job name = the URN; job data = the canonical { job, trace_id, data, meta, attempts } envelope
23
+ ```
24
+
25
+ ## Consume
26
+
27
+ ```ts
28
+ import { Worker } from "bullmq";
29
+ import { processor } from "@babelqueue/bullmq";
30
+
31
+ new Worker(
32
+ "orders",
33
+ processor({
34
+ "urn:babel:orders:created": async (env) => {
35
+ console.log(env.data.order_id, env.trace_id);
36
+ },
37
+ }),
38
+ { connection: { host: "localhost", port: 6379 } },
39
+ );
40
+ ```
41
+
42
+ `processor` validates each envelope (`EnvelopeCodec.accepts`) and routes by URN; a
43
+ non-conformant envelope throws (BullMQ retries/fails per its options), and an
44
+ unmapped URN throws unless you pass `onUnknownUrn`.
45
+
46
+ > BullMQ stores jobs in its own Redis structures, so this gives the canonical
47
+ > envelope **shape + URN routing + trace propagation** to BullMQ-based Node
48
+ > services. For raw cross-language queues, other SDKs read/write plain broker
49
+ > queues directly.
50
+
51
+ ## License
52
+
53
+ [MIT](../../LICENSE) © Muhammet Şafak · [babelqueue.com](https://babelqueue.com)
package/dist/index.cjs ADDED
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ processor: () => processor,
24
+ publish: () => publish
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+ var import_core = require("@babelqueue/core");
28
+ async function publish(queue, urn, data, options = {}) {
29
+ const envelope = import_core.EnvelopeCodec.make(urn, data, {
30
+ queue: queue.name,
31
+ traceId: options.traceId
32
+ });
33
+ await queue.add(urn, envelope, options.jobsOptions);
34
+ return envelope.meta.id;
35
+ }
36
+ function processor(handlers, options = {}) {
37
+ return async (job) => {
38
+ const envelope = job.data;
39
+ if (!import_core.EnvelopeCodec.accepts(envelope)) {
40
+ throw new import_core.BabelQueueError(
41
+ `Rejected a non-conformant BabelQueue envelope on job ${job.id ?? "?"}.`
42
+ );
43
+ }
44
+ const urn = import_core.EnvelopeCodec.urn(envelope);
45
+ const handler = handlers[urn];
46
+ if (!handler) {
47
+ if (options.onUnknownUrn) {
48
+ return options.onUnknownUrn(envelope, job);
49
+ }
50
+ throw new import_core.UnknownUrnError(urn);
51
+ }
52
+ return handler(envelope, job);
53
+ };
54
+ }
55
+ // Annotate the CommonJS export names for ESM import in node:
56
+ 0 && (module.exports = {
57
+ processor,
58
+ publish
59
+ });
60
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * BullMQ adapter for BabelQueue.\n *\n * It makes your BullMQ jobs carry the canonical BabelQueue envelope and routes\n * them by URN, so a BullMQ-based Node service speaks the same contract (envelope\n * shape, URN identity, trace propagation) as the PHP/Laravel, Python, Go, Java and\n * .NET SDKs.\n *\n * import { Queue, Worker } from \"bullmq\";\n * import { publish, processor } from \"@babelqueue/bullmq\";\n *\n * const queue = new Queue(\"orders\", { connection });\n * await publish(queue, \"urn:babel:orders:created\", { order_id: 1042 });\n *\n * new Worker(\"orders\", processor({\n * \"urn:babel:orders:created\": async (env) => { ... },\n * }), { connection });\n */\n\nimport {\n BabelQueueError,\n EnvelopeCodec,\n UnknownUrnError,\n type Envelope,\n type IncomingEnvelope,\n} from \"@babelqueue/core\";\nimport type { Job, JobsOptions, Queue } from \"bullmq\";\n\n/** A URN handler. Receives the validated envelope and the raw BullMQ job. */\nexport type BabelHandler = (envelope: Envelope, job: Job) => unknown | Promise<unknown>;\n\n/** A map of URN → handler. */\nexport type BabelHandlers = Record<string, BabelHandler>;\n\n/** Options for {@link publish}. */\nexport interface PublishOptions {\n /** Reuse an existing trace id (trace continuation). */\n traceId?: string;\n /** BullMQ job options (delay, attempts, backoff, …). */\n jobsOptions?: JobsOptions;\n}\n\n/**\n * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the\n * job name is the URN, the job data is the envelope). Returns the message id\n * (`meta.id`).\n */\nexport async function publish(\n queue: Queue,\n urn: string,\n data: Record<string, unknown>,\n options: PublishOptions = {},\n): Promise<string> {\n const envelope = EnvelopeCodec.make(urn, data, {\n queue: queue.name,\n traceId: options.traceId,\n });\n await queue.add(urn, envelope, options.jobsOptions);\n return envelope.meta.id;\n}\n\n/** Options for {@link processor}. */\nexport interface ProcessorOptions {\n /** Called instead of throwing when a job's URN has no handler. */\n onUnknownUrn?: (envelope: IncomingEnvelope, job: Job) => unknown | Promise<unknown>;\n}\n\n/**\n * Build a BullMQ processor that decodes each job's envelope, validates it, and\n * routes it to the handler registered for its URN. A non-conformant envelope\n * throws (so BullMQ retries / fails the job per its options); an unmapped URN\n * throws unless `onUnknownUrn` is given.\n *\n * new Worker(\"orders\", processor(handlers), { connection });\n */\nexport function processor(\n handlers: BabelHandlers,\n options: ProcessorOptions = {},\n): (job: Job) => Promise<unknown> {\n return async (job: Job): Promise<unknown> => {\n const envelope = job.data as IncomingEnvelope;\n\n if (!EnvelopeCodec.accepts(envelope)) {\n throw new BabelQueueError(\n `Rejected a non-conformant BabelQueue envelope on job ${job.id ?? \"?\"}.`,\n );\n }\n\n const urn = EnvelopeCodec.urn(envelope);\n const handler = handlers[urn];\n if (!handler) {\n if (options.onUnknownUrn) {\n return options.onUnknownUrn(envelope, job);\n }\n throw new UnknownUrnError(urn);\n }\n\n return handler(envelope, job);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBA,kBAMO;AAsBP,eAAsB,QACpB,OACA,KACA,MACA,UAA0B,CAAC,GACV;AACjB,QAAM,WAAW,0BAAc,KAAK,KAAK,MAAM;AAAA,IAC7C,OAAO,MAAM;AAAA,IACb,SAAS,QAAQ;AAAA,EACnB,CAAC;AACD,QAAM,MAAM,IAAI,KAAK,UAAU,QAAQ,WAAW;AAClD,SAAO,SAAS,KAAK;AACvB;AAgBO,SAAS,UACd,UACA,UAA4B,CAAC,GACG;AAChC,SAAO,OAAO,QAA+B;AAC3C,UAAM,WAAW,IAAI;AAErB,QAAI,CAAC,0BAAc,QAAQ,QAAQ,GAAG;AACpC,YAAM,IAAI;AAAA,QACR,wDAAwD,IAAI,MAAM,GAAG;AAAA,MACvE;AAAA,IACF;AAEA,UAAM,MAAM,0BAAc,IAAI,QAAQ;AACtC,UAAM,UAAU,SAAS,GAAG;AAC5B,QAAI,CAAC,SAAS;AACZ,UAAI,QAAQ,cAAc;AACxB,eAAO,QAAQ,aAAa,UAAU,GAAG;AAAA,MAC3C;AACA,YAAM,IAAI,4BAAgB,GAAG;AAAA,IAC/B;AAEA,WAAO,QAAQ,UAAU,GAAG;AAAA,EAC9B;AACF;","names":[]}
@@ -0,0 +1,55 @@
1
+ import { Envelope, IncomingEnvelope } from '@babelqueue/core';
2
+ import { Job, JobsOptions, Queue } from 'bullmq';
3
+
4
+ /**
5
+ * BullMQ adapter for BabelQueue.
6
+ *
7
+ * It makes your BullMQ jobs carry the canonical BabelQueue envelope and routes
8
+ * them by URN, so a BullMQ-based Node service speaks the same contract (envelope
9
+ * shape, URN identity, trace propagation) as the PHP/Laravel, Python, Go, Java and
10
+ * .NET SDKs.
11
+ *
12
+ * import { Queue, Worker } from "bullmq";
13
+ * import { publish, processor } from "@babelqueue/bullmq";
14
+ *
15
+ * const queue = new Queue("orders", { connection });
16
+ * await publish(queue, "urn:babel:orders:created", { order_id: 1042 });
17
+ *
18
+ * new Worker("orders", processor({
19
+ * "urn:babel:orders:created": async (env) => { ... },
20
+ * }), { connection });
21
+ */
22
+
23
+ /** A URN handler. Receives the validated envelope and the raw BullMQ job. */
24
+ type BabelHandler = (envelope: Envelope, job: Job) => unknown | Promise<unknown>;
25
+ /** A map of URN → handler. */
26
+ type BabelHandlers = Record<string, BabelHandler>;
27
+ /** Options for {@link publish}. */
28
+ interface PublishOptions {
29
+ /** Reuse an existing trace id (trace continuation). */
30
+ traceId?: string;
31
+ /** BullMQ job options (delay, attempts, backoff, …). */
32
+ jobsOptions?: JobsOptions;
33
+ }
34
+ /**
35
+ * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the
36
+ * job name is the URN, the job data is the envelope). Returns the message id
37
+ * (`meta.id`).
38
+ */
39
+ declare function publish(queue: Queue, urn: string, data: Record<string, unknown>, options?: PublishOptions): Promise<string>;
40
+ /** Options for {@link processor}. */
41
+ interface ProcessorOptions {
42
+ /** Called instead of throwing when a job's URN has no handler. */
43
+ onUnknownUrn?: (envelope: IncomingEnvelope, job: Job) => unknown | Promise<unknown>;
44
+ }
45
+ /**
46
+ * Build a BullMQ processor that decodes each job's envelope, validates it, and
47
+ * routes it to the handler registered for its URN. A non-conformant envelope
48
+ * throws (so BullMQ retries / fails the job per its options); an unmapped URN
49
+ * throws unless `onUnknownUrn` is given.
50
+ *
51
+ * new Worker("orders", processor(handlers), { connection });
52
+ */
53
+ declare function processor(handlers: BabelHandlers, options?: ProcessorOptions): (job: Job) => Promise<unknown>;
54
+
55
+ export { type BabelHandler, type BabelHandlers, type ProcessorOptions, type PublishOptions, processor, publish };
@@ -0,0 +1,55 @@
1
+ import { Envelope, IncomingEnvelope } from '@babelqueue/core';
2
+ import { Job, JobsOptions, Queue } from 'bullmq';
3
+
4
+ /**
5
+ * BullMQ adapter for BabelQueue.
6
+ *
7
+ * It makes your BullMQ jobs carry the canonical BabelQueue envelope and routes
8
+ * them by URN, so a BullMQ-based Node service speaks the same contract (envelope
9
+ * shape, URN identity, trace propagation) as the PHP/Laravel, Python, Go, Java and
10
+ * .NET SDKs.
11
+ *
12
+ * import { Queue, Worker } from "bullmq";
13
+ * import { publish, processor } from "@babelqueue/bullmq";
14
+ *
15
+ * const queue = new Queue("orders", { connection });
16
+ * await publish(queue, "urn:babel:orders:created", { order_id: 1042 });
17
+ *
18
+ * new Worker("orders", processor({
19
+ * "urn:babel:orders:created": async (env) => { ... },
20
+ * }), { connection });
21
+ */
22
+
23
+ /** A URN handler. Receives the validated envelope and the raw BullMQ job. */
24
+ type BabelHandler = (envelope: Envelope, job: Job) => unknown | Promise<unknown>;
25
+ /** A map of URN → handler. */
26
+ type BabelHandlers = Record<string, BabelHandler>;
27
+ /** Options for {@link publish}. */
28
+ interface PublishOptions {
29
+ /** Reuse an existing trace id (trace continuation). */
30
+ traceId?: string;
31
+ /** BullMQ job options (delay, attempts, backoff, …). */
32
+ jobsOptions?: JobsOptions;
33
+ }
34
+ /**
35
+ * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the
36
+ * job name is the URN, the job data is the envelope). Returns the message id
37
+ * (`meta.id`).
38
+ */
39
+ declare function publish(queue: Queue, urn: string, data: Record<string, unknown>, options?: PublishOptions): Promise<string>;
40
+ /** Options for {@link processor}. */
41
+ interface ProcessorOptions {
42
+ /** Called instead of throwing when a job's URN has no handler. */
43
+ onUnknownUrn?: (envelope: IncomingEnvelope, job: Job) => unknown | Promise<unknown>;
44
+ }
45
+ /**
46
+ * Build a BullMQ processor that decodes each job's envelope, validates it, and
47
+ * routes it to the handler registered for its URN. A non-conformant envelope
48
+ * throws (so BullMQ retries / fails the job per its options); an unmapped URN
49
+ * throws unless `onUnknownUrn` is given.
50
+ *
51
+ * new Worker("orders", processor(handlers), { connection });
52
+ */
53
+ declare function processor(handlers: BabelHandlers, options?: ProcessorOptions): (job: Job) => Promise<unknown>;
54
+
55
+ export { type BabelHandler, type BabelHandlers, type ProcessorOptions, type PublishOptions, processor, publish };
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ // src/index.ts
2
+ import {
3
+ BabelQueueError,
4
+ EnvelopeCodec,
5
+ UnknownUrnError
6
+ } from "@babelqueue/core";
7
+ async function publish(queue, urn, data, options = {}) {
8
+ const envelope = EnvelopeCodec.make(urn, data, {
9
+ queue: queue.name,
10
+ traceId: options.traceId
11
+ });
12
+ await queue.add(urn, envelope, options.jobsOptions);
13
+ return envelope.meta.id;
14
+ }
15
+ function processor(handlers, options = {}) {
16
+ return async (job) => {
17
+ const envelope = job.data;
18
+ if (!EnvelopeCodec.accepts(envelope)) {
19
+ throw new BabelQueueError(
20
+ `Rejected a non-conformant BabelQueue envelope on job ${job.id ?? "?"}.`
21
+ );
22
+ }
23
+ const urn = EnvelopeCodec.urn(envelope);
24
+ const handler = handlers[urn];
25
+ if (!handler) {
26
+ if (options.onUnknownUrn) {
27
+ return options.onUnknownUrn(envelope, job);
28
+ }
29
+ throw new UnknownUrnError(urn);
30
+ }
31
+ return handler(envelope, job);
32
+ };
33
+ }
34
+ export {
35
+ processor,
36
+ publish
37
+ };
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * BullMQ adapter for BabelQueue.\n *\n * It makes your BullMQ jobs carry the canonical BabelQueue envelope and routes\n * them by URN, so a BullMQ-based Node service speaks the same contract (envelope\n * shape, URN identity, trace propagation) as the PHP/Laravel, Python, Go, Java and\n * .NET SDKs.\n *\n * import { Queue, Worker } from \"bullmq\";\n * import { publish, processor } from \"@babelqueue/bullmq\";\n *\n * const queue = new Queue(\"orders\", { connection });\n * await publish(queue, \"urn:babel:orders:created\", { order_id: 1042 });\n *\n * new Worker(\"orders\", processor({\n * \"urn:babel:orders:created\": async (env) => { ... },\n * }), { connection });\n */\n\nimport {\n BabelQueueError,\n EnvelopeCodec,\n UnknownUrnError,\n type Envelope,\n type IncomingEnvelope,\n} from \"@babelqueue/core\";\nimport type { Job, JobsOptions, Queue } from \"bullmq\";\n\n/** A URN handler. Receives the validated envelope and the raw BullMQ job. */\nexport type BabelHandler = (envelope: Envelope, job: Job) => unknown | Promise<unknown>;\n\n/** A map of URN → handler. */\nexport type BabelHandlers = Record<string, BabelHandler>;\n\n/** Options for {@link publish}. */\nexport interface PublishOptions {\n /** Reuse an existing trace id (trace continuation). */\n traceId?: string;\n /** BullMQ job options (delay, attempts, backoff, …). */\n jobsOptions?: JobsOptions;\n}\n\n/**\n * Build the canonical envelope for `(urn, data)` and add it as a BullMQ job (the\n * job name is the URN, the job data is the envelope). Returns the message id\n * (`meta.id`).\n */\nexport async function publish(\n queue: Queue,\n urn: string,\n data: Record<string, unknown>,\n options: PublishOptions = {},\n): Promise<string> {\n const envelope = EnvelopeCodec.make(urn, data, {\n queue: queue.name,\n traceId: options.traceId,\n });\n await queue.add(urn, envelope, options.jobsOptions);\n return envelope.meta.id;\n}\n\n/** Options for {@link processor}. */\nexport interface ProcessorOptions {\n /** Called instead of throwing when a job's URN has no handler. */\n onUnknownUrn?: (envelope: IncomingEnvelope, job: Job) => unknown | Promise<unknown>;\n}\n\n/**\n * Build a BullMQ processor that decodes each job's envelope, validates it, and\n * routes it to the handler registered for its URN. A non-conformant envelope\n * throws (so BullMQ retries / fails the job per its options); an unmapped URN\n * throws unless `onUnknownUrn` is given.\n *\n * new Worker(\"orders\", processor(handlers), { connection });\n */\nexport function processor(\n handlers: BabelHandlers,\n options: ProcessorOptions = {},\n): (job: Job) => Promise<unknown> {\n return async (job: Job): Promise<unknown> => {\n const envelope = job.data as IncomingEnvelope;\n\n if (!EnvelopeCodec.accepts(envelope)) {\n throw new BabelQueueError(\n `Rejected a non-conformant BabelQueue envelope on job ${job.id ?? \"?\"}.`,\n );\n }\n\n const urn = EnvelopeCodec.urn(envelope);\n const handler = handlers[urn];\n if (!handler) {\n if (options.onUnknownUrn) {\n return options.onUnknownUrn(envelope, job);\n }\n throw new UnknownUrnError(urn);\n }\n\n return handler(envelope, job);\n };\n}\n"],"mappings":";AAmBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAsBP,eAAsB,QACpB,OACA,KACA,MACA,UAA0B,CAAC,GACV;AACjB,QAAM,WAAW,cAAc,KAAK,KAAK,MAAM;AAAA,IAC7C,OAAO,MAAM;AAAA,IACb,SAAS,QAAQ;AAAA,EACnB,CAAC;AACD,QAAM,MAAM,IAAI,KAAK,UAAU,QAAQ,WAAW;AAClD,SAAO,SAAS,KAAK;AACvB;AAgBO,SAAS,UACd,UACA,UAA4B,CAAC,GACG;AAChC,SAAO,OAAO,QAA+B;AAC3C,UAAM,WAAW,IAAI;AAErB,QAAI,CAAC,cAAc,QAAQ,QAAQ,GAAG;AACpC,YAAM,IAAI;AAAA,QACR,wDAAwD,IAAI,MAAM,GAAG;AAAA,MACvE;AAAA,IACF;AAEA,UAAM,MAAM,cAAc,IAAI,QAAQ;AACtC,UAAM,UAAU,SAAS,GAAG;AAC5B,QAAI,CAAC,SAAS;AACZ,UAAI,QAAQ,cAAc;AACxB,eAAO,QAAQ,aAAa,UAAU,GAAG;AAAA,MAC3C;AACA,YAAM,IAAI,gBAAgB,GAAG;AAAA,IAC/B;AAEA,WAAO,QAAQ,UAAU,GAAG;AAAA,EAC9B;AACF;","names":[]}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@babelqueue/bullmq",
3
+ "version": "0.1.0",
4
+ "description": "BullMQ adapter for BabelQueue — canonical-envelope jobs and a URN-routed processor.",
5
+ "keywords": ["babelqueue", "bullmq", "queue", "polyglot", "redis", "messaging"],
6
+ "homepage": "https://babelqueue.com",
7
+ "bugs": {
8
+ "url": "https://github.com/BabelQueue/babelqueue-node-adapters/issues"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/BabelQueue/babelqueue-node-adapters.git",
13
+ "directory": "packages/bullmq"
14
+ },
15
+ "license": "MIT",
16
+ "author": "Muhammet Şafak <info@muhammetsafak.com.tr>",
17
+ "type": "module",
18
+ "exports": {
19
+ ".": {
20
+ "import": {
21
+ "types": "./dist/index.d.ts",
22
+ "default": "./dist/index.js"
23
+ },
24
+ "require": {
25
+ "types": "./dist/index.d.cts",
26
+ "default": "./dist/index.cjs"
27
+ }
28
+ }
29
+ },
30
+ "main": "./dist/index.cjs",
31
+ "module": "./dist/index.js",
32
+ "types": "./dist/index.d.ts",
33
+ "files": ["dist"],
34
+ "sideEffects": false,
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "scripts": {
39
+ "build": "tsup",
40
+ "typecheck": "tsc --noEmit",
41
+ "test": "node --import tsx --test test/*.test.ts"
42
+ },
43
+ "dependencies": {
44
+ "@babelqueue/core": "^0.1.0"
45
+ },
46
+ "peerDependencies": {
47
+ "bullmq": "^5.0.0"
48
+ },
49
+ "devDependencies": {
50
+ "bullmq": "^5.34.0"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ }
55
+ }