{"_id":"@typed-macro/core","_rev":"2-1a9f2a34d9f36b35f62b5b8f047f2799","name":"@typed-macro/core","dist-tags":{"alpha":"1.0.0-alpha.1","latest":"1.0.0-alpha"},"versions":{"1.0.0-alpha":{"name":"@typed-macro/core","version":"1.0.0-alpha","description":"**For basic concepts, see [documentation for typed-macro](https://github.com/typed-macro/typed-macro/blob/master/DOCUMENTATION.md).**","license":"MIT","repository":{"type":"git","url":"https://github.com/typed-macro/typed-macro"},"author":{"name":"unbyte","email":"i@shangyes.net"},"homepage":"https://github.com/typed-macro/typed-macro/tree/master/packages/core#readme","bugs":{"url":"https://github.com/typed-macro/typed-macro/issues/new"},"main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@babel/generator":"^7.15.8","@babel/parser":"^7.15.8","@babel/template":"^7.15.4","@babel/traverse":"^7.15.4","@babel/types":"^7.15.6","@types/babel__generator":"^7.6.3","@types/babel__template":"^7.4.1","@types/babel__traverse":"^7.14.2","@typed-macro/shared":"1.0.0-alpha"},"peerDependencies":{"chokidar":"^3.5.2"},"_id":"@typed-macro/core@1.0.0-alpha","dist":{"shasum":"387450d3d042fc7d71b7073d1b9eb70241d61594","integrity":"sha512-8tKQ8PMcqUu8a3joZCvt+CR6cPjq+ijW1YRRl8aToGotmYwmjGUTTJOWpWU+YgAn7fPlYPb66XkfXUVvXcXPWA==","tarball":"https://registry.npmjs.org/@typed-macro/core/-/core-1.0.0-alpha.tgz","fileCount":7,"unpackedSize":34412,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhvOCoCRA9TVsSAnZWagAAoqoP/icbxltfBAGttRuC0gb8\nJPVDst6wNWHI2klNoozoAmZACPlbeUDymMwNYU74WPNmFEizhDyfyFr87+Ou\nJaf+EyfJyB7TEEBhM5R96mtOUTGD0wYn2EdJtat4XRiFK9tlx0OxNGfDVaAm\npvcewAVocXVjC1YUz+8lCv+PTdzZz46001fQfpXfK1C1phRCbFl2FHl043Nm\nUr8473/Z6hRdMuK2XfQisD1P3Wj2e6v3fngzOzikBmwD+GGrbAXF1Xzcz5qN\nEpJGrKce2NEspsfsvszpnA2tZC+D/L00OMEvVPkr769aNMx4TefvITdqhO0Q\nuuX7XDem65mfM6qGvF3H5lCdj5PQRXUMMu/LG3Sg3G6jCB5Mfk/WpeH6fTVv\nGQWTqhi8zSJejyyXR6xWu/Pnt54UGNk3RlXEpgswTEeAzWLUoPMzy1q4wjVc\nqz73hOxPvLmMUEgnw+gBaAGc42P7niotmE5Lokgdf6GSHhJJ4JX1tAijmgtd\nfkDYOWNFNE7niMW3jsXf8qb5Vq/KoZOz+asoubmoiBvMYy/E1MGG7sSvV299\nEPkrcbnfncxTNyxB/8LcIuESwDEeuvCXV/kn37k5Paws6MeNFTUoky2AKxVh\n/O4A+J7f0t6T6WztLI0u8QCIDGlLeUuInvu0HjAuCZZOIPLe4dcdaV7s0DkR\ntPHH\r\n=3y+K\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/MmT7EQWHK8i01vi16Kg1M7yzgXjAYEeKMN4UmZKcEgIgI8bFQnFT2TUfropXWjPjGXx/S3k5E9skg6ewNYmDwIA="}]},"_npmUser":{"name":"unbyte","email":"i@shangyes.net"},"directories":{},"maintainers":[{"name":"unbyte","email":"i@shangyes.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/core_1.0.0-alpha_1639768231893_0.30646930656095805"},"_hasShrinkwrap":false},"1.0.0-alpha.1":{"name":"@typed-macro/core","version":"1.0.0-alpha.1","description":"**For basic concepts, see [documentation for typed-macro](https://github.com/typed-macro/typed-macro/blob/master/DOCUMENTATION.md).**","license":"MIT","repository":{"type":"git","url":"https://github.com/typed-macro/typed-macro"},"author":{"name":"unbyte","email":"i@shangyes.net"},"homepage":"https://github.com/typed-macro/typed-macro/tree/master/packages/core#readme","bugs":{"url":"https://github.com/typed-macro/typed-macro/issues/new"},"main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@babel/generator":"^7.15.8","@babel/parser":"^7.15.8","@babel/template":"^7.15.4","@babel/traverse":"^7.15.4","@babel/types":"^7.15.6","@types/babel__generator":"^7.6.3","@types/babel__template":"^7.4.1","@types/babel__traverse":"^7.14.2","@typed-macro/shared":"1.0.0-alpha.1"},"readmeFilename":"README.md","readme":"# @typed-macro/core\n\n**For basic concepts, see [documentation for typed-macro](https://github.com/typed-macro/typed-macro/blob/master/DOCUMENTATION.md).**\n\n# Guide\n\n### Define your macro\n\nIt's pretty easy to define a macro, as long as you know the\n[basic principles of AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) and [basic operation APIs of Babel](https://github.com/jamiebuilds/babel-handbook).\n\n```typescript\nimport { defineMacro } from '@typed-macro/core'\n\nconst echoMacro = defineMacro('echo') // macro builder\n  // give macro a function signature\n  .withSignature('(msg: Message, repeat?: number): void')\n  // custom type will be rendered to the final d.ts file with signatures\n  .withCustomType(`export type Message = string`)\n  // set the handler for macro\n  .withHandler(({ path, args }, { template, types }) => {\n    // you can throw errors directly; the error message with the row number and col number\n    // of the macro call currently being expanded will be in the terminal.\n    // so you don't have to worry about telling users where the wrong code is.\n    if (args.length === 0) throw new Error('empty arguments is invalid')\n    const firstArg = args[0]\n    if (!firstArg.isStringLiteral())\n      throw new Error('please use literal string as message')\n    const msg = firstArg.node.value\n\n    let repeat = 5\n    if (args.length > 1) {\n      const secondArg = args[1]\n      if (!secondArg.isNumericLiteral())\n        throw new Error('please use literal number as repeat')\n      repeat = secondArg.node.value\n    }\n\n    path.replaceWith(\n      template.statement.ast(`console.log(\"${msg.repeat(repeat)}\")`)\n    )\n  })\n```\n\n_The above example is **JUST** to show how to define multiple signatures.\nThe above scenario is more suitable for using optional parameters\nrather than overloading. See [Do's and Don'ts](https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html#use-optional-parameters)._\n\nAs the above example shows, you should give a name, at least one signature,\nmaybe with a comment, and a handler function to a macro.\nThe custom type is optional.\n\nIdeally, macros should be transparent to users;\nthat is, users can use macros like normal functions.\nSo it's essential to write types/comments correctly to provide a friendly development experience.\n\nA macro handler receives three arguments: `ctx`, `babel`, and `helper`.\n\n- `ctx` - the transformation context, including the [node path](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#paths) of\n  the call expression currently being processed, traversal states, argument nodes, and so on.\n- `babel` - a collection of Babel tools, containing\n  [@babel/types](https://babeljs.io/docs/en/babel-types),\n  [@babel/traverse](https://babeljs.io/docs/en/babel-traverse),\n  [@babel/parser](https://babeljs.io/docs/en/babel-parser),\n  [@babel/template](https://babeljs.io/docs/en/babel-template).\n- `helper` - some functions that wrap Babel tools to make writing macro handlers easier.\n\nIn order to handle nested macros correctly,\nand reduce the conflict on modifying the AST,\n**you can't use asynchronous macro handlers.**\n\nIf the handler is a normal function like the above example shows,\nthe nested macros inside the current call expression will be expanded\nautomatically before calling the handler.\n\nIf the handler is a generator function, you can:\n\n- yield node paths of import statements to collect macros from them,\n  _note that macros must be collected before used, or you should wait for the next traversal\n  because the runtime collects imported macros automatically before every traversal_\n- yield node paths to actively expand macros inside them\n- yield undefined to do nothing 😂\n\ne.g.\n\n```typescript\nconst helloMacro = defineMacro(`hello`)\n  .withSignature(`(msg?: string): void`, `output hello message`)\n  .withHandler(function* (\n    { path, args },\n    { template },\n    { prependImports, appendToBody }\n  ) {\n    // do some thing...\n\n    // expand macros inside the current call expression\n    yield args\n\n    // do some thing...\n\n    // actively collect the imported macro so it can be used immediately,\n    // or you should wait for the next traversal\n    yield prependImports({\n      moduleName: '@other-macros',\n      exportName: 'macro',\n      localName: '__macro',\n    })\n\n    // insert a macro call and expand it\n    yield appendToBody(template.statement.ast(`__macro()`))\n\n    // do some thing..\n  })\n```\n\nThough sometimes writing these lexical macros themselves is cumbersome enough,\nplease always keep the following in mind:\n\n- don't forget to remove or replace the macro call expressions,\n  otherwise the plugin will process this call expression\n  again and again until reach max traversal times\n  because there is always a macro call remaining in the source.\n- If you replace the current call expression with another call expression,\n  the next traversed node will be this new call expression.\n  Therefore, if you replace current macro call expression with another macro call,\n  please make sure this replacement is not recursive.\n\n### Organize your macros\n\nIt is not enough to have defined macros only. Macros should be organized,\nat least, into some `modules` so that users can import them.\n\nThe most basic organizational unit is `Exportable`.\n\nAn `Exportable` contains either **Javascript code** and corresponding types,\nor macros and additional types.\n\n```typescript\ntype Exportable =\n  | { macros: Macro[]; types?: string }\n  | { code: string; types?: string }\n```\n\n_Macro authors often prefer to use external helpers in the expanded code\nin order to reduce the final size.\nSo `Exportable` is designed to be able to contain Javascript code._\n\n`ModularizedExportable` is a collection of `Exportable`s,\nestablishing the mapping relationship between module name and exportable.\n\n```typescript\ntype ModularizedExportable = { [moduleName: string]: Exportable }\n```\n\nFinally `ModularizedExportable`s should be packaged into providers.\n\n```typescript\nimport { defineMacroProvider } from '@typed-macro/core'\n\ndefineMacroProvider({\n  id: 'echo',\n  exports: {\n    '@macros': {\n      macros: [helloMacro],\n      types: `export type SomeThing<T> = T`,\n    },\n    '@helper': {\n      code: `export const n = 1`,\n    },\n  },\n})\n```\n\n`defineMacroProvider` accepts a builder function if needed.\n\n```typescript\nimport { defineMacroProvider } from '@typed-macro/core'\n\ndefineMacroProvider((env) => {\n  return {\n    id: 'test',\n    exports: {\n      '@macros': {\n        macros: [],\n        types: env.dev ? '...' : '...',\n      },\n    },\n    hooks: {\n      onStart() {\n        env.watcher?.add(someFile)\n      },\n    },\n    options: {\n      parserPlugins: ['decimal'],\n    },\n  }\n})\n```\n\nYou can get properties of `env` via parameter `ctx` within macro handler,\nso you don't need to define macros inside provider builder function.\n\n```typescript\ndefineMacro(`test`)\n  .withSignature(`(): void`)\n  .withHandler((ctx) => {\n    ctx.dev // env.dev\n    ctx.ssr // env.ssr\n    ctx.host // env.host\n    // ...\n  })\n```\n\nThere are two special object in `env`: `env.watcher` and `env.modules`.\nSuppose your macro needs to be re-expanded when an external file changes,\nyou can use them like below.\n\n```typescript\n// in macros\nwithHandler((ctx) => {\n  // ...\n  ctx.modules?.setTag(ctx.filepath, 'some_xyz')\n  // ...\n})\n\n// in hooks\n{\n  onStart: () => {\n    env.watcher?.add(someFile)\n    env.watcher?.on('change', (path) => {\n      if (path === someFile) {\n        env.modules?.invalidateByTag(/^some/)\n      }\n    })\n  }\n}\n```\n\nNote that `env.watcher` and `env.modules` may be undefined,\nof which different runtime wrappers may have different strategies.\n\n### Test your macros\n\nSee [@typed-macro/test-utils](https://github.com/typed-macro/typed-macro/blob/master/packages/test-utils/README.md).\n","_id":"@typed-macro/core@1.0.0-alpha.1","dist":{"shasum":"a1e53bda569e48e0d4d640606b0cd3563fbd9178","integrity":"sha512-Io7F9hZVuj5UXBrJBYlEdOThxV0/S3jweJqKs936a4nnXxmePa91EFkSFdtAPMXo76Eyl0748WUPIF131dfciQ==","tarball":"https://registry.npmjs.org/@typed-macro/core/-/core-1.0.0-alpha.1.tgz","fileCount":7,"unpackedSize":41101,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh3/QbCRA9TVsSAnZWagAAgDAP/0WhnjmeqU7gV7QPS/gm\n1Wwp7QJ3Dc557yB5pKJlTBMMShRRVaxMCwaa9M0codRsmIhJHGyLOysQ1Ywi\njwr80WPMl8dqi72LJ9bGTkQH5oi1374/M/NNczi2fbr5Ljc+aFz89MG751Cy\nDYQ9KzOCgzVzGTfgRU8CzTfcsfHojtNNg59k64DbgezeXUfD2gsSl67cHIdw\nqf1kLMhfF5BT4XS+N314sySFJh7QRh7ukORt456DmSeDyRqgIODFxOETbX7F\nWVMTWS72ikM04IOnED0NrIS55AcOFg2+ZGwEfrMeTodahzZDnSkOzMz72Tpu\nOqRHUGIvxnwNm92O+S+2rJDOcRV0vejCBSe9W4KmQYUa1kOIiOxwcCn4JrIw\nDJa7K6p14jjyEXqA8SGxTp3kFTb0nzrNb6a38OwFPIgt9xr+xF8rhEQ1nlhY\nAvRDNNHvubNO891JnvqHoAGZgB8W62aFEIAjbYf3gJHCV9LxXJSIL81Oht8P\nIghY1zOrZjz4x1llKTNmHy9mCMrjKaI5CU723h3JRmYBfDOmIfERTS5ccC8A\n6VS+xXUAQno+Jsh/qCO8r50QohjHfJtHWJ1WrsoJagXIrKZrp6MyI/kkbq3e\ny4auU1F+ksQiMCtxJ2l48RRX9tCB1AXz9BZZKGz84f5ZHABbgam1c5Zkk5H+\nwWgq\r\n=zAKV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC0rd5fFAsLHWFQ+OmdSuK/6OD9rxo755emUNqLAwluLAIgRAPBs8Le2Jkj0iBHcmn+HIf09oo/2oieSiqQIJW1804="}]},"_npmUser":{"name":"unbyte","email":"i@shangyes.net"},"directories":{},"maintainers":[{"name":"unbyte","email":"i@shangyes.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/core_1.0.0-alpha.1_1642066971135_0.6767455691296198"},"_hasShrinkwrap":false}},"time":{"created":"2021-12-17T19:10:31.837Z","1.0.0-alpha":"2021-12-17T19:10:32.101Z","modified":"2022-04-07T08:15:41.916Z","1.0.0-alpha.1":"2022-01-13T09:42:51.293Z"},"maintainers":[{"name":"unbyte","email":"i@shangyes.net"}],"description":"**For basic concepts, see [documentation for typed-macro](https://github.com/typed-macro/typed-macro/blob/master/DOCUMENTATION.md).**","homepage":"https://github.com/typed-macro/typed-macro/tree/master/packages/core#readme","repository":{"type":"git","url":"https://github.com/typed-macro/typed-macro"},"author":{"name":"unbyte","email":"i@shangyes.net"},"bugs":{"url":"https://github.com/typed-macro/typed-macro/issues/new"},"license":"MIT","readme":"","readmeFilename":""}