Skip to content

Import Patterns

Jac Client Import Patterns - Implementation Status

Section titled “Jac Client Import Patterns - Implementation Status”

This document provides a comprehensive reference of all JavaScript/ECMAScript import patterns and their Jac equivalents, showing which patterns are currently supported.

CategoryJavaScript PatternJac PatternStatusGenerated JavaScriptNotes
Category 1: Named Imports
Single namedimport { useState } from 'react'cl import from react { useState }Workingimport { useState } from "react";
Multiple namedimport { map, filter } from 'lodash'cl import from lodash { map, filter }Workingimport { map, filter } from "lodash";
Named with aliasimport { get as httpGet } from 'axios'cl import from axios { get as httpGet }Workingimport { get as httpGet } from "axios";
Mixed named + aliasesimport { createApp, ref as reactive } from 'vue'cl import from vue { createApp, ref as reactive }Workingimport { createApp, ref as reactive } from "vue";
Category 1: Relative Paths
Single dot (current)import { helper } from './utils'cl import from .utils { helper }Workingimport { helper } from "./utils";
Double dot (parent)import { format } from '../lib'cl import from ..lib { format }Workingimport { format } from "../lib";
Triple dot (grandparent)import { settings } from '../../config'cl import from ...config { settings }Workingimport { settings } from "../../config";Supports any number of dots
Category 1: Module Prefix
With jac: prefiximport { renderJsxTree } from 'jac:client_runtime'cl import from jac:client_runtime { renderJsxTree }Workingimport { renderJsxTree } from "client_runtime";Prefix stripped for resolution
Category 1: String Literal Imports
Hyphenated packagesimport { render } from 'react-dom'cl import from "react-dom" { render }Workingimport { render } from "react-dom";Use string literals for package names with hyphens
Multiple hyphensimport { BrowserRouter } from 'react-router-dom'cl import from "react-router-dom" { BrowserRouter }Workingimport { BrowserRouter } from "react-router-dom";Works with any special characters
Category 2: Default Imports
Default importimport React from 'react'cl import from react { default as React }Workingimport React from "react";Must use cl prefix
Default with relativeimport Component from './Button'cl import from .Button { default as Component }Workingimport Component from "./Button";
Category 4: Namespace Imports
Namespace importimport * as React from 'react'cl import from react { * as React }Workingimport * as React from "react";Must use cl prefix
Namespace with relativeimport * as utils from './utils'cl import from .utils { * as utils }Workingimport * as utils from "./utils";
Category 3: Mixed Imports
Default + Namedimport React, { useState } from 'react'cl import from react { default as React, useState }Workingimport React, { useState } from "react";Order matters: default first
Default + Namespaceimport React, * as All from 'react'cl import from react { default as React, * as All }Workingimport React, * as All from "react";Valid JS (rarely used)
Named + Namespaceimport * as _, { map } from 'lodash'cl import from lodash { * as _, map }️ Generatesimport * as _, { map } from "lodash";Invalid JavaScript - not recommended
PatternWhy Not SupportedWorkaround
default or * in non-cl importsNo Python equivalent for default/namespace exportsUse cl import instead
Side-effect only importsNot yet implementedUse regular Python import for now
Dynamic importsRuntime feature, not syntaxUse JavaScript directly or add to roadmap
Import assertions (JSON, CSS)Stage 3 proposal, specializedMay add in future
  • Default imports (default as Name) and namespace imports (* as Name) MUST use cl prefix
  • Named imports work with or without cl prefix (but cl generates JavaScript)
# Correct Usage
cl import from react { useState } # Category 1: Named
cl import from react { default as React } # Category 2: Default
cl import from react { * as React } # Category 4: Namespace
cl import from react { default as React, useState } # Category 3: Mixed
# Incorrect Usage (these would fail parsing or generate invalid JS)
import from react { default as React } # Error: default requires cl
import from lodash { * as _ } # Error: namespace requires cl
cl import from lodash { * as _, map } # Generates invalid JS

3. String Literal Imports for Special Characters

Section titled “3. String Literal Imports for Special Characters”

For package names containing special characters (hyphens, @-scopes, etc.), use string literals:

# Correct Usage - String literals for hyphenated packages
cl import from "react-dom" { render }
cl import from "styled-components" { default as styled }
cl import from "react-router-dom" { BrowserRouter, Route }
cl import from "date-fns" { format, parse }
# Incorrect Usage - Without quotes (would fail parsing)
cl import from react-dom { render } # Error: hyphen not allowed in identifier

When to use string literals:

  • Package names with hyphens: react-dom, styled-components, react-router-dom, date-fns
  • Package names with special characters that aren’t valid in identifiers
  • Any package name that would cause a syntax error without quotes

Note: String literals work with all import types (named, default, namespace, mixed)

Jac uses Python-style dots for relative imports, which are automatically converted to JavaScript format:

Jac SyntaxJavaScript OutputDescription
.utils"./utils"Current directory
..lib"../lib"Parent directory
...config"../../config"Grandparent directory
....deep"../../../deep"Great-grandparent directory
import_path: (NAME COLON)? (dotted_name | STRING) (KW_AS NAME)?
import_item: (KW_DEFAULT | STAR_MUL | named_ref) (KW_AS NAME)?
  • Regular named imports: ModuleItem.name is Name
  • Default imports: ModuleItem.name is Token(KW_DEFAULT)
  • Namespace imports: ModuleItem.name is Token(STAR_MUL)
  • String literal imports: ModulePath.path contains a single String node
  • pyast_gen_pass.py:
    • Logs error if default or * used without cl
    • Logs error if string literal imports used without cl (Python doesn’t support string literal module names)
  • sym_tab_build_pass.py: Only alias added to symbol table for default/namespace; skips symbol creation for String paths
  • esast_gen_pass.py: Generates appropriate ImportSpecifier, ImportDefaultSpecifier, or ImportNamespaceSpecifier
  • parser.py: Handles both dotted_name (list of Names) and STRING in import paths
  • unitree.py: ModulePath.dot_path_str extracts string value from String literals

All patterns tested and verified in:

  • test_js_generation.py::test_category1_named_imports_generate_correct_js
  • test_js_generation.py::test_category2_default_imports_generate_correct_js
  • test_js_generation.py::test_category4_namespace_imports_generate_correct_js
  • test_js_generation.py::test_hyphenated_package_imports_generate_correct_js
  • test_pyast_gen_pass.py::test_string_literal_import_requires_cl
  • test_pyast_gen_pass.py::test_string_literal_import_works_with_cl
cl {
# Named imports
import from react { useEffect, useRef }
import from lodash { map as mapArray, filter }
# Default imports
import from react { default as React }
import from axios { default as axios }
# Namespace imports
import from "date-fns" { * as DateFns }
import from .utils { * as Utils }
# String literal imports (for hyphenated packages)
import from "react-dom" { render, hydrate }
import from "styled-components" { default as styled }
import from "react-router-dom" { BrowserRouter, Route }
# Mixed imports
import from react { default as React, useEffect }
# Relative paths
import from .components.Button { default as Button }
import from ..lib.helpers { formatDate }
import from ...config.constants { API_URL }
def MyComponent() {
# Reactive state - auto-generates useState
has count: int = 0;
now = DateFns.format(Date.now());
axios.get(API_URL);
return count;
}
}

Note: Inside cl {} blocks and .cl.jac files, use has variables for reactive state instead of explicit useState calls. The compiler automatically generates const [count, setCount] = useState(0);, auto-injects the useState import from @jac-client/utils, and transforms assignments to setter calls.

import { useState } from "@jac-client/utils"; // Auto-injected for `has` variables
import { useEffect, useRef } from "react";
import { map as mapArray, filter } from "lodash";
import React from "react";
import axios from "axios";
import * as DateFns from "date-fns";
import * as Utils from "./utils";
import { render, hydrate } from "react-dom";
import styled from "styled-components";
import { BrowserRouter, Route } from "react-router-dom";
import React, { useEffect } from "react";
import Button from "./components.Button";
import { formatDate } from "../lib.helpers";
import { API_URL } from "../../config.constants";
function MyComponent() {
// Generated from `has count: int = 0;` (useState import auto-injected from @jac-client/utils)
const [count, setCount] = useState(0);
now = DateFns.format(Date.now());
axios.get(API_URL);
return count;
}
  • Category 1 (Named Imports): Fully implemented and tested
  • Category 2 (Default Imports): Fully implemented and tested
  • Category 3 (Mixed Imports): Working for default+named and default+namespace
  • Category 4 (Namespace Imports): Fully implemented and tested
  • Relative Paths: Full support with automatic conversion
  • String Literal Imports: Full support for hyphenated package names (react-dom, styled-components, etc.)
  • Named + Namespace Mix: Generates but produces invalid JavaScript

Last Updated: 2025-10-23