@sebspark/pubsub
Version:
A wrapper around [@google-cloud/pubsub](https://www.npmjs.com/package/@google-cloud/pubsub) adding simple methods for publishing and subscribing with typed messages.
197 lines (193 loc) • 6.34 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
createPublisher: () => createPublisher,
createSubscriber: () => createSubscriber
});
module.exports = __toCommonJS(index_exports);
// src/lib/publisher.ts
var import_pubsub = require("@google-cloud/pubsub");
var import_avsc = require("avsc");
var schemaIdPattern = /^(?!goog)[a-zA-Z][a-zA-Z0-9-._~%+]{2,254}$/;
var syncTopicSchema = async (client, cloudSchema) => {
if (!schemaIdPattern.test(cloudSchema.schemaId)) {
throw Error(
"schemaId is no in a valid format. Check google cloud platform for more information"
);
}
const schema = client.schema(cloudSchema.schemaId);
const exits = await schemaExists(client, cloudSchema.schemaId);
if (exits) {
const data2 = await schema.get();
return data2;
}
await client.createSchema(
cloudSchema.schemaId,
import_pubsub.SchemaTypes.Avro,
cloudSchema.avroDefinition
);
const data = await schema.get();
return data;
};
var createOrGetTopic = async (client, name, schemaData) => {
const [exists] = await client.topic(name).exists();
if (exists) {
const [topic2] = await client.topic(name).get();
return topic2;
}
if (schemaData) {
const [topic2] = await client.createTopic({
name,
schemaSettings: {
schema: schemaData?.name,
encoding: import_pubsub.Encodings.Binary
}
});
return topic2;
}
const [topic] = await client.createTopic({
name
});
return topic;
};
var createPublisher = (clientOptions, publishOptions) => {
const client = clientOptions ? new import_pubsub.PubSub(clientOptions) : new import_pubsub.PubSub();
let _topic;
let _type;
const ensureInitiated = async (name, schema) => {
if (!_topic) {
if (schema) {
const schemaData = await syncTopicSchema(client, schema);
_topic = await createOrGetTopic(client, name, schemaData);
} else {
_topic = await createOrGetTopic(client, name);
}
if (publishOptions) {
_topic.setPublishOptions(publishOptions);
}
if (schema && !_type) {
const schemaType = import_avsc.Type.forSchema(JSON.parse(schema.avroDefinition));
_type = schemaType;
}
}
};
const typedClient = {
topic: (name, schema) => {
return {
initiate: async () => {
return ensureInitiated(name, schema);
},
publish: async (json) => {
await ensureInitiated(name, schema);
if (_type) {
const data = _type.toBuffer(
json
);
await _topic.publishMessage({ data });
} else {
await _topic.publishMessage({ json });
}
}
};
}
};
return typedClient;
};
var schemaExists = async (client, schemaId) => {
for await (const s of client.listSchemas()) {
if (s.name?.endsWith(`/${schemaId}`)) {
return true;
}
}
return false;
};
// src/lib/subscriber.ts
var import_pubsub2 = require("@google-cloud/pubsub");
var import_avsc2 = require("avsc");
var makeSureSubscriptionExists = async (topic, name, options) => {
const createSubscriptionOptions = {
messageRetentionDuration: {
seconds: options?.messageRetentionDuration || 3600 * 24
// Default to 1 day.
},
expirationPolicy: {
ttl: {
seconds: options?.expirationPolicy || 3600 * 24 * 7
// Default to 7 days.
}
}
};
const [exists] = await topic.subscription(name).exists();
if (exists) {
return;
}
await topic.createSubscription(name, createSubscriptionOptions);
};
var createSubscriber = (clientOptions) => {
const client = clientOptions ? new import_pubsub2.PubSub(clientOptions) : new import_pubsub2.PubSub();
let _type;
const typedClient = {
topic: (name, schema) => {
if (schema && !_type) {
const schemaType = import_avsc2.Type.forSchema(JSON.parse(schema.avroDefinition));
_type = schemaType;
}
const _topic = client.topic(name);
return {
initiate: async (subscriptionName, options) => {
await makeSureSubscriptionExists(_topic, subscriptionName, options);
},
subscribe: async (subscriptionName, callbacks, options) => {
const subscription = _topic.subscription(subscriptionName);
subscription.on("message", async (msg) => {
const data = _type ? _type.fromBuffer(msg.data) : JSON.parse(msg.data.toString("utf8"));
if (options?.autoAck === void 0 || options.autoAck === true) {
try {
await callbacks.onMessage(Object.assign(msg, { data }));
msg.ack();
} catch (error) {
msg.nack();
callbacks.onError ? callbacks.onError(Object.assign(msg, { data }), error) : console.error(error);
}
} else {
await callbacks.onMessage(Object.assign(msg, { data }));
}
});
return subscription;
},
close: async (subscriptionName) => {
const subscription = _topic.subscription(subscriptionName);
await subscription.close();
},
delete: async (subscriptionName) => {
const subscription = _topic.subscription(subscriptionName);
await subscription.delete();
}
};
}
};
return typedClient;
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
createPublisher,
createSubscriber
});