@pikku/openapi-parser 0.12.6 → 0.12.7

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @pikku/openapi-parser
2
2
 
3
+ ## 0.12.7
4
+
5
+ ### Patch Changes
6
+
7
+ - 5dd1996: Fix credentials command crash when state.credentials is undefined, and add --credential flag to `pikku new addon` for per-user credential wiring (apikey, bearer, oauth2).
8
+
3
9
  ## 0.12.6
4
10
 
5
11
  ### Patch Changes
package/dist/codegen.d.ts CHANGED
@@ -14,6 +14,7 @@ interface AddonVars {
14
14
  interface CodegenFlags {
15
15
  oauth: boolean;
16
16
  secret: boolean;
17
+ credential?: 'apikey' | 'bearer' | 'oauth2';
17
18
  mcp?: boolean;
18
19
  }
19
20
  export declare function generateAddonFromOpenAPI(spec: ParsedSpec, vars: AddonVars, flags: CodegenFlags): Record<string, string>;
package/dist/codegen.js CHANGED
@@ -235,7 +235,10 @@ function generateServiceFile(spec, opPairs, vars, flags) {
235
235
  const lines = [];
236
236
  // Always import all error classes used in the switch statement
237
237
  const allErrorClasses = new Set(Object.values(STATUS_TO_ERROR));
238
- if (flags.oauth) {
238
+ if (flags.credential && flags.credential !== 'oauth2') {
239
+ // Per-user credential: no special imports needed, creds passed via constructor
240
+ }
241
+ else if (flags.oauth || flags.credential === 'oauth2') {
239
242
  lines.push("import { OAuth2Client } from '@pikku/core/oauth2'");
240
243
  lines.push("import type { TypedSecretService } from '#pikku/secrets/pikku-secrets.gen.js'");
241
244
  }
@@ -286,7 +289,14 @@ function generateServiceFile(spec, opPairs, vars, flags) {
286
289
  // Class declaration
287
290
  lines.push(`export class ${pascalName}Service {`);
288
291
  lines.push(' private baseUrl: string');
289
- if (flags.oauth) {
292
+ if (flags.credential && flags.credential !== 'oauth2') {
293
+ const credField = flags.credential === 'bearer' ? 'token' : 'apiKey';
294
+ lines.push('');
295
+ lines.push(` constructor(private creds: { ${credField}: string }, variables: TypedVariablesService) {`);
296
+ lines.push(` this.baseUrl = variables.get('${screamingName}_BASE_URL') as string`);
297
+ lines.push(' }');
298
+ }
299
+ else if (flags.oauth || flags.credential === 'oauth2') {
290
300
  lines.push(' private oauth: OAuth2Client');
291
301
  lines.push('');
292
302
  lines.push(` constructor(secrets: TypedSecretService, variables: TypedVariablesService) {`);
@@ -359,7 +369,29 @@ function generateServiceFile(spec, opPairs, vars, flags) {
359
369
  lines.push(' url.searchParams.set(key, value)');
360
370
  lines.push(' }');
361
371
  lines.push('');
362
- if (flags.oauth) {
372
+ if (flags.credential && flags.credential !== 'oauth2') {
373
+ // Per-user credential: use creds from wire.getCredentials()
374
+ if (flags.credential === 'bearer') {
375
+ lines.push(' headers.Authorization = `Bearer ${this.creds.token}`');
376
+ }
377
+ else {
378
+ // apikey: check spec for custom header name
379
+ const apiKeyScheme = Object.values(spec.securitySchemes).find((s) => s.type === 'apiKey');
380
+ if (apiKeyScheme?.name && apiKeyScheme?.in === 'header') {
381
+ lines.push(` headers[${JSON.stringify(apiKeyScheme.name)}] = this.creds.apiKey`);
382
+ }
383
+ else {
384
+ lines.push(' headers.Authorization = `Bearer ${this.creds.apiKey}`');
385
+ }
386
+ }
387
+ lines.push('');
388
+ lines.push(' const response = await fetch(url.toString(), {');
389
+ lines.push(' method,');
390
+ lines.push(' headers,');
391
+ lines.push(' body: body ? JSON.stringify(body) : undefined,');
392
+ lines.push(' })');
393
+ }
394
+ else if (flags.oauth || flags.credential === 'oauth2') {
363
395
  lines.push(' const response = await this.oauth.request(url.toString(), {');
364
396
  lines.push(' method,');
365
397
  lines.push(' headers,');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/openapi-parser",
3
- "version": "0.12.6",
3
+ "version": "0.12.7",
4
4
  "description": "OpenAPI spec parser and code generator for Pikku",
5
5
  "author": "yasser.fadl@gmail.com",
6
6
  "license": "MIT",
package/src/codegen.ts CHANGED
@@ -32,6 +32,7 @@ interface AddonVars {
32
32
  interface CodegenFlags {
33
33
  oauth: boolean
34
34
  secret: boolean
35
+ credential?: 'apikey' | 'bearer' | 'oauth2'
35
36
  mcp?: boolean
36
37
  }
37
38
 
@@ -386,7 +387,9 @@ function generateServiceFile(
386
387
  // Always import all error classes used in the switch statement
387
388
  const allErrorClasses = new Set<string>(Object.values(STATUS_TO_ERROR))
388
389
 
389
- if (flags.oauth) {
390
+ if (flags.credential && flags.credential !== 'oauth2') {
391
+ // Per-user credential: no special imports needed, creds passed via constructor
392
+ } else if (flags.oauth || flags.credential === 'oauth2') {
390
393
  lines.push("import { OAuth2Client } from '@pikku/core/oauth2'")
391
394
  lines.push(
392
395
  "import type { TypedSecretService } from '#pikku/secrets/pikku-secrets.gen.js'"
@@ -458,7 +461,17 @@ function generateServiceFile(
458
461
  lines.push(`export class ${pascalName}Service {`)
459
462
  lines.push(' private baseUrl: string')
460
463
 
461
- if (flags.oauth) {
464
+ if (flags.credential && flags.credential !== 'oauth2') {
465
+ const credField = flags.credential === 'bearer' ? 'token' : 'apiKey'
466
+ lines.push('')
467
+ lines.push(
468
+ ` constructor(private creds: { ${credField}: string }, variables: TypedVariablesService) {`
469
+ )
470
+ lines.push(
471
+ ` this.baseUrl = variables.get('${screamingName}_BASE_URL') as string`
472
+ )
473
+ lines.push(' }')
474
+ } else if (flags.oauth || flags.credential === 'oauth2') {
462
475
  lines.push(' private oauth: OAuth2Client')
463
476
  lines.push('')
464
477
  lines.push(
@@ -548,7 +561,30 @@ function generateServiceFile(
548
561
  lines.push(' }')
549
562
  lines.push('')
550
563
 
551
- if (flags.oauth) {
564
+ if (flags.credential && flags.credential !== 'oauth2') {
565
+ // Per-user credential: use creds from wire.getCredentials()
566
+ if (flags.credential === 'bearer') {
567
+ lines.push(' headers.Authorization = `Bearer ${this.creds.token}`')
568
+ } else {
569
+ // apikey: check spec for custom header name
570
+ const apiKeyScheme = Object.values(spec.securitySchemes).find(
571
+ (s) => s.type === 'apiKey'
572
+ )
573
+ if (apiKeyScheme?.name && apiKeyScheme?.in === 'header') {
574
+ lines.push(
575
+ ` headers[${JSON.stringify(apiKeyScheme.name)}] = this.creds.apiKey`
576
+ )
577
+ } else {
578
+ lines.push(' headers.Authorization = `Bearer ${this.creds.apiKey}`')
579
+ }
580
+ }
581
+ lines.push('')
582
+ lines.push(' const response = await fetch(url.toString(), {')
583
+ lines.push(' method,')
584
+ lines.push(' headers,')
585
+ lines.push(' body: body ? JSON.stringify(body) : undefined,')
586
+ lines.push(' })')
587
+ } else if (flags.oauth || flags.credential === 'oauth2') {
552
588
  lines.push(
553
589
  ' const response = await this.oauth.request(url.toString(), {'
554
590
  )