yuku-ast 0.1.1 → 0.1.3

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
@@ -6,6 +6,7 @@ node builders, type guards, a walker, and identifier validators. No runtime depe
6
6
  | Import | Provides |
7
7
  | --------------------- | ------------------------------------------------------------ |
8
8
  | `yuku-ast` | `walk`, `walkAsync`, `b` (node builders), `is` (type guards) |
9
+ | `yuku-ast/utils` | node utilities such as `nameOf` |
9
10
  | `yuku-ast/identifier` | identifier and reserved-word validators |
10
11
 
11
12
  ```ts
@@ -114,6 +115,9 @@ is.StringLiteral(node); // Literal variants
114
115
  is.StaticMemberExpression(node); // MemberExpression variants
115
116
  is.BindingIdentifier(node); // Identifier roles, via `kind`
116
117
 
118
+ is.Identifier(node, "this"); // an Identifier with that exact name
119
+ is.oneOf(node, ["CallExpression", "NewExpression"]); // any of these types
120
+
117
121
  walk(program, {
118
122
  Literal(node, path) {
119
123
  if (is.ArrayExpression(path.parent)) {
@@ -123,6 +127,32 @@ walk(program, {
123
127
  });
124
128
  ```
125
129
 
130
+ `is.oneOf(node, types)` narrows to the union of the listed types, and
131
+ `is.Identifier(node, name?)` narrows to `Identifier`. Both accept `null` or
132
+ `undefined`.
133
+
134
+ ## Reading names (`nameOf`)
135
+
136
+ `nameOf(node)` returns the static name a node denotes, an `Identifier`'s `name`
137
+ or a string `Literal`'s `value`, and `null` for anything else (including `null`
138
+ or `undefined`). It reads the common `Identifier | StringLiteral` slots, such as
139
+ a `ModuleExportName` or a static property or member key, in one call.
140
+
141
+ ```ts
142
+ import { walk } from "yuku-ast";
143
+ import { nameOf } from "yuku-ast/utils";
144
+
145
+ walk(program, {
146
+ ExportSpecifier(node) {
147
+ // `export { x as y }` and `export { x as "z" }` both resolve.
148
+ nameOf(node.exported); // "y", "z"
149
+ },
150
+ Property(node) {
151
+ if (!node.computed) nameOf(node.key); // static key name, else null
152
+ },
153
+ });
154
+ ```
155
+
126
156
  ## Builders (`b`)
127
157
 
128
158
  A builder for every node type. Required fields are positional, the rest go in a
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as t from "yuku-parser";
2
- import { BigIntLiteral, BindingIdentifier, BooleanLiteral, ComputedMemberExpression, Directive, IdentifierName, IdentifierReference, LabelIdentifier, Node, NullLiteral, NumericLiteral, PrivateFieldExpression, RegExpLiteral, StaticMemberExpression, StringLiteral } from "yuku-parser";
2
+ import { BigIntLiteral, BindingIdentifier, BooleanLiteral, ComputedMemberExpression, Directive, Identifier, IdentifierName, IdentifierReference, LabelIdentifier, Node, NullLiteral, NumericLiteral, PrivateFieldExpression, RegExpLiteral, StaticMemberExpression, StringLiteral } from "yuku-parser";
3
3
 
4
4
  //#region src/types.d.ts
5
5
  /** Discriminant `type` string of every AST node. */
@@ -95,6 +95,8 @@ type AliasMap = { [K in AliasName]: NodeOfType<(typeof ALIAS_GROUPS)[K][number]>
95
95
  //#region src/predicates.d.ts
96
96
  type MaybeNode = Node | null | undefined;
97
97
  declare const is: {
98
+ /** True when `node`'s `type` is one of `types`, narrowing to that union. */oneOf: <const K extends NodeType>(node: MaybeNode, types: readonly K[]) => node is NodeOfType<K>; /** An `Identifier`, optionally with the exact `name` (e.g. `is.Identifier(node, "this")`). */
99
+ Identifier: (node: MaybeNode, name?: string) => node is Identifier;
98
100
  Expression: (node: MaybeNode) => node is NodeOfType<"Identifier" | "Literal" | "ThisExpression" | "Super" | "ArrayExpression" | "ObjectExpression" | "FunctionExpression" | "ArrowFunctionExpression" | "ClassExpression" | "TaggedTemplateExpression" | "TemplateLiteral" | "MemberExpression" | "CallExpression" | "NewExpression" | "ChainExpression" | "SequenceExpression" | "ParenthesizedExpression" | "BinaryExpression" | "LogicalExpression" | "ConditionalExpression" | "UnaryExpression" | "UpdateExpression" | "AssignmentExpression" | "YieldExpression" | "AwaitExpression" | "ImportExpression" | "MetaProperty" | "TSAsExpression" | "TSSatisfiesExpression" | "TSTypeAssertion" | "TSNonNullExpression" | "TSInstantiationExpression" | "JSXElement" | "JSXFragment">;
99
101
  Statement: (node: MaybeNode) => node is AliasMap["Statement"];
100
102
  Declaration: (node: MaybeNode) => node is AliasMap["Declaration"];
@@ -122,7 +124,6 @@ declare const is: {
122
124
  Directive: (node: MaybeNode) => node is Directive;
123
125
  TSTypeAnnotation: (node: MaybeNode) => node is import("yuku-parser").TSTypeAnnotation;
124
126
  Decorator: (node: MaybeNode) => node is import("yuku-parser").Decorator;
125
- Identifier: (node: MaybeNode) => node is import("yuku-parser").Identifier;
126
127
  PrivateIdentifier: (node: MaybeNode) => node is import("yuku-parser").PrivateIdentifier;
127
128
  Literal: (node: MaybeNode) => node is NodeOfType<"Literal">;
128
129
  TemplateElement: (node: MaybeNode) => node is import("yuku-parser").TemplateElement;
package/dist/index.mjs CHANGED
@@ -548,6 +548,10 @@ function aliasGuard(name) {
548
548
  }
549
549
  const is = {
550
550
  ...Object.fromEntries(Object.keys(VISITOR_KEYS).map((type) => [type, (node) => node != null && node.type === type])),
551
+ /** True when `node`'s `type` is one of `types`, narrowing to that union. */
552
+ oneOf: (node, types) => node != null && types.includes(node.type),
553
+ /** An `Identifier`, optionally with the exact `name` (e.g. `is.Identifier(node, "this")`). */
554
+ Identifier: (node, name) => node?.type === "Identifier" && (name === void 0 || node.name === name),
551
555
  Expression: aliasGuard("Expression"),
552
556
  Statement: aliasGuard("Statement"),
553
557
  Declaration: aliasGuard("Declaration"),
@@ -0,0 +1,18 @@
1
+ import { Node } from "yuku-parser";
2
+
3
+ //#region src/utils/index.d.ts
4
+ type MaybeNode = Node | null | undefined;
5
+ /**
6
+ * The static name a node denotes: an `Identifier`'s `name`, or a string
7
+ * `Literal`'s `value`. Returns `null` for anything else, and for `null` or
8
+ * `undefined`, so the common `Identifier | StringLiteral` name slots (a
9
+ * `ModuleExportName`, or a static property or member key) read in one call.
10
+ *
11
+ * @example
12
+ * nameOf(b.identifier("x")) // "x"
13
+ * nameOf(b.stringLiteral("y")) // "y"
14
+ * nameOf(b.numericLiteral(1)) // null
15
+ */
16
+ declare function nameOf(node: MaybeNode): string | null;
17
+ //#endregion
18
+ export { nameOf };
package/dist/utils.mjs ADDED
@@ -0,0 +1,20 @@
1
+ //#region src/utils/index.ts
2
+ /**
3
+ * The static name a node denotes: an `Identifier`'s `name`, or a string
4
+ * `Literal`'s `value`. Returns `null` for anything else, and for `null` or
5
+ * `undefined`, so the common `Identifier | StringLiteral` name slots (a
6
+ * `ModuleExportName`, or a static property or member key) read in one call.
7
+ *
8
+ * @example
9
+ * nameOf(b.identifier("x")) // "x"
10
+ * nameOf(b.stringLiteral("y")) // "y"
11
+ * nameOf(b.numericLiteral(1)) // null
12
+ */
13
+ function nameOf(node) {
14
+ if (node == null) return null;
15
+ if (node.type === "Identifier") return node.name;
16
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
17
+ return null;
18
+ }
19
+ //#endregion
20
+ export { nameOf };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yuku-ast",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "A fast, typed AST toolkit for yuku-parser's ESTree / TypeScript-ESTree AST: node builders, type guards, a walker, and identifier validators.",
5
5
  "keywords": [
6
6
  "ast",
@@ -30,6 +30,7 @@
30
30
  "exports": {
31
31
  ".": "./dist/index.mjs",
32
32
  "./identifier": "./dist/identifier.mjs",
33
+ "./utils": "./dist/utils.mjs",
33
34
  "./package.json": "./package.json"
34
35
  },
35
36
  "scripts": {