conjure-js 0.0.12 → 0.0.13

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.
Files changed (77) hide show
  1. package/dist-cli/conjure-js.mjs +9360 -5298
  2. package/dist-vite-plugin/index.mjs +9463 -5185
  3. package/package.json +3 -1
  4. package/src/bin/cli.ts +2 -2
  5. package/src/bin/nrepl-symbol.ts +150 -0
  6. package/src/bin/nrepl.ts +289 -167
  7. package/src/bin/version.ts +1 -1
  8. package/src/clojure/core.clj +757 -29
  9. package/src/clojure/core.clj.d.ts +75 -131
  10. package/src/clojure/generated/builtin-namespace-registry.ts +4 -0
  11. package/src/clojure/generated/clojure-core-source.ts +758 -29
  12. package/src/clojure/generated/clojure-set-source.ts +136 -0
  13. package/src/clojure/generated/clojure-walk-source.ts +72 -0
  14. package/src/clojure/set.clj +132 -0
  15. package/src/clojure/set.clj.d.ts +20 -0
  16. package/src/clojure/string.clj.d.ts +14 -0
  17. package/src/clojure/walk.clj +68 -0
  18. package/src/clojure/walk.clj.d.ts +7 -0
  19. package/src/core/assertions.ts +114 -6
  20. package/src/core/bootstrap.ts +337 -0
  21. package/src/core/conversions.ts +48 -31
  22. package/src/core/core-module.ts +303 -0
  23. package/src/core/env.ts +20 -6
  24. package/src/core/evaluator/apply.ts +40 -25
  25. package/src/core/evaluator/arity.ts +8 -8
  26. package/src/core/evaluator/async-evaluator.ts +565 -0
  27. package/src/core/evaluator/collections.ts +28 -5
  28. package/src/core/evaluator/destructure.ts +180 -69
  29. package/src/core/evaluator/dispatch.ts +12 -14
  30. package/src/core/evaluator/evaluate.ts +22 -20
  31. package/src/core/evaluator/expand.ts +45 -15
  32. package/src/core/evaluator/form-parsers.ts +178 -0
  33. package/src/core/evaluator/index.ts +7 -9
  34. package/src/core/evaluator/js-interop.ts +189 -0
  35. package/src/core/evaluator/quasiquote.ts +14 -8
  36. package/src/core/evaluator/recur-check.ts +6 -6
  37. package/src/core/evaluator/special-forms.ts +234 -191
  38. package/src/core/factories.ts +182 -3
  39. package/src/core/index.ts +54 -4
  40. package/src/core/module.ts +136 -0
  41. package/src/core/ns-forms.ts +107 -0
  42. package/src/core/printer.ts +371 -11
  43. package/src/core/reader.ts +84 -33
  44. package/src/core/registry.ts +209 -0
  45. package/src/core/runtime.ts +376 -0
  46. package/src/core/session.ts +253 -487
  47. package/src/core/stdlib/arithmetic.ts +528 -194
  48. package/src/core/stdlib/async-fns.ts +132 -0
  49. package/src/core/stdlib/atoms.ts +291 -56
  50. package/src/core/stdlib/errors.ts +54 -50
  51. package/src/core/stdlib/hof.ts +82 -166
  52. package/src/core/stdlib/js-namespace.ts +344 -0
  53. package/src/core/stdlib/lazy.ts +34 -0
  54. package/src/core/stdlib/maps-sets.ts +322 -0
  55. package/src/core/stdlib/meta.ts +61 -30
  56. package/src/core/stdlib/predicates.ts +325 -187
  57. package/src/core/stdlib/regex.ts +126 -98
  58. package/src/core/stdlib/seq.ts +564 -0
  59. package/src/core/stdlib/strings.ts +164 -135
  60. package/src/core/stdlib/transducers.ts +95 -100
  61. package/src/core/stdlib/utils.ts +292 -130
  62. package/src/core/stdlib/vars.ts +27 -27
  63. package/src/core/stdlib/vectors.ts +122 -0
  64. package/src/core/tokenizer.ts +2 -2
  65. package/src/core/transformations.ts +117 -9
  66. package/src/core/types.ts +98 -2
  67. package/src/host/node-host-module.ts +74 -0
  68. package/src/{vite-plugin-clj/nrepl-relay.ts → nrepl/relay.ts} +72 -11
  69. package/src/vite-plugin-clj/codegen.ts +87 -95
  70. package/src/vite-plugin-clj/index.ts +178 -23
  71. package/src/vite-plugin-clj/namespace-utils.ts +39 -0
  72. package/src/vite-plugin-clj/static-analysis.ts +211 -0
  73. package/src/clojure/demo.clj +0 -72
  74. package/src/clojure/demo.clj.d.ts +0 -0
  75. package/src/core/core-env.ts +0 -61
  76. package/src/core/stdlib/collections.ts +0 -739
  77. package/src/host/node.ts +0 -55
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "conjure-js",
3
3
  "private": false,
4
- "version": "0.0.12",
4
+ "version": "0.0.13",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -12,6 +12,7 @@
12
12
  "license": "MIT",
13
13
  "exports": {
14
14
  ".": "./src/core/index.ts",
15
+ "./nrepl": "./src/bin/nrepl.ts",
15
16
  "./vite-plugin": {
16
17
  "bun": "./src/vite-plugin-clj/index.ts",
17
18
  "default": "./dist-vite-plugin/index.mjs"
@@ -48,6 +49,7 @@
48
49
  "build-cli": "node scripts/gen-version.mjs && bun build --compile src/bin/cli.ts --outfile conjure-js",
49
50
  "build-npm-bin": "node scripts/gen-version.mjs && node scripts/build-npm-bin.mjs",
50
51
  "build-vite-plugin": "node scripts/build-vite-plugin.mjs",
52
+ "prepublishOnly": "bun run gen:core-source && node scripts/build-vite-plugin.mjs",
51
53
  "typecheck": "tsc --noEmit",
52
54
  "test": "vitest",
53
55
  "gen:core-source": "bun run scripts/gen-core-source.mjs",
package/src/bin/cli.ts CHANGED
@@ -12,7 +12,7 @@ import { extractNsName } from '../vite-plugin-clj/namespace-utils'
12
12
  import { inferSourceRoot, discoverSourceRoots } from './nrepl-utils'
13
13
  import { startNreplServer } from './nrepl'
14
14
  import { VERSION } from './version'
15
- import { injectNodeHostFunctions } from '../host/node'
15
+ import { makeNodeHostModule } from '../host/node-host-module'
16
16
 
17
17
  type CliIo = {
18
18
  writeLine: (text: string) => void
@@ -32,7 +32,7 @@ export function createCliSession(sourceRoots: string[], io: CliIo): Session {
32
32
  sourceRoots,
33
33
  readFile: (filePath) => readFileSync(filePath, 'utf8'),
34
34
  })
35
- injectNodeHostFunctions(session)
35
+ session.runtime.installModules([makeNodeHostModule(session)])
36
36
  return session
37
37
  }
38
38
 
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Shared symbol resolution and metadata extraction for nREPL ops.
3
+ * Used by both the standalone nREPL server (nrepl.ts) and the browser relay
4
+ * (nrepl-relay.ts) so info/eldoc/lookup work identically in both transports.
5
+ */
6
+ import { tryLookup, lookupVar, getNamespaceEnv } from '../core/env'
7
+ import { printString } from '../core/printer'
8
+ import type { CljMap, CljValue, CljVar, Session } from '../core'
9
+
10
+ export type ResolvedSymbol = {
11
+ value: CljValue
12
+ resolvedNs: string
13
+ localName: string
14
+ /** The raw CljVar for this symbol, if one exists. Its meta holds :doc/:arglists/:line/:column/:file. */
15
+ varObj?: CljVar
16
+ }
17
+
18
+ export type ExtractedMeta = {
19
+ doc: string
20
+ arglistsStr: string
21
+ eldocArgs: string[][] | null
22
+ type: string
23
+ }
24
+
25
+ /**
26
+ * Resolve a symbol string in the context of a session.
27
+ * Handles qualified symbols (ns/name, alias/name) and unqualified symbols.
28
+ * Returns null if the symbol cannot be resolved.
29
+ */
30
+ export function resolveSymbol(
31
+ sym: string,
32
+ session: Session,
33
+ contextNs?: string
34
+ ): ResolvedSymbol | null {
35
+ const ns = contextNs ?? session.currentNs
36
+ const slashIdx = sym.indexOf('/')
37
+
38
+ if (slashIdx > 0) {
39
+ const qualifier = sym.slice(0, slashIdx)
40
+ const localName = sym.slice(slashIdx + 1)
41
+
42
+ // 1. Try as full namespace name
43
+ const nsEnvFull = session.registry.get(qualifier)
44
+ if (nsEnvFull) {
45
+ const value = tryLookup(localName, nsEnvFull)
46
+ if (value !== undefined) {
47
+ const varObj = lookupVar(localName, nsEnvFull)
48
+ return { value, resolvedNs: qualifier, localName, varObj }
49
+ }
50
+ }
51
+
52
+ // 2. Try as alias (:as str → clojure.string)
53
+ const currentNsData = session.getNs(ns)
54
+ const aliasedNs = currentNsData?.aliases.get(qualifier)
55
+ if (aliasedNs) {
56
+ const varObj = aliasedNs.vars.get(localName)
57
+ if (varObj !== undefined)
58
+ return { value: varObj.value, resolvedNs: aliasedNs.name, localName, varObj }
59
+ }
60
+
61
+ return null
62
+ }
63
+
64
+ // Unqualified symbol
65
+ const localName = sym
66
+ const nsEnvFull = session.registry.get(ns)
67
+ if (!nsEnvFull) return null
68
+ const value = tryLookup(sym, nsEnvFull)
69
+ if (value === undefined) return null
70
+
71
+ // Determine the namespace where this symbol is defined.
72
+ const varObj = lookupVar(sym, nsEnvFull)
73
+ let resolvedNs: string
74
+ if (varObj) {
75
+ resolvedNs = varObj.ns
76
+ } else if (value.kind === 'function' || value.kind === 'macro') {
77
+ resolvedNs = getNamespaceEnv(value.env).ns?.name ?? ns
78
+ } else if (value.kind === 'native-function') {
79
+ const i = value.name.indexOf('/')
80
+ resolvedNs = i > 0 ? value.name.slice(0, i) : ns
81
+ } else {
82
+ resolvedNs = ns
83
+ }
84
+
85
+ return { value, resolvedNs, localName, varObj }
86
+ }
87
+
88
+ /**
89
+ * Extract documentation, arglists, and eldoc args from a resolved CljValue.
90
+ * Pass `varMeta` (from the CljVar that holds the value) to get :doc/:arglists
91
+ * stored on the var rather than on the value itself.
92
+ */
93
+ export function extractMeta(value: CljValue, varMeta?: CljMap): ExtractedMeta {
94
+ const type =
95
+ value.kind === 'macro'
96
+ ? 'macro'
97
+ : value.kind === 'function' || value.kind === 'native-function'
98
+ ? 'function'
99
+ : 'var'
100
+
101
+ // Prefer var-level metadata (canonical location for :doc/:arglists after the
102
+ // metadata-on-vars refactor). Fall back to value-level meta for backward compat.
103
+ const meta: CljMap | undefined =
104
+ varMeta ??
105
+ (value.kind === 'function'
106
+ ? value.meta
107
+ : value.kind === 'native-function'
108
+ ? value.meta
109
+ : undefined)
110
+
111
+ let doc = ''
112
+ let arglistsStr = ''
113
+ let eldocArgs: string[][] | null = null
114
+
115
+ if (meta) {
116
+ const docEntry = meta.entries.find(
117
+ ([k]) => k.kind === 'keyword' && k.name === ':doc'
118
+ )
119
+ if (docEntry && docEntry[1].kind === 'string') doc = docEntry[1].value
120
+
121
+ const argsEntry = meta.entries.find(
122
+ ([k]) => k.kind === 'keyword' && k.name === ':arglists'
123
+ )
124
+ if (argsEntry && argsEntry[1].kind === 'vector') {
125
+ const arglists = argsEntry[1]
126
+ arglistsStr = '(' + arglists.value.map((al) => printString(al)).join(' ') + ')'
127
+ eldocArgs = arglists.value.map((al) => {
128
+ if (al.kind !== 'vector') return [printString(al)]
129
+ return al.value.map((p) => (p.kind === 'symbol' ? p.name : printString(p)))
130
+ })
131
+ }
132
+ }
133
+
134
+ // Fallback: derive arglists from structural arities (fn/macro without meta)
135
+ if (arglistsStr === '' && (value.kind === 'function' || value.kind === 'macro')) {
136
+ const arityStrs = value.arities.map((arity) => {
137
+ const params = arity.params.map((p) => printString(p))
138
+ if (arity.restParam) params.push('&', printString(arity.restParam))
139
+ return '[' + params.join(' ') + ']'
140
+ })
141
+ arglistsStr = '(' + arityStrs.join(' ') + ')'
142
+ eldocArgs = value.arities.map((arity) => {
143
+ const params = arity.params.map((p) => printString(p))
144
+ if (arity.restParam) params.push('&', printString(arity.restParam))
145
+ return params
146
+ })
147
+ }
148
+
149
+ return { doc, arglistsStr, eldocArgs, type }
150
+ }