@aihu/magna 0.2.5 → 0.2.6

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 CHANGED
@@ -27,7 +27,7 @@ npm install @aihu/magna
27
27
  bun add @aihu/magna
28
28
  ```
29
29
 
30
- <sub><i>Auto-generated against `@aihu/magna@0.2.5`.</i></sub>
30
+ <sub><i>Auto-generated against `@aihu/magna@0.2.6`.</i></sub>
31
31
 
32
32
  <!-- END_AUTOGEN: install -->
33
33
 
@@ -38,13 +38,13 @@ bun add @aihu/magna
38
38
 
39
39
  | | |
40
40
  |---|---|
41
- | **Version** | `0.2.5` |
41
+ | **Version** | `0.2.6` |
42
42
  | **Tier** | B — Meta-framework — dep-free Magna GraphQL bridge (resources + JWT relay) |
43
43
  | **Bundle size** | 758 B (gz) — limit 1.8 KB |
44
44
  | **Published files** | 2 entries |
45
45
  | **License** | MIT |
46
46
 
47
- <sub><i>Auto-generated against `@aihu/magna@0.2.5`.</i></sub>
47
+ <sub><i>Auto-generated against `@aihu/magna@0.2.6`.</i></sub>
48
48
 
49
49
  <!-- END_AUTOGEN: stats -->
50
50
 
@@ -58,7 +58,7 @@ bun add @aihu/magna
58
58
  | `.` | `./dist/index.js` | `—` |
59
59
  | `./codegen` | `./dist/codegen.js` | `—` |
60
60
 
61
- <sub><i>Auto-generated against `@aihu/magna@0.2.5`.</i></sub>
61
+ <sub><i>Auto-generated against `@aihu/magna@0.2.6`.</i></sub>
62
62
 
63
63
  <!-- END_AUTOGEN: exports -->
64
64
 
@@ -78,7 +78,7 @@ bun add @aihu/magna
78
78
 
79
79
  - `@aihu/magna-gqlmin` — `^0.2.0`
80
80
 
81
- <sub><i>Auto-generated against `@aihu/magna@0.2.5`.</i></sub>
81
+ <sub><i>Auto-generated against `@aihu/magna@0.2.6`.</i></sub>
82
82
 
83
83
  <!-- END_AUTOGEN: deps -->
84
84
 
@@ -91,7 +91,7 @@ bun add @aihu/magna
91
91
  - [@aihu/server](../server)
92
92
  - [Aihu framework root](../../README.md)
93
93
 
94
- <sub><i>Auto-generated against `@aihu/magna@0.2.5`.</i></sub>
94
+ <sub><i>Auto-generated against `@aihu/magna@0.2.6`.</i></sub>
95
95
 
96
96
  <!-- END_AUTOGEN: see-also -->
97
97
 
@@ -102,6 +102,6 @@ bun add @aihu/magna
102
102
 
103
103
  MIT — see [LICENSE](../../LICENSE).
104
104
 
105
- <sub><i>Auto-generated against `@aihu/magna@0.2.5`.</i></sub>
105
+ <sub><i>Auto-generated against `@aihu/magna@0.2.6`.</i></sub>
106
106
 
107
107
  <!-- END_AUTOGEN: license -->
package/dist/codegen.js CHANGED
@@ -1,3 +1,3 @@
1
- import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as r}from"node:fs";import{dirname as i,isAbsolute as a,join as o}from"node:path";import{definePlugin as s}from"@aihu/plugin";function c(e){return o(e,`.aihu`)}function l(n){e(n)||t(n,{recursive:!0})}function u(t,r){if(!e(t))return r;try{return JSON.parse(n(t,`utf8`))}catch{return r}}function d(e,t){let n=c(e);l(n);let i=o(n,`magna-warnings.json`),a=u(i,{messages:[]});a.messages.includes(t)||(a.messages.push(t),r(i,JSON.stringify(a,null,2),`utf8`))}function f(e,t,n){let a=c(e);l(a);let s=u(o(a,`build-flags.json`),{}),d=t.split(`.`),f=s;for(let e=0;e<d.length-1;e++){let t=d[e];(typeof f[t]!=`object`||f[t]===null||Array.isArray(f[t]))&&(f[t]={}),f=f[t]}let p=d[d.length-1];f[p]=n;let m=o(c(e),`build-flags.json`);l(i(m)),r(m,JSON.stringify(s,null,2),`utf8`)}async function p(s){let{outputDir:c,projectRoot:l}=s,{options:u,outputPath:p}=s.magna,m=u.schemaPath??`schema.graphql`,h=a(m)?m:o(l,m),g;try{g=await import(`@aihu/magna-gqlmin`)}catch{d(c,`gqlmin not installed; SDL validation skipped. createMagnaResource will use untyped string-template GraphQL.`),f(c,`magna.untyped`,!0);return}if(!e(h)){d(c,`schema not found at ${h}; resources will be untyped.`),f(c,`magna.untyped`,!0);return}let _=n(h,`utf8`);try{g.parseSchema(_)}catch(e){d(c,`SDL parse error in ${h}: ${e.message??String(e)}; resources will be untyped.`),f(c,`magna.untyped`,!0);return}let v=a(p)?p:o(l,p);t(i(v),{recursive:!0}),r(v,[`// AUTO-GENERATED by @aihu/magna beforeCompile. Do not edit.`,`// Schema: ${h}`,`// Generated: ${new Date().toISOString()}`,``,`// Typed bindings will be populated when @aihu/magna-gqlmin codegen is implemented.`,`export {}`,``].join(`
1
+ import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as r}from"node:fs";import{dirname as i,isAbsolute as a,join as o}from"node:path";import{definePlugin as s}from"@aihu/plugin";function c(e){return o(e,`.aihu`)}function l(n){e(n)||t(n,{recursive:!0})}function u(t,r){if(!e(t))return r;try{return JSON.parse(n(t,`utf8`))}catch{return r}}function d(e,t){let n=c(e);l(n);let i=o(n,`magna-warnings.json`),a=u(i,{messages:[]});a.messages.includes(t)||(a.messages.push(t),r(i,JSON.stringify(a,null,2),`utf8`))}function f(e,t,n){let a=c(e);l(a);let s=u(o(a,`build-flags.json`),{}),d=new Set([`__proto__`,`constructor`,`prototype`]),f=t.split(`.`);if(f.some(e=>d.has(e)))throw Error(`setBuildFlag: unsafe key segment in "${t}"`);let p=s;for(let e=0;e<f.length-1;e++){let t=f[e];(typeof p[t]!=`object`||p[t]===null||Array.isArray(p[t]))&&(p[t]={}),p=p[t]}let m=f[f.length-1];p[m]=n;let h=o(c(e),`build-flags.json`);l(i(h)),r(h,JSON.stringify(s,null,2),`utf8`)}async function p(s){let{outputDir:c,projectRoot:l}=s,{options:u,outputPath:p}=s.magna,m=u.schemaPath??`schema.graphql`,h=a(m)?m:o(l,m),g;try{g=await import(`@aihu/magna-gqlmin`)}catch{d(c,`gqlmin not installed; SDL validation skipped. createMagnaResource will use untyped string-template GraphQL.`),f(c,`magna.untyped`,!0);return}if(!e(h)){d(c,`schema not found at ${h}; resources will be untyped.`),f(c,`magna.untyped`,!0);return}let _=n(h,`utf8`);try{g.parseSchema(_)}catch(e){d(c,`SDL parse error in ${h}: ${e.message??String(e)}; resources will be untyped.`),f(c,`magna.untyped`,!0);return}let v=a(p)?p:o(l,p);t(i(v),{recursive:!0}),r(v,[`// AUTO-GENERATED by @aihu/magna beforeCompile. Do not edit.`,`// Schema: ${h}`,`// Generated: ${new Date().toISOString()}`,``,`// Typed bindings will be populated when @aihu/magna-gqlmin codegen is implemented.`,`export {}`,``].join(`
2
2
  `),`utf8`),f(c,`magna.untyped`,!1)}function m(e){return s({name:`@aihu/magna`,version:`0.1.0`,namespace:`magna`,aihuVersion:`^0.2.0`,hooks:{beforeCompile:async t=>{await p({...t,magna:{options:e,untyped:!1,outputPath:`src/generated/magna.ts`,warnings:[]}})}}})}export{p as beforeCompile,m as magna,f as setBuildFlag,d as writeWarnOnce};
3
3
  //# sourceMappingURL=codegen.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"codegen.js","names":[],"sources":["../src/warnings.ts","../src/codegen.ts","../src/plugin.ts"],"sourcesContent":["/**\n * @aihu/magna — build-time warning and flag helpers.\n *\n * This module is build-time ONLY. It uses Node.js `node:fs` to read and write\n * JSON files in the output directory. It MUST NOT be imported in browser bundles.\n *\n * Two helpers:\n * writeWarnOnce — coalescing warn logger (deduplicates messages)\n * setBuildFlag — deep-merge key/value into build-flags.json\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\n/** Absolute path to the .aihu/ directory inside outputDir. */\nfunction aihuDir(outputDir: string): string {\n return join(outputDir, '.aihu')\n}\n\nfunction ensureDir(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n}\n\nfunction readJson<T>(filePath: string, fallback: T): T {\n if (!existsSync(filePath)) return fallback\n try {\n return JSON.parse(readFileSync(filePath, 'utf8')) as T\n } catch {\n return fallback\n }\n}\n\n/**\n * Append `message` to `<outputDir>/.aihu/magna-warnings.json` unless it is\n * already present (coalesce duplicate warnings across multiple build runs or\n * hook invocations within the same run).\n *\n * File format: `{ \"messages\": [\"...\"] }`\n */\nexport function writeWarnOnce(outputDir: string, message: string): void {\n const dir = aihuDir(outputDir)\n ensureDir(dir)\n\n const filePath = join(dir, 'magna-warnings.json')\n const data = readJson<{ messages: string[] }>(filePath, { messages: [] })\n\n if (!data.messages.includes(message)) {\n data.messages.push(message)\n writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8')\n }\n}\n\n/**\n * Deep-merge `value` into `<outputDir>/.aihu/build-flags.json` at the given\n * dot-notation `key` (e.g. `'magna.untyped'` → `{ magna: { untyped: value } }`).\n *\n * Existing sibling keys at each nesting level are preserved; only the target\n * leaf is overwritten.\n */\nexport function setBuildFlag(outputDir: string, key: string, value: unknown): void {\n const dir = aihuDir(outputDir)\n ensureDir(dir)\n\n const filePath = join(dir, 'build-flags.json')\n const root = readJson<Record<string, unknown>>(filePath, {})\n\n // Walk dot-notation segments and deep-merge.\n const segments = key.split('.')\n let cursor: Record<string, unknown> = root\n\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i] as string\n if (typeof cursor[seg] !== 'object' || cursor[seg] === null || Array.isArray(cursor[seg])) {\n cursor[seg] = {}\n }\n cursor = cursor[seg] as Record<string, unknown>\n }\n\n const leaf = segments[segments.length - 1] as string\n cursor[leaf] = value\n\n const absPath = join(aihuDir(outputDir), 'build-flags.json')\n ensureDir(dirname(absPath))\n writeFileSync(absPath, JSON.stringify(root, null, 2), 'utf8')\n}\n","/**\n * @aihu/magna — beforeCompile SDL pipeline.\n *\n * Implements the SDL validation + typed-binding generation step that runs during\n * the aihu build phase. Gracefully skips when @aihu/magna-gqlmin is absent.\n *\n * Pipeline (per brief):\n * 1. Resolve schemaPath (default 'schema.graphql') against ctx.projectRoot.\n * 2. Try to import @aihu/magna-gqlmin. On failure → warn + untyped=true, return.\n * 3. Check if schema file exists. If not → warn + untyped=true, return.\n * 4. Parse SDL via gqlmin.parseSchema(). On parse error → warn + untyped=true, return.\n * 5. Emit typed bindings to outputPath (default 'src/generated/magna.ts').\n * 6. setBuildFlag(magna.untyped, false).\n *\n * This module is build-time ONLY (uses node:fs). Never imported in browser bundles.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, isAbsolute, join } from 'node:path'\nimport type { MagnaBuildContext } from './types.js'\nimport { setBuildFlag, writeWarnOnce } from './warnings.js'\n\ninterface GqlminModule {\n parseSchema: (sdl: string) => unknown\n}\n\n/**\n * Run the beforeCompile SDL pipeline.\n *\n * All failures are handled gracefully — the build is never aborted; instead\n * a warning is recorded and `magna.untyped` is set to `true` so consumers\n * know typed generation was skipped.\n */\nexport async function beforeCompile(ctx: MagnaBuildContext): Promise<void> {\n const { outputDir, projectRoot } = ctx\n const { options, outputPath } = ctx.magna\n\n // 1. Resolve schemaPath\n const rawPath = options.schemaPath ?? 'schema.graphql'\n const schemaAbsPath = isAbsolute(rawPath) ? rawPath : join(projectRoot, rawPath)\n\n // 2. Try to import @aihu/magna-gqlmin\n let gqlmin: GqlminModule\n try {\n // @ts-expect-error — @aihu/magna-gqlmin is optional; graceful-skip when absent\n // eslint-disable-next-line\n gqlmin = (await import(/* @vite-ignore */ '@aihu/magna-gqlmin')) as GqlminModule\n } catch {\n writeWarnOnce(\n outputDir,\n 'gqlmin not installed; SDL validation skipped. createMagnaResource will use untyped string-template GraphQL.',\n )\n setBuildFlag(outputDir, 'magna.untyped', true)\n return\n }\n\n // 3. Check if schema file exists\n if (!existsSync(schemaAbsPath)) {\n writeWarnOnce(outputDir, `schema not found at ${schemaAbsPath}; resources will be untyped.`)\n setBuildFlag(outputDir, 'magna.untyped', true)\n return\n }\n\n // 4. Parse the SDL\n const sdl = readFileSync(schemaAbsPath, 'utf8')\n let _ast: unknown\n try {\n _ast = gqlmin.parseSchema(sdl)\n } catch (err) {\n writeWarnOnce(\n outputDir,\n `SDL parse error in ${schemaAbsPath}: ${(err as Error).message ?? String(err)}; resources will be untyped.`,\n )\n setBuildFlag(outputDir, 'magna.untyped', true)\n return\n }\n\n // 5. Emit typed bindings\n const absOutputPath = isAbsolute(outputPath) ? outputPath : join(projectRoot, outputPath)\n mkdirSync(dirname(absOutputPath), { recursive: true })\n writeFileSync(\n absOutputPath,\n [\n '// AUTO-GENERATED by @aihu/magna beforeCompile. Do not edit.',\n `// Schema: ${schemaAbsPath}`,\n `// Generated: ${new Date().toISOString()}`,\n '',\n '// Typed bindings will be populated when @aihu/magna-gqlmin codegen is implemented.',\n 'export {}',\n '',\n ].join('\\n'),\n 'utf8',\n )\n\n // 6. Mark as typed\n setBuildFlag(outputDir, 'magna.untyped', false)\n}\n","/**\n * @aihu/magna — plugin factory.\n *\n * `magna(options)` returns a `Plugin` that wires the SDL pipeline into the\n * aihu `beforeCompile` build hook. Register it in `defineAihuConfig`:\n *\n * @example\n * // aihu.config.ts\n * import { magna } from '@aihu/magna'\n * import { defineAihuConfig } from '@aihu/server'\n *\n * export default defineAihuConfig({\n * plugins: [\n * magna({ url: process.env.MAGNA_GRAPHQL_URL! }),\n * ],\n * })\n */\n\nimport type { Plugin } from '@aihu/plugin'\nimport { definePlugin } from '@aihu/plugin'\nimport { beforeCompile } from './codegen.js'\nimport type { MagnaBuildContext, MagnaPluginOptions } from './types.js'\n\n/**\n * Create the @aihu/magna plugin.\n *\n * Wires the SDL validation pipeline into the `beforeCompile` hook so that\n * typed GraphQL bindings are generated (or gracefully skipped) at build time.\n */\nexport function magna(options: MagnaPluginOptions): Plugin {\n return definePlugin({\n name: '@aihu/magna',\n version: '0.1.0',\n namespace: 'magna',\n aihuVersion: '^0.2.0',\n hooks: {\n beforeCompile: async (ctx) => {\n const magnaCtx: MagnaBuildContext = {\n ...ctx,\n magna: {\n options,\n untyped: false,\n outputPath: 'src/generated/magna.ts',\n warnings: [],\n },\n }\n await beforeCompile(magnaCtx)\n },\n },\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"codegen.js","names":[],"sources":["../src/warnings.ts","../src/codegen.ts","../src/plugin.ts"],"sourcesContent":["/**\n * @aihu/magna — build-time warning and flag helpers.\n *\n * This module is build-time ONLY. It uses Node.js `node:fs` to read and write\n * JSON files in the output directory. It MUST NOT be imported in browser bundles.\n *\n * Two helpers:\n * writeWarnOnce — coalescing warn logger (deduplicates messages)\n * setBuildFlag — deep-merge key/value into build-flags.json\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\n/** Absolute path to the .aihu/ directory inside outputDir. */\nfunction aihuDir(outputDir: string): string {\n return join(outputDir, '.aihu')\n}\n\nfunction ensureDir(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n}\n\nfunction readJson<T>(filePath: string, fallback: T): T {\n if (!existsSync(filePath)) return fallback\n try {\n return JSON.parse(readFileSync(filePath, 'utf8')) as T\n } catch {\n return fallback\n }\n}\n\n/**\n * Append `message` to `<outputDir>/.aihu/magna-warnings.json` unless it is\n * already present (coalesce duplicate warnings across multiple build runs or\n * hook invocations within the same run).\n *\n * File format: `{ \"messages\": [\"...\"] }`\n */\nexport function writeWarnOnce(outputDir: string, message: string): void {\n const dir = aihuDir(outputDir)\n ensureDir(dir)\n\n const filePath = join(dir, 'magna-warnings.json')\n const data = readJson<{ messages: string[] }>(filePath, { messages: [] })\n\n if (!data.messages.includes(message)) {\n data.messages.push(message)\n writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8')\n }\n}\n\n/**\n * Deep-merge `value` into `<outputDir>/.aihu/build-flags.json` at the given\n * dot-notation `key` (e.g. `'magna.untyped'` → `{ magna: { untyped: value } }`).\n *\n * Existing sibling keys at each nesting level are preserved; only the target\n * leaf is overwritten.\n */\nexport function setBuildFlag(outputDir: string, key: string, value: unknown): void {\n const dir = aihuDir(outputDir)\n ensureDir(dir)\n\n const filePath = join(dir, 'build-flags.json')\n const root = readJson<Record<string, unknown>>(filePath, {})\n\n // Walk dot-notation segments and deep-merge. `key` is a public API\n // parameter (exported function) — reject __proto__/constructor/prototype\n // segments so a future caller can't pollute Object.prototype across the\n // process (CodeQL js/prototype-pollution-utility). Every CURRENT caller\n // passes a hardcoded literal ('magna.untyped'), but the guard costs\n // nothing and the contract itself accepts an arbitrary string.\n const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype'])\n const segments = key.split('.')\n if (segments.some((seg) => UNSAFE_KEYS.has(seg))) {\n throw new Error(`setBuildFlag: unsafe key segment in \"${key}\"`)\n }\n let cursor: Record<string, unknown> = root\n\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i] as string\n if (typeof cursor[seg] !== 'object' || cursor[seg] === null || Array.isArray(cursor[seg])) {\n cursor[seg] = {}\n }\n cursor = cursor[seg] as Record<string, unknown>\n }\n\n const leaf = segments[segments.length - 1] as string\n cursor[leaf] = value\n\n const absPath = join(aihuDir(outputDir), 'build-flags.json')\n ensureDir(dirname(absPath))\n writeFileSync(absPath, JSON.stringify(root, null, 2), 'utf8')\n}\n","/**\n * @aihu/magna — beforeCompile SDL pipeline.\n *\n * Implements the SDL validation + typed-binding generation step that runs during\n * the aihu build phase. Gracefully skips when @aihu/magna-gqlmin is absent.\n *\n * Pipeline (per brief):\n * 1. Resolve schemaPath (default 'schema.graphql') against ctx.projectRoot.\n * 2. Try to import @aihu/magna-gqlmin. On failure → warn + untyped=true, return.\n * 3. Check if schema file exists. If not → warn + untyped=true, return.\n * 4. Parse SDL via gqlmin.parseSchema(). On parse error → warn + untyped=true, return.\n * 5. Emit typed bindings to outputPath (default 'src/generated/magna.ts').\n * 6. setBuildFlag(magna.untyped, false).\n *\n * This module is build-time ONLY (uses node:fs). Never imported in browser bundles.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, isAbsolute, join } from 'node:path'\nimport type { MagnaBuildContext } from './types.js'\nimport { setBuildFlag, writeWarnOnce } from './warnings.js'\n\ninterface GqlminModule {\n parseSchema: (sdl: string) => unknown\n}\n\n/**\n * Run the beforeCompile SDL pipeline.\n *\n * All failures are handled gracefully — the build is never aborted; instead\n * a warning is recorded and `magna.untyped` is set to `true` so consumers\n * know typed generation was skipped.\n */\nexport async function beforeCompile(ctx: MagnaBuildContext): Promise<void> {\n const { outputDir, projectRoot } = ctx\n const { options, outputPath } = ctx.magna\n\n // 1. Resolve schemaPath\n const rawPath = options.schemaPath ?? 'schema.graphql'\n const schemaAbsPath = isAbsolute(rawPath) ? rawPath : join(projectRoot, rawPath)\n\n // 2. Try to import @aihu/magna-gqlmin\n let gqlmin: GqlminModule\n try {\n // @ts-expect-error — @aihu/magna-gqlmin is optional; graceful-skip when absent\n // eslint-disable-next-line\n gqlmin = (await import(/* @vite-ignore */ '@aihu/magna-gqlmin')) as GqlminModule\n } catch {\n writeWarnOnce(\n outputDir,\n 'gqlmin not installed; SDL validation skipped. createMagnaResource will use untyped string-template GraphQL.',\n )\n setBuildFlag(outputDir, 'magna.untyped', true)\n return\n }\n\n // 3. Check if schema file exists\n if (!existsSync(schemaAbsPath)) {\n writeWarnOnce(outputDir, `schema not found at ${schemaAbsPath}; resources will be untyped.`)\n setBuildFlag(outputDir, 'magna.untyped', true)\n return\n }\n\n // 4. Parse the SDL\n const sdl = readFileSync(schemaAbsPath, 'utf8')\n let _ast: unknown\n try {\n _ast = gqlmin.parseSchema(sdl)\n } catch (err) {\n writeWarnOnce(\n outputDir,\n `SDL parse error in ${schemaAbsPath}: ${(err as Error).message ?? String(err)}; resources will be untyped.`,\n )\n setBuildFlag(outputDir, 'magna.untyped', true)\n return\n }\n\n // 5. Emit typed bindings\n const absOutputPath = isAbsolute(outputPath) ? outputPath : join(projectRoot, outputPath)\n mkdirSync(dirname(absOutputPath), { recursive: true })\n writeFileSync(\n absOutputPath,\n [\n '// AUTO-GENERATED by @aihu/magna beforeCompile. Do not edit.',\n `// Schema: ${schemaAbsPath}`,\n `// Generated: ${new Date().toISOString()}`,\n '',\n '// Typed bindings will be populated when @aihu/magna-gqlmin codegen is implemented.',\n 'export {}',\n '',\n ].join('\\n'),\n 'utf8',\n )\n\n // 6. Mark as typed\n setBuildFlag(outputDir, 'magna.untyped', false)\n}\n","/**\n * @aihu/magna — plugin factory.\n *\n * `magna(options)` returns a `Plugin` that wires the SDL pipeline into the\n * aihu `beforeCompile` build hook. Register it in `defineAihuConfig`:\n *\n * @example\n * // aihu.config.ts\n * import { magna } from '@aihu/magna'\n * import { defineAihuConfig } from '@aihu/server'\n *\n * export default defineAihuConfig({\n * plugins: [\n * magna({ url: process.env.MAGNA_GRAPHQL_URL! }),\n * ],\n * })\n */\n\nimport type { Plugin } from '@aihu/plugin'\nimport { definePlugin } from '@aihu/plugin'\nimport { beforeCompile } from './codegen.js'\nimport type { MagnaBuildContext, MagnaPluginOptions } from './types.js'\n\n/**\n * Create the @aihu/magna plugin.\n *\n * Wires the SDL validation pipeline into the `beforeCompile` hook so that\n * typed GraphQL bindings are generated (or gracefully skipped) at build time.\n */\nexport function magna(options: MagnaPluginOptions): Plugin {\n return definePlugin({\n name: '@aihu/magna',\n version: '0.1.0',\n namespace: 'magna',\n aihuVersion: '^0.2.0',\n hooks: {\n beforeCompile: async (ctx) => {\n const magnaCtx: MagnaBuildContext = {\n ...ctx,\n magna: {\n options,\n untyped: false,\n outputPath: 'src/generated/magna.ts',\n warnings: [],\n },\n }\n await beforeCompile(magnaCtx)\n },\n },\n })\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aihu/magna",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "aihu bridge for Magna GraphQL — dep-free fetch, resource composition, JWT relay",
5
5
  "license": "MIT",
6
6
  "type": "module",