inai-react-components 1.5.0 → 1.5.2
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/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +89 -13
- package/dist/index.js +1 -1
- package/dist/utils/paths.d.ts +34 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +54 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,iBAAiB,EAEtB,KAAK,kBAAkB,EAExB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,iBAAiB,EAEtB,KAAK,kBAAkB,EAExB,MAAM,aAAa,CAAC;AAwBrB,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kEAAkE;IAClE,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAChD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAsCA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE;IAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAAC,SAAS,EAAE,iBAAiB,EAAE,CAAA;CAAE,EAC1G,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,iBAAiB,GAAG,IAAI,CAc1B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,iBAAiB,EAC5B,cAAc,EAAE,kBAAkB,GACjC,MAAM,CAiBR;AAgUD,wBAAsB,MAAM,CAC1B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,SAAS,CAAC,CAmMpB;AAqCD,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,UAAU,CAC9B,aAAa,CAAC,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAqIf"}
|
package/dist/commands/add.js
CHANGED
|
@@ -10,7 +10,7 @@ import { saveSnapshot, sha256, } from "../utils/snapshot.js";
|
|
|
10
10
|
import { fuzzySearchNames } from "../utils/fuzzy-search.js";
|
|
11
11
|
import { normalizeThemeCss, getLocalTailwindCssTemplate, getLegacyTailwindCssTemplate, } from "./init.js";
|
|
12
12
|
import { autoInstallDeps } from "../utils/auto-install.js";
|
|
13
|
-
import { resolveLocalDir, getSourceRoot } from "../utils/paths.js";
|
|
13
|
+
import { resolveLocalDir, getSourceRoot, rewriteCompanyUiImports, } from "../utils/paths.js";
|
|
14
14
|
/**
|
|
15
15
|
* Parse a component spec into its registry namespace, type prefix and name.
|
|
16
16
|
*
|
|
@@ -107,10 +107,19 @@ async function installOne(component, registry, componentsJson, registryDir, root
|
|
|
107
107
|
const baseTargetDir = getTargetDir(component, componentsJson);
|
|
108
108
|
const isMultiFile = component.type === "block" || component.type === "template";
|
|
109
109
|
const targetDir = isMultiFile ? path.join(baseTargetDir, name) : baseTargetDir;
|
|
110
|
-
//
|
|
111
|
-
// component's internal subdirectory structure
|
|
112
|
-
//
|
|
110
|
+
// Prefixes used by source files. Stripping them preserves each
|
|
111
|
+
// component/block's internal subdirectory structure.
|
|
112
|
+
//
|
|
113
|
+
// Components: `packages/ui/src/<name>.tsx` and
|
|
114
|
+
// `packages/ui/src/<name>/sub.tsx` → strip `packages/ui/src/`
|
|
115
|
+
// so compound subdirs (`data-table/`) land as-is under
|
|
116
|
+
// `<componentDir>/`.
|
|
117
|
+
//
|
|
118
|
+
// Blocks/templates: `apps/docs/src/registry/blocks/<name>/**` → strip
|
|
119
|
+
// `apps/docs/src/registry/blocks/<name>/` so nested `parts/`
|
|
120
|
+
// subfolders are preserved under `<blocksDir>/<name>/`.
|
|
113
121
|
const UI_PREFIX = "packages/ui/src/";
|
|
122
|
+
const BLOCK_PREFIX = `apps/docs/src/registry/blocks/${name}/`;
|
|
114
123
|
const copiedFiles = [];
|
|
115
124
|
const skippedFiles = [];
|
|
116
125
|
// Track captured content for the snapshot (only for files that were
|
|
@@ -118,19 +127,19 @@ async function installOne(component, registry, componentsJson, registryDir, root
|
|
|
118
127
|
const capturedFiles = {};
|
|
119
128
|
for (const filePath of component.files) {
|
|
120
129
|
const registryFilePath = path.join(registryDir, filePath);
|
|
121
|
-
// Destination path relative to `targetDir
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
// like `data-table` keep their internal `data-table/` subfolder.
|
|
130
|
+
// Destination path relative to `targetDir`. The prefix stripping
|
|
131
|
+
// preserves intra-component directory structure (compound subdirs,
|
|
132
|
+
// blocks' `parts/` folders, etc.). Flattening to basename here was
|
|
133
|
+
// the cause of broken `./parts/*` and `../data` imports in templates.
|
|
126
134
|
let destRel;
|
|
127
|
-
if (isMultiFile) {
|
|
128
|
-
destRel =
|
|
135
|
+
if (isMultiFile && filePath.startsWith(BLOCK_PREFIX)) {
|
|
136
|
+
destRel = filePath.slice(BLOCK_PREFIX.length);
|
|
129
137
|
}
|
|
130
|
-
else if (filePath.startsWith(UI_PREFIX)) {
|
|
138
|
+
else if (!isMultiFile && filePath.startsWith(UI_PREFIX)) {
|
|
131
139
|
destRel = filePath.slice(UI_PREFIX.length);
|
|
132
140
|
}
|
|
133
141
|
else {
|
|
142
|
+
// Fallback for legacy registry entries without the expected prefix.
|
|
134
143
|
destRel = path.basename(filePath);
|
|
135
144
|
}
|
|
136
145
|
const localFilePath = path.join(rootDir, targetDir, destRel);
|
|
@@ -163,7 +172,14 @@ async function installOne(component, registry, componentsJson, registryDir, root
|
|
|
163
172
|
throw new Error(`File "${path.relative(rootDir, localFilePath)}" already exists. Use --force to overwrite or --skip-existing to ignore (stdin is not a TTY, cannot prompt).`);
|
|
164
173
|
}
|
|
165
174
|
}
|
|
166
|
-
|
|
175
|
+
let content = fs.readFileSync(registryFilePath, "utf-8");
|
|
176
|
+
// Blocks and templates reference sibling components via
|
|
177
|
+
// `from "@company/ui/<name>"`. Rewrite those to point at the user's
|
|
178
|
+
// locally-installed components using the project's alias prefix, so
|
|
179
|
+
// the block compiles without `@company/ui` being in node_modules.
|
|
180
|
+
if (isMultiFile) {
|
|
181
|
+
content = rewriteCompanyUiImports(content, componentsJson);
|
|
182
|
+
}
|
|
167
183
|
if (options.dryRun) {
|
|
168
184
|
console.log(chalk.dim(` [dry-run] would write ${path.relative(rootDir, localFilePath)}`));
|
|
169
185
|
}
|
|
@@ -241,6 +257,66 @@ async function installOne(component, registry, componentsJson, registryDir, root
|
|
|
241
257
|
fs.copyFileSync(src, dest);
|
|
242
258
|
}
|
|
243
259
|
}
|
|
260
|
+
// Some data-heavy blocks (data-table-full, template-admin-dashboard,
|
|
261
|
+
// detail-panel-table, etc.) import from `../../../lib/api-client` and
|
|
262
|
+
// `../../../lib/api-types`, which resolves to `<sourceRoot>/lib/`.
|
|
263
|
+
// These are integration points with the user's backend that can't be
|
|
264
|
+
// shipped as real code — but we can write minimal stubs so the project
|
|
265
|
+
// compiles out of the box. Stubs are only written if the file doesn't
|
|
266
|
+
// already exist; if the user has a real implementation it stays intact.
|
|
267
|
+
const sourceRoot = getSourceRoot(componentsJson);
|
|
268
|
+
const userLibDir = path.join(rootDir, sourceRoot, "lib");
|
|
269
|
+
const stubApiTypes = path.join(userLibDir, "api-types.ts");
|
|
270
|
+
const stubApiClient = path.join(userLibDir, "api-client.ts");
|
|
271
|
+
if (!fs.existsSync(stubApiTypes) && !options.dryRun) {
|
|
272
|
+
fs.mkdirSync(userLibDir, { recursive: true });
|
|
273
|
+
fs.writeFileSync(stubApiTypes, `// Stub generated by inai-react-components. Replace with your real API types.
|
|
274
|
+
// These types satisfy the shape expected by data-heavy blocks
|
|
275
|
+
// (data-table-full, template-admin-dashboard, detail-panel-table, ...).
|
|
276
|
+
// If you already have a typed API layer, delete this file and point the
|
|
277
|
+
// block imports at your own module instead.
|
|
278
|
+
|
|
279
|
+
export interface PaginationMeta {
|
|
280
|
+
totalRows: number;
|
|
281
|
+
totalPages: number;
|
|
282
|
+
page: number;
|
|
283
|
+
pageSize: number;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export interface PaginatedResponse<T> {
|
|
287
|
+
data: T[];
|
|
288
|
+
pagination: PaginationMeta;
|
|
289
|
+
}
|
|
290
|
+
`);
|
|
291
|
+
}
|
|
292
|
+
if (!fs.existsSync(stubApiClient) && !options.dryRun) {
|
|
293
|
+
fs.mkdirSync(userLibDir, { recursive: true });
|
|
294
|
+
fs.writeFileSync(stubApiClient, `// Stub generated by inai-react-components. Replace with your real API client.
|
|
295
|
+
// Data-heavy blocks call \`fetchPaginated\` and \`downloadCsv\` at runtime.
|
|
296
|
+
// Without a real implementation the app will throw when you interact with
|
|
297
|
+
// those features — wire these up to your backend (fetch, tRPC, REST, etc.).
|
|
298
|
+
|
|
299
|
+
import type { PaginatedResponse } from "./api-types.js";
|
|
300
|
+
|
|
301
|
+
export async function fetchPaginated<T>(
|
|
302
|
+
endpoint: string,
|
|
303
|
+
_params: Record<string, unknown>
|
|
304
|
+
): Promise<PaginatedResponse<T>> {
|
|
305
|
+
throw new Error(
|
|
306
|
+
\`fetchPaginated stub called for "\${endpoint}". Replace <sourceRoot>/lib/api-client.ts with your real API client.\`
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export async function downloadCsv(
|
|
311
|
+
endpoint: string,
|
|
312
|
+
_params: Record<string, unknown>
|
|
313
|
+
): Promise<void> {
|
|
314
|
+
throw new Error(
|
|
315
|
+
\`downloadCsv stub called for "\${endpoint}". Replace <sourceRoot>/lib/api-client.ts with your real CSV exporter.\`
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
`);
|
|
319
|
+
}
|
|
244
320
|
}
|
|
245
321
|
// Update components.json (skipped in dry-run).
|
|
246
322
|
if (!options.dryRun) {
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ const program = new Command();
|
|
|
17
17
|
program
|
|
18
18
|
.name("inai-ui")
|
|
19
19
|
.description("CLI for InAI UI component library")
|
|
20
|
-
.version("1.5.
|
|
20
|
+
.version("1.5.2");
|
|
21
21
|
program
|
|
22
22
|
.command("init [repo-url]")
|
|
23
23
|
.description("Initialize InAI UI in your project. Optionally pass a Git repo URL to fetch components remotely.")
|
package/dist/utils/paths.d.ts
CHANGED
|
@@ -23,4 +23,38 @@ export declare function resolveLocalDir(alias: string, componentsJson: Pick<Comp
|
|
|
23
23
|
* `components.json` files without a `layout` field.
|
|
24
24
|
*/
|
|
25
25
|
export declare function getSourceRoot(componentsJson: Pick<ComponentsJsonFile, "layout">): string;
|
|
26
|
+
/**
|
|
27
|
+
* Compute the import-alias form of `aliases.components` for use when
|
|
28
|
+
* rewriting `@company/ui/*` imports in block and template files.
|
|
29
|
+
*
|
|
30
|
+
* Rules:
|
|
31
|
+
* 1. If the stored alias already starts with a known alias prefix
|
|
32
|
+
* (`@/`, `~/`, `$/`), return it as-is. Block imports written with
|
|
33
|
+
* this prefix will resolve through the user's `tsconfig.json` paths.
|
|
34
|
+
* 2. Otherwise it's a raw filesystem path (e.g. `app/components/ui`).
|
|
35
|
+
* Strip `layout.sourceRoot` and prepend `layout.aliasPrefix` to
|
|
36
|
+
* produce an alias form (e.g. `~/components/ui`). This matches what
|
|
37
|
+
* the user's tsconfig `paths` maps, so the rewritten imports resolve
|
|
38
|
+
* without needing the user to configure anything extra.
|
|
39
|
+
* 3. If the stored alias doesn't match the layout's sourceRoot, return
|
|
40
|
+
* it as-is (the user may have chosen a non-standard location and we
|
|
41
|
+
* assume their tsconfig handles it).
|
|
42
|
+
*/
|
|
43
|
+
export declare function getComponentsImportAlias(componentsJson: Pick<ComponentsJsonFile, "aliases" | "layout">): string;
|
|
44
|
+
/**
|
|
45
|
+
* Rewrite `@company/ui/*` imports in a block or template file to point
|
|
46
|
+
* at the user's locally-installed components. Without this, block files
|
|
47
|
+
* that `import { Button } from "@company/ui/button"` would fail at
|
|
48
|
+
* compile time because `@company/ui` doesn't exist in the consumer project.
|
|
49
|
+
*
|
|
50
|
+
* Transformations:
|
|
51
|
+
* - `from "@company/ui/data-table"` → `from "~/components/ui/data-table"`
|
|
52
|
+
* - `from "@company/ui/data-table/sub"` → `from "~/components/ui/data-table/sub"`
|
|
53
|
+
* - `from "@company/ui/lib/animations"` → `from "~/components/ui/lib/animations"`
|
|
54
|
+
* - `from "@company/ui"` (bare barrel) → no rewrite (logged as unsupported)
|
|
55
|
+
*
|
|
56
|
+
* The alias prefix (`~/`, `@/`, etc.) is derived from the project layout
|
|
57
|
+
* so it matches the user's `tsconfig.json` paths.
|
|
58
|
+
*/
|
|
59
|
+
export declare function rewriteCompanyUiImports(source: string, componentsJson: Pick<ComponentsJsonFile, "aliases" | "layout">): string;
|
|
26
60
|
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GACjD,MAAM,CAQR;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GACjD,MAAM,CAER"}
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GACjD,MAAM,CAQR;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GACjD,MAAM,CAER;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAYR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC,GAC7D,MAAM,CAaR"}
|
package/dist/utils/paths.js
CHANGED
|
@@ -33,3 +33,57 @@ export function resolveLocalDir(alias, componentsJson) {
|
|
|
33
33
|
export function getSourceRoot(componentsJson) {
|
|
34
34
|
return componentsJson.layout?.sourceRoot ?? "src";
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Compute the import-alias form of `aliases.components` for use when
|
|
38
|
+
* rewriting `@company/ui/*` imports in block and template files.
|
|
39
|
+
*
|
|
40
|
+
* Rules:
|
|
41
|
+
* 1. If the stored alias already starts with a known alias prefix
|
|
42
|
+
* (`@/`, `~/`, `$/`), return it as-is. Block imports written with
|
|
43
|
+
* this prefix will resolve through the user's `tsconfig.json` paths.
|
|
44
|
+
* 2. Otherwise it's a raw filesystem path (e.g. `app/components/ui`).
|
|
45
|
+
* Strip `layout.sourceRoot` and prepend `layout.aliasPrefix` to
|
|
46
|
+
* produce an alias form (e.g. `~/components/ui`). This matches what
|
|
47
|
+
* the user's tsconfig `paths` maps, so the rewritten imports resolve
|
|
48
|
+
* without needing the user to configure anything extra.
|
|
49
|
+
* 3. If the stored alias doesn't match the layout's sourceRoot, return
|
|
50
|
+
* it as-is (the user may have chosen a non-standard location and we
|
|
51
|
+
* assume their tsconfig handles it).
|
|
52
|
+
*/
|
|
53
|
+
export function getComponentsImportAlias(componentsJson) {
|
|
54
|
+
const raw = componentsJson.aliases.components;
|
|
55
|
+
// Already in alias form
|
|
56
|
+
for (const prefix of ["@/", "~/", "$/"]) {
|
|
57
|
+
if (raw.startsWith(prefix))
|
|
58
|
+
return raw;
|
|
59
|
+
}
|
|
60
|
+
// Raw path — convert to alias form via layout
|
|
61
|
+
const layout = componentsJson.layout;
|
|
62
|
+
if (layout && raw.startsWith(`${layout.sourceRoot}/`)) {
|
|
63
|
+
return `${layout.aliasPrefix}${raw.slice(layout.sourceRoot.length + 1)}`;
|
|
64
|
+
}
|
|
65
|
+
return raw;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Rewrite `@company/ui/*` imports in a block or template file to point
|
|
69
|
+
* at the user's locally-installed components. Without this, block files
|
|
70
|
+
* that `import { Button } from "@company/ui/button"` would fail at
|
|
71
|
+
* compile time because `@company/ui` doesn't exist in the consumer project.
|
|
72
|
+
*
|
|
73
|
+
* Transformations:
|
|
74
|
+
* - `from "@company/ui/data-table"` → `from "~/components/ui/data-table"`
|
|
75
|
+
* - `from "@company/ui/data-table/sub"` → `from "~/components/ui/data-table/sub"`
|
|
76
|
+
* - `from "@company/ui/lib/animations"` → `from "~/components/ui/lib/animations"`
|
|
77
|
+
* - `from "@company/ui"` (bare barrel) → no rewrite (logged as unsupported)
|
|
78
|
+
*
|
|
79
|
+
* The alias prefix (`~/`, `@/`, etc.) is derived from the project layout
|
|
80
|
+
* so it matches the user's `tsconfig.json` paths.
|
|
81
|
+
*/
|
|
82
|
+
export function rewriteCompanyUiImports(source, componentsJson) {
|
|
83
|
+
const compImport = getComponentsImportAlias(componentsJson);
|
|
84
|
+
// Handle subpath imports (@company/ui/xxx)
|
|
85
|
+
let result = source.replace(/(from\s+["'])@company\/ui\/([^"']+)(["'])/g, (_, pre, sub, post) => `${pre}${compImport}/${sub}${post}`);
|
|
86
|
+
// Handle side-effect imports like `import "@company/ui/xxx"`
|
|
87
|
+
result = result.replace(/(import\s+["'])@company\/ui\/([^"']+)(["'])/g, (_, pre, sub, post) => `${pre}${compImport}/${sub}${post}`);
|
|
88
|
+
return result;
|
|
89
|
+
}
|
package/package.json
CHANGED