@theholocron/holocron-plugin-postman 2.0.0-alpha.51 → 2.0.0-alpha.52

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/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
- import { AuthError, ResolveTokenInput, RestClient, RestClient as RestClient$1, Tooling, ToolingDoctorReport } from "@theholocron/cli";
1
+ import { AuthError, ResolveTokenInput, Tooling, ToolingDoctorReport } from "@theholocron/cli";
2
+ import { PostmanClient, PostmanClient as PostmanClient$1, PostmanCollection, PostmanEnvironment, PostmanPlanLimitError, PostmanSpec, PostmanUser, PostmanWorkspace, createPostmanClient, detectPlanLimit } from "@theholocron/postman-client";
2
3
 
3
4
  //#region src/auth.d.ts
4
5
  declare const resolveToken: (input?: import("@theholocron/http-client").ResolveTokenInput) => string;
@@ -17,38 +18,13 @@ interface PostmanToolingOptions {
17
18
  /** Working repo root. Defaults to process.cwd(). */
18
19
  repoRoot?: string;
19
20
  }
20
- interface PostmanUser {
21
- id: number;
22
- username: string;
23
- fullName: string;
24
- }
25
- interface PostmanWorkspace {
26
- id: string;
27
- name: string;
28
- type: string;
29
- }
30
- interface PostmanCollection {
31
- id: string;
32
- uid: string;
33
- name: string;
34
- }
35
- interface PostmanEnvironment {
36
- id: string;
37
- uid: string;
38
- name: string;
39
- }
40
- interface PostmanSpec {
41
- id: string;
42
- name: string;
43
- type: string;
44
- }
45
21
  declare class PostmanTooling implements Tooling {
46
- private readonly rest;
22
+ private readonly client;
47
23
  readonly key: "tooling";
48
24
  readonly providerName = "postman";
49
25
  private readonly opts;
50
26
  private readonly repoRoot;
51
- constructor(rest: RestClient, opts: PostmanToolingOptions);
27
+ constructor(client: PostmanClient$1, opts: PostmanToolingOptions);
52
28
  sync(): Promise<void>;
53
29
  doctor(): Promise<ToolingDoctorReport>;
54
30
  getMyself(): Promise<PostmanUser>;
@@ -95,41 +71,6 @@ declare class PostmanTooling implements Tooling {
95
71
  }): Promise<void>;
96
72
  }
97
73
  //#endregion
98
- //#region src/errors.d.ts
99
- /**
100
- * Postman-specific errors that callers might want to discriminate.
101
- */
102
- /**
103
- * Thrown when Postman returns a `limitReachedError` (e.g., a Free-tier
104
- * account hitting the "0 APIs" cap). Callers can render "upgrade
105
- * required" instead of dumping the raw API body.
106
- */
107
- declare class PostmanPlanLimitError extends Error {
108
- /** Human-readable plan-limit message from Postman. */
109
- readonly limitMessage: string;
110
- /** Original response body (JSON or text). */
111
- readonly body: string;
112
- name: string;
113
- constructor(/** Human-readable plan-limit message from Postman. */
114
-
115
- limitMessage: string, /** Original response body (JSON or text). */
116
-
117
- body: string);
118
- }
119
- /**
120
- * Inspect a Postman error body for the plan-limit shape. Returns the
121
- * limit message when matched; null otherwise (caller throws a generic
122
- * `ProviderApiError`).
123
- */
124
- declare function detectPlanLimit(body: string): string | null;
125
- //#endregion
126
- //#region src/rest.d.ts
127
- declare function createPostmanRestClient(opts: {
128
- token: string;
129
- baseUrl?: string;
130
- fetch?: typeof fetch;
131
- }): RestClient$1;
132
- //#endregion
133
74
  //#region src/verify-token.d.ts
134
75
  /**
135
76
  * `verifyToken` — plugin-level export used by `holocron auth set` +
@@ -162,7 +103,7 @@ interface PostmanPluginOptions extends ResolveTokenInput, PostmanToolingOptions
162
103
  }
163
104
  interface PluginContext {
164
105
  options: PostmanPluginOptions;
165
- rest: RestClient;
106
+ client: PostmanClient;
166
107
  }
167
108
  declare function createContext(options: PostmanPluginOptions): PluginContext;
168
109
  declare function tooling(ctx: PluginContext): Tooling;
@@ -178,4 +119,4 @@ declare function createPlugin(options: PostmanPluginOptions): {
178
119
  */
179
120
  declare const AUTH_HINT: string;
180
121
  //#endregion
181
- export { AUTH_HINT, AuthError, PluginContext, PostmanPlanLimitError, PostmanPluginOptions, PostmanTooling, type ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createContext, createPlugin, createPostmanRestClient, detectPlanLimit, resolveToken, tooling, verifyToken };
122
+ export { AUTH_HINT, AuthError, PluginContext, type PostmanClient, PostmanPlanLimitError, PostmanPluginOptions, PostmanTooling, type ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createContext, createPlugin, createPostmanClient, detectPlanLimit, resolveToken, tooling, verifyToken };
package/dist/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
- import { AuthError, ProviderApiError, createResolveToken, createRestClient } from "@theholocron/cli";
1
+ import { AuthError, ProviderApiError, createResolveToken } from "@theholocron/cli";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { basename, resolve } from "node:path";
4
+ import { PostmanPlanLimitError, createPostmanClient, detectPlanLimit } from "@theholocron/postman-client";
4
5
  //#region src/auth.ts
5
6
  const resolveToken = createResolveToken({
6
7
  envName: "HOLOCRON_POSTMAN_API_KEY",
@@ -33,13 +34,13 @@ const resolveToken = createResolveToken({
33
34
  * reachability and returns a `ToolingDoctorReport`.
34
35
  */
35
36
  var PostmanTooling = class {
36
- rest;
37
+ client;
37
38
  key = "tooling";
38
39
  providerName = "postman";
39
40
  opts;
40
41
  repoRoot;
41
- constructor(rest, opts) {
42
- this.rest = rest;
42
+ constructor(client, opts) {
43
+ this.client = client;
43
44
  if (!opts.workspaceId) throw new Error("PostmanTooling requires `workspaceId` in options");
44
45
  this.opts = opts;
45
46
  this.repoRoot = opts.repoRoot ?? process.cwd();
@@ -113,176 +114,57 @@ var PostmanTooling = class {
113
114
  }
114
115
  }
115
116
  async getMyself() {
116
- const raw = await this.rest.request("/me");
117
- return {
118
- id: raw.user.id,
119
- username: raw.user.username,
120
- fullName: raw.user.fullName
121
- };
117
+ return (await this.client.me.get()).user ?? {};
122
118
  }
123
119
  async listWorkspaces() {
124
- return (await this.rest.request("/workspaces")).workspaces.map((w) => ({
125
- id: w.id,
126
- name: w.name,
127
- type: w.type
128
- }));
120
+ const { workspaces } = await this.client.workspaces.list();
121
+ return workspaces;
129
122
  }
130
123
  async findCollectionByName(input) {
131
- const match = (await this.rest.request("/collections", { query: { workspace: input.workspaceId } })).collections.find((c) => c.name === input.name);
132
- return match ? {
133
- id: match.id,
134
- uid: match.uid,
135
- name: match.name
136
- } : null;
124
+ const { collections } = await this.client.collections.list(input.workspaceId);
125
+ return collections.find((c) => c.name === input.name) ?? null;
137
126
  }
138
127
  async deleteCollection(uid) {
139
- await this.rest.request(`/collections/${encodeURIComponent(uid)}`, { method: "DELETE" });
128
+ await this.client.collections.delete(uid);
140
129
  }
141
130
  async importOpenApi(input) {
142
- const created = (await this.rest.request("/import/openapi", {
143
- method: "POST",
144
- query: { workspace: input.workspaceId },
145
- body: {
146
- type: "string",
147
- input: typeof input.spec === "string" ? input.spec : JSON.stringify(input.spec)
148
- }
149
- })).collections[0];
131
+ const { collections } = await this.client.import.openapi(input.workspaceId, input.spec);
132
+ const created = collections[0];
150
133
  if (!created) throw new ProviderApiError("Postman returned no collection on import — check the OpenAPI spec is well-formed", 500, void 0);
151
- return {
152
- id: created.id,
153
- uid: created.uid,
154
- name: created.name
155
- };
134
+ return created;
156
135
  }
157
136
  async listEnvironments(input) {
158
- return (await this.rest.request("/environments", { query: { workspace: input.workspaceId } })).environments.map((e) => ({
159
- id: e.id,
160
- uid: e.uid,
161
- name: e.name
162
- }));
137
+ const { environments } = await this.client.environments.list(input.workspaceId);
138
+ return environments;
163
139
  }
164
140
  async findEnvironmentByName(input) {
165
141
  return (await this.listEnvironments(input)).find((e) => e.name === input.name) ?? null;
166
142
  }
167
143
  async createEnvironment(input) {
168
- const raw = await this.rest.request("/environments", {
169
- method: "POST",
170
- query: { workspace: input.workspaceId },
171
- body: { environment: input.environment }
172
- });
173
- return {
174
- id: raw.environment.id,
175
- uid: raw.environment.uid,
176
- name: raw.environment.name
177
- };
144
+ const { environment } = await this.client.environments.create(input.workspaceId, input.environment);
145
+ return environment;
178
146
  }
179
147
  async updateEnvironment(input) {
180
- const raw = await this.rest.request(`/environments/${encodeURIComponent(input.uid)}`, {
181
- method: "PUT",
182
- body: { environment: input.environment }
183
- });
184
- return {
185
- id: raw.environment.id,
186
- uid: raw.environment.uid,
187
- name: raw.environment.name
188
- };
148
+ const { environment } = await this.client.environments.update(input.uid, input.environment);
149
+ return environment;
189
150
  }
190
151
  async findSpecByName(input) {
191
- const match = (await this.rest.request("/specs", { query: { workspaceId: input.workspaceId } })).specs.find((s) => s.name === input.name);
192
- return match ? {
193
- id: match.id,
194
- name: match.name,
195
- type: match.type
196
- } : null;
152
+ const { specs } = await this.client.specs.list(input.workspaceId);
153
+ return specs.find((s) => s.name === input.name) ?? null;
197
154
  }
198
155
  async createSpec(input) {
199
- const raw = await this.rest.request("/specs", {
200
- method: "POST",
201
- query: { workspaceId: input.workspaceId },
202
- body: {
203
- name: input.name,
204
- type: input.type ?? "OPENAPI:3.0",
205
- files: [{
206
- path: input.filePath ?? "index.json",
207
- content: input.fileContent
208
- }]
209
- }
156
+ return this.client.specs.create(input.workspaceId, {
157
+ name: input.name,
158
+ type: input.type,
159
+ filePath: input.filePath,
160
+ fileContent: input.fileContent
210
161
  });
211
- return {
212
- id: raw.id,
213
- name: raw.name,
214
- type: raw.type
215
- };
216
162
  }
217
163
  async upsertSpecFile(input) {
218
- await this.rest.request(`/specs/${encodeURIComponent(input.specId)}/files/${encodeURIComponent(input.filePath)}`, {
219
- method: "PATCH",
220
- body: { content: input.content }
221
- });
164
+ await this.client.specs.updateFile(input.specId, input.filePath, input.content);
222
165
  }
223
166
  };
224
167
  //#endregion
225
- //#region src/errors.ts
226
- /**
227
- * Postman-specific errors that callers might want to discriminate.
228
- */
229
- /**
230
- * Thrown when Postman returns a `limitReachedError` (e.g., a Free-tier
231
- * account hitting the "0 APIs" cap). Callers can render "upgrade
232
- * required" instead of dumping the raw API body.
233
- */
234
- var PostmanPlanLimitError = class extends Error {
235
- limitMessage;
236
- body;
237
- name = "PostmanPlanLimitError";
238
- constructor(limitMessage, body) {
239
- super(limitMessage);
240
- this.limitMessage = limitMessage;
241
- this.body = body;
242
- }
243
- };
244
- /**
245
- * Inspect a Postman error body for the plan-limit shape. Returns the
246
- * limit message when matched; null otherwise (caller throws a generic
247
- * `ProviderApiError`).
248
- */
249
- function detectPlanLimit(body) {
250
- try {
251
- const parsed = JSON.parse(body);
252
- if (parsed.error?.name === "limitReachedError" && parsed.error.message) return parsed.error.message;
253
- } catch {}
254
- return null;
255
- }
256
- //#endregion
257
- //#region src/rest.ts
258
- function createPostmanRestClient(opts) {
259
- const base = createRestClient({
260
- baseUrl: opts.baseUrl ?? "https://api.getpostman.com",
261
- token: opts.token,
262
- tokenScheme: "apikey",
263
- apiKeyHeader: "x-api-key",
264
- vendor: "Postman",
265
- fetch: opts.fetch
266
- });
267
- return {
268
- baseUrl: base.baseUrl,
269
- async request(path, reqOpts) {
270
- let res;
271
- try {
272
- res = await base.request(path, reqOpts);
273
- } catch (err) {
274
- const details = err.details;
275
- if (typeof details === "string") {
276
- const limit = detectPlanLimit(details);
277
- if (limit) throw new PostmanPlanLimitError(limit, details);
278
- }
279
- throw err;
280
- }
281
- return res;
282
- }
283
- };
284
- }
285
- //#endregion
286
168
  //#region src/verify-token.ts
287
169
  /**
288
170
  * `verifyToken` — plugin-level export used by `holocron auth set` +
@@ -290,13 +172,13 @@ function createPostmanRestClient(opts) {
290
172
  * authenticated user).
291
173
  */
292
174
  async function verifyToken(token, opts = {}) {
293
- const rest = createPostmanRestClient({
175
+ const client = createPostmanClient({
294
176
  token,
295
177
  baseUrl: opts.baseUrl,
296
178
  fetch: opts.fetch
297
179
  });
298
180
  try {
299
- const res = await rest.request("/me");
181
+ const res = await client.me.get();
300
182
  return {
301
183
  ok: true,
302
184
  subject: `user @ ${res?.user?.email ?? res?.user?.username ?? res?.user?.fullName ?? String(res?.user?.id ?? "unknown")}`
@@ -314,7 +196,7 @@ function createContext(options) {
314
196
  if (!options.workspaceId) throw new Error("@theholocron/holocron-plugin-postman requires `workspaceId` in options");
315
197
  return {
316
198
  options,
317
- rest: createPostmanRestClient({
199
+ client: createPostmanClient({
318
200
  token: resolveToken(options),
319
201
  baseUrl: options.baseUrl,
320
202
  fetch: options.fetch
@@ -328,7 +210,7 @@ function tooling(ctx) {
328
210
  if (ctx.options.collectionName !== void 0) opts.collectionName = ctx.options.collectionName;
329
211
  if (ctx.options.envFiles !== void 0) opts.envFiles = ctx.options.envFiles;
330
212
  if (ctx.options.repoRoot !== void 0) opts.repoRoot = ctx.options.repoRoot;
331
- return new PostmanTooling(ctx.rest, opts);
213
+ return new PostmanTooling(ctx.client, opts);
332
214
  }
333
215
  function createPlugin(options) {
334
216
  const ctx = createContext(options);
@@ -343,4 +225,4 @@ function createPlugin(options) {
343
225
  */
344
226
  const AUTH_HINT = "generate a Postman API key at https://postman.co/settings/me/api-keys, then run: holocron auth set postman <KEY>";
345
227
  //#endregion
346
- export { AUTH_HINT, AuthError, PostmanPlanLimitError, PostmanTooling, createContext, createPlugin, createPostmanRestClient, detectPlanLimit, resolveToken, tooling, verifyToken };
228
+ export { AUTH_HINT, AuthError, PostmanPlanLimitError, PostmanTooling, createContext, createPlugin, createPostmanClient, detectPlanLimit, resolveToken, tooling, verifyToken };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/holocron-plugin-postman",
3
- "version": "2.0.0-alpha.51",
3
+ "version": "2.0.0-alpha.52",
4
4
  "description": "Holocron plugin for Postman. Implements the tooling capability against Postman's REST API — workspace + collection + spec + environment sync.",
5
5
  "homepage": "https://github.com/theholocron/holocron/tree/main/packages/holocron-plugin-postman#readme",
6
6
  "bugs": "https://github.com/theholocron/holocron/issues",
@@ -21,9 +21,16 @@
21
21
  }
22
22
  },
23
23
  "peerDependencies": {
24
- "@theholocron/cli": "2.0.0-alpha.51"
24
+ "@theholocron/postman-client": "^0.10.0",
25
+ "@theholocron/cli": "2.0.0-alpha.52"
26
+ },
27
+ "peerDependenciesMeta": {
28
+ "@theholocron/postman-client": {
29
+ "optional": false
30
+ }
25
31
  },
26
32
  "devDependencies": {
33
+ "@theholocron/postman-client": "^0.10.0",
27
34
  "@types/node": "^26",
28
35
  "@theholocron/eslint-config": "^7.0.0",
29
36
  "@theholocron/tsconfig": "^7.0.0",
@@ -37,7 +44,7 @@
37
44
  "tsx": "^4.22.4",
38
45
  "typescript": "^5.9.3",
39
46
  "vitest": "^4.1.10",
40
- "@theholocron/cli": "2.0.0-alpha.51"
47
+ "@theholocron/cli": "2.0.0-alpha.52"
41
48
  },
42
49
  "publishConfig": {
43
50
  "access": "public"