@saasicat/cli 0.27.0 → 1.0.0-rc.1
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 +4 -2
- package/bin/saasicat.js +184 -1
- package/codemods/v1-imports.map.json +135 -0
- package/codemods/v1-rename.map.json +51 -0
- package/dist/.build-stamp +1 -0
- package/dist/index.cjs +288 -9
- package/dist/index.d.cts +113 -2
- package/dist/index.d.ts +113 -2
- package/dist/index.js +280 -9
- package/package.json +9 -8
- package/templates/init/src/auth/password.hasher.ts.tpl +1 -1
- package/templates/init/src/saas/admin-manifest.contribution.ts.tpl +1 -1
- package/templates/init/src/saas/feature-ui-registry.ts.tpl +1 -1
- package/templates/init/src/saas/quota.provider.ts.tpl +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Cross-cutting helpers for consumer CLIs. Provides:
|
|
|
10
10
|
- `ManifestCliFlow` + `DEFAULT_MANIFEST_CHECKS` (12 platform checks) —
|
|
11
11
|
`<app> manifest dump|validate|hash|diff|check`
|
|
12
12
|
|
|
13
|
-
Spec: [`
|
|
13
|
+
Spec: [`cli-conventions.md`][conventions] in `@saasicat/spec`.
|
|
14
14
|
|
|
15
15
|
## Plugin Architecture
|
|
16
16
|
|
|
@@ -126,7 +126,7 @@ domain commands on top.
|
|
|
126
126
|
|
|
127
127
|
## Exit codes
|
|
128
128
|
|
|
129
|
-
Per [`cli-conventions.md`]
|
|
129
|
+
Per [`cli-conventions.md`][conventions] §6:
|
|
130
130
|
|
|
131
131
|
| Code | Meaning |
|
|
132
132
|
| ---- | --------------------------------------- |
|
|
@@ -139,3 +139,5 @@ Per [`cli-conventions.md`](https://github.com/uelker70/saasicat/blob/main/packag
|
|
|
139
139
|
| 6 | conflict |
|
|
140
140
|
| 7 | drift (e.g. manifest check: error) |
|
|
141
141
|
| 99 | internal |
|
|
142
|
+
|
|
143
|
+
[conventions]: https://github.com/uelker70/saasicat/blob/main/packages/spec/cli-conventions.md
|
package/bin/saasicat.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// `saasicat` — bootstrap CLI for the SaaSiCat framework.
|
|
3
|
+
// naming-history: the codemod help below names the pre-1.0 spellings it rewrites.
|
|
3
4
|
//
|
|
4
5
|
// Sub-commands:
|
|
5
6
|
// schema apply [--prisma-schema=PATH] [--fragments=01,02,03]
|
|
@@ -16,6 +17,9 @@
|
|
|
16
17
|
// Prisma's DSL cannot express to the migration it just wrote.
|
|
17
18
|
//
|
|
18
19
|
// init --project-key=X --quota=key:Model [--quota=…]... [--app-name=X] [--api-base=X]
|
|
20
|
+
// codemod v1-imports [--dir=X] [--dry-run]
|
|
21
|
+
// codemod v1-rename [--dir=X] [--dry-run]
|
|
22
|
+
// codemod v1 [--dir=X] [--dry-run] — both, in that order
|
|
19
23
|
// [--skip-hasher] [--dry-run] [--dir=.]
|
|
20
24
|
// Writes the platform wiring — config, persistence, manifest
|
|
21
25
|
// contribution, admin module, one provider per quota — and adds
|
|
@@ -23,7 +27,7 @@
|
|
|
23
27
|
|
|
24
28
|
import { readFile, writeFile, readdir, mkdir } from 'node:fs/promises';
|
|
25
29
|
import { existsSync } from 'node:fs';
|
|
26
|
-
import { dirname, join, resolve } from 'node:path';
|
|
30
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
27
31
|
import { createRequire } from 'node:module';
|
|
28
32
|
import { fileURLToPath } from 'node:url';
|
|
29
33
|
import { spawn } from 'node:child_process';
|
|
@@ -43,7 +47,11 @@ import {
|
|
|
43
47
|
findFkPointers,
|
|
44
48
|
hasConstraints,
|
|
45
49
|
assertValidProjectKey,
|
|
50
|
+
buildImportMap,
|
|
46
51
|
migrationCreatedBy,
|
|
52
|
+
rewriteImports,
|
|
53
|
+
rewriteManifest,
|
|
54
|
+
rewriteNames,
|
|
47
55
|
reportConstraints,
|
|
48
56
|
patchAppModule,
|
|
49
57
|
patchOptionsFor,
|
|
@@ -523,6 +531,161 @@ async function writeConstraintsIntoMigration(args, migrationsBefore) {
|
|
|
523
531
|
}
|
|
524
532
|
}
|
|
525
533
|
|
|
534
|
+
/**
|
|
535
|
+
* Rewrites `@saasicat/ui-vue` imports to the 1.0 export map.
|
|
536
|
+
*
|
|
537
|
+
* The rules come from the same table the platform's own move ran on, shipped
|
|
538
|
+
* with this package — so what a consumer's imports become cannot disagree with
|
|
539
|
+
* where the files actually went.
|
|
540
|
+
*/
|
|
541
|
+
async function cmdCodemodV1Imports(args) {
|
|
542
|
+
const root = resolve(args.dir ?? '.');
|
|
543
|
+
const dryRun = args['dry-run'] === true;
|
|
544
|
+
|
|
545
|
+
const table = JSON.parse(await readFile(codemodTable('v1-imports.map.json'), 'utf8'));
|
|
546
|
+
const map = buildImportMap(table);
|
|
547
|
+
|
|
548
|
+
const unmapped = new Map();
|
|
549
|
+
let rewritten = 0;
|
|
550
|
+
let touched = 0;
|
|
551
|
+
await walkSources(root, async (full, source) => {
|
|
552
|
+
if (basename(full) === CODEMOD_MANIFEST) return;
|
|
553
|
+
const result = rewriteImports(source, map);
|
|
554
|
+
for (const [subpath, n] of result.unmapped) {
|
|
555
|
+
unmapped.set(subpath, (unmapped.get(subpath) ?? 0) + n);
|
|
556
|
+
}
|
|
557
|
+
if (result.rewritten === 0) return;
|
|
558
|
+
if (!dryRun) await writeFile(full, result.text);
|
|
559
|
+
rewritten += result.rewritten;
|
|
560
|
+
touched += 1;
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
console.log(
|
|
564
|
+
`${dryRun ? 'Would rewrite' : 'Rewrote'} ${rewritten} import(s) in ${touched} file(s).`,
|
|
565
|
+
);
|
|
566
|
+
if (unmapped.size === 0) return;
|
|
567
|
+
|
|
568
|
+
console.log('');
|
|
569
|
+
console.log('These have no new home — they need a decision, not a rewrite:');
|
|
570
|
+
for (const [subpath, n] of [...unmapped].sort()) {
|
|
571
|
+
console.log(` ${String(n).padStart(3)}× @saasicat/ui-vue/${subpath}`);
|
|
572
|
+
}
|
|
573
|
+
console.log('');
|
|
574
|
+
console.log(' They moved into `features/` or `internal/`, which the 1.0 surface does');
|
|
575
|
+
console.log(' not publish: they were domain or page-private components, and importing');
|
|
576
|
+
console.log(' them tied your app to our internal structure. Copy what you need into');
|
|
577
|
+
console.log(' your own repository.');
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Rewrites the names 1.0 changed: identifier stems, registry keys, the one
|
|
582
|
+
* token that had two meanings, and the e2e helper's subpath.
|
|
583
|
+
*
|
|
584
|
+
* Same shape as `v1-imports`, same table discipline: the rules are read from
|
|
585
|
+
* `codemods/v1-rename.map.json`, shipped with this package, so what a
|
|
586
|
+
* consumer's code becomes is what the platform's own rename was checked
|
|
587
|
+
* against.
|
|
588
|
+
*/
|
|
589
|
+
async function cmdCodemodV1Rename(args) {
|
|
590
|
+
const root = resolve(args.dir ?? '.');
|
|
591
|
+
const dryRun = args['dry-run'] === true;
|
|
592
|
+
const table = JSON.parse(await readFile(codemodTable('v1-rename.map.json'), 'utf8'));
|
|
593
|
+
|
|
594
|
+
const ambiguous = new Map();
|
|
595
|
+
let rewritten = 0;
|
|
596
|
+
let touched = 0;
|
|
597
|
+
let manifestsTouched = 0;
|
|
598
|
+
await walkSources(root, async (full, source) => {
|
|
599
|
+
// A manifest takes the package renames in its dependency fields; a
|
|
600
|
+
// source file takes everything. Under pnpm an import a manifest does
|
|
601
|
+
// not declare fails to resolve, so the two travel together.
|
|
602
|
+
const result =
|
|
603
|
+
basename(full) === CODEMOD_MANIFEST
|
|
604
|
+
? rewriteManifest(source, table, { targetRange: `^${OWN_VERSION}` })
|
|
605
|
+
: rewriteNames(source, table);
|
|
606
|
+
for (const name of result.ambiguous) {
|
|
607
|
+
ambiguous.set(name, (ambiguous.get(name) ?? 0) + 1);
|
|
608
|
+
}
|
|
609
|
+
if (result.rewritten === 0) return;
|
|
610
|
+
if (!dryRun) await writeFile(full, result.text);
|
|
611
|
+
rewritten += result.rewritten;
|
|
612
|
+
touched += 1;
|
|
613
|
+
if (basename(full) === CODEMOD_MANIFEST) manifestsTouched += 1;
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
console.log(
|
|
617
|
+
`${dryRun ? 'Would rewrite' : 'Rewrote'} ${rewritten} name(s) in ${touched} file(s).`,
|
|
618
|
+
);
|
|
619
|
+
if (manifestsTouched > 0) {
|
|
620
|
+
// The lockfile is not rewritten: its shape is the package manager's,
|
|
621
|
+
// and a wrong guess at it is worse than an honest instruction. A CI
|
|
622
|
+
// that installs with a frozen lockfile refuses the migrated checkout
|
|
623
|
+
// until it is regenerated.
|
|
624
|
+
console.log('');
|
|
625
|
+
console.log(
|
|
626
|
+
`${manifestsTouched} package.json ${manifestsTouched === 1 ? 'file' : 'files'} changed — ` +
|
|
627
|
+
'regenerate the lockfile before committing:',
|
|
628
|
+
);
|
|
629
|
+
console.log(
|
|
630
|
+
' pnpm install (or npm install / yarn install, whichever owns your lockfile)',
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
if (ambiguous.size === 0) return;
|
|
634
|
+
|
|
635
|
+
console.log('');
|
|
636
|
+
console.log('These need a decision, not a rewrite:');
|
|
637
|
+
for (const [name, n] of [...ambiguous].sort()) {
|
|
638
|
+
console.log(` ${String(n).padStart(3)}× ${name}`);
|
|
639
|
+
}
|
|
640
|
+
console.log('');
|
|
641
|
+
console.log(' FEATURE_UI_REGISTRY_TOKEN meant one registry in `@saasicat/nest/billing`');
|
|
642
|
+
console.log(' and another in `@saasicat/nest/catalog`. Import it from the entry you');
|
|
643
|
+
console.log(' mean — BILLING_FEATURE_UI_REGISTRY_TOKEN or CATALOG_FEATURE_UI_REGISTRY_TOKEN.');
|
|
644
|
+
console.log(' A dependency listed "in <field> (<range>)" points at a workspace or a path;');
|
|
645
|
+
console.log(' rename it by hand to @saasicat/core at the location you keep it.');
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* The version this CLI was released as — and therefore the line a consumer
|
|
650
|
+
* running its codemod is migrating to. The manifest rewrite sets the renamed
|
|
651
|
+
* dependency to `^<this>`, because the old range (`^0.27.0`) names a line
|
|
652
|
+
* the renamed package was never published on.
|
|
653
|
+
*/
|
|
654
|
+
const OWN_VERSION = JSON.parse(
|
|
655
|
+
await readFile(join(dirname(require_.resolve('@saasicat/cli')), '..', 'package.json'), 'utf8'),
|
|
656
|
+
).version;
|
|
657
|
+
|
|
658
|
+
/** Where a shipped codemod table lives, resolved through the package itself. */
|
|
659
|
+
function codemodTable(name) {
|
|
660
|
+
return join(dirname(require_.resolve('@saasicat/cli')), '..', 'codemods', name);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Anything a build wrote is skipped, whatever it is called: `dist`, `dist-app`,
|
|
664
|
+
// `dist-dev` — a consumer's declaration output carries the old names too, and
|
|
665
|
+
// rewriting it would only make the next build disagree with it.
|
|
666
|
+
const CODEMOD_SKIP = new Set(['node_modules', '.git', '.output', 'coverage']);
|
|
667
|
+
const isBuildOutput = (name) => name === 'dist' || name.startsWith('dist-');
|
|
668
|
+
const CODEMOD_EXTENSIONS = /\.(ts|tsx|mts|cts|js|jsx|mjs|cjs|vue|md)$/;
|
|
669
|
+
/** Walked for the package renames alone; see `rewriteManifest`. */
|
|
670
|
+
const CODEMOD_MANIFEST = 'package.json';
|
|
671
|
+
|
|
672
|
+
/** Every source file under `root` a codemod may touch, with its text. */
|
|
673
|
+
async function walkSources(root, visit) {
|
|
674
|
+
const walk = async (dir) => {
|
|
675
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
676
|
+
if (CODEMOD_SKIP.has(entry.name) || isBuildOutput(entry.name)) continue;
|
|
677
|
+
const full = join(dir, entry.name);
|
|
678
|
+
if (entry.isDirectory()) {
|
|
679
|
+
await walk(full);
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
if (!CODEMOD_EXTENSIONS.test(entry.name) && entry.name !== CODEMOD_MANIFEST) continue;
|
|
683
|
+
await visit(full, await readFile(full, 'utf8'));
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
await walk(root);
|
|
687
|
+
}
|
|
688
|
+
|
|
526
689
|
/** Reads a repeated flag (`--quota=a --quota=b`) off argv. */
|
|
527
690
|
function repeatedFlag(argv, name) {
|
|
528
691
|
return argv
|
|
@@ -662,6 +825,18 @@ async function patchAppModuleFile(root, plan, args) {
|
|
|
662
825
|
|
|
663
826
|
async function main() {
|
|
664
827
|
const [, , cmd, sub, ...rest] = process.argv;
|
|
828
|
+
if (cmd === 'codemod' && sub === 'v1-imports') {
|
|
829
|
+
return cmdCodemodV1Imports(parseArgs(rest));
|
|
830
|
+
}
|
|
831
|
+
if (cmd === 'codemod' && sub === 'v1-rename') {
|
|
832
|
+
return cmdCodemodV1Rename(parseArgs(rest));
|
|
833
|
+
}
|
|
834
|
+
if (cmd === 'codemod' && sub === 'v1') {
|
|
835
|
+
// Imports first: the rename table keys its per-entry tokens by the
|
|
836
|
+
// specifier they are imported from, which the import rewrite settles.
|
|
837
|
+
await cmdCodemodV1Imports(parseArgs(rest));
|
|
838
|
+
return cmdCodemodV1Rename(parseArgs(rest));
|
|
839
|
+
}
|
|
665
840
|
if (cmd === 'init') {
|
|
666
841
|
return cmdInit(parseArgs([sub, ...rest].filter(Boolean)), process.argv.slice(3));
|
|
667
842
|
}
|
|
@@ -694,6 +869,14 @@ async function main() {
|
|
|
694
869
|
console.log(' every plan must declare one, or the catalogue does not load.');
|
|
695
870
|
console.log(' init --project-key=myapp --quota=notes:Note --quota=seats:Seat');
|
|
696
871
|
console.log('');
|
|
872
|
+
console.log(' codemod v1 [--dir=.] [--dry-run]');
|
|
873
|
+
console.log(' the whole 1.0 migration: v1-imports, then v1-rename');
|
|
874
|
+
console.log(' codemod v1-imports [--dir=.] [--dry-run]');
|
|
875
|
+
console.log(' rewrite @saasicat/ui-vue imports to the 1.0 export map');
|
|
876
|
+
console.log(' codemod v1-rename [--dir=.] [--dry-run]');
|
|
877
|
+
console.log(' rewrite the names 1.0 changed: SaasPlatform*, Symbol.for keys,');
|
|
878
|
+
console.log(' FEATURE_UI_REGISTRY_TOKEN, @saasicat/ui-vue/testing-e2e/*');
|
|
879
|
+
console.log('');
|
|
697
880
|
console.log('Optional --prisma-schema=PATH (default prisma/schema.prisma).');
|
|
698
881
|
console.log('Optional --tenant-model=X --user-model=Y for apply/migrate — enables');
|
|
699
882
|
console.log(' the foreign keys from the platform tables to your models.');
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": [
|
|
3
|
+
"The 4.1 move, as data rather than as commands.",
|
|
4
|
+
"",
|
|
5
|
+
"Two axes decide every destination, and each directory answers exactly one",
|
|
6
|
+
"question (AP3 \u00a73.6): the LAYER a file belongs to (client / vue / quasar /",
|
|
7
|
+
"SFC) and how far it is REUSED \u2014 ui (surface-neutral, many domains) \u2192",
|
|
8
|
+
"features (one domain, many pages) \u2192 internal/<page> (one page) \u2192 pages",
|
|
9
|
+
"(one route).",
|
|
10
|
+
"",
|
|
11
|
+
"Written down because the mapping is the reviewable part. A 210-file move",
|
|
12
|
+
"expressed as `git mv` lines is a diff nobody can check; expressed as a",
|
|
13
|
+
"table, the question is whether each row is right.",
|
|
14
|
+
"",
|
|
15
|
+
"Two destinations differ from the sketch in AP3 \u00a73.6, and the reason is a",
|
|
16
|
+
"measurement rather than a preference. Consumers import `FeatureGate.vue` 19",
|
|
17
|
+
"times and `MfaPromptDialog.vue` 5 times across notesapp, vereinsfux and",
|
|
18
|
+
"autohauspro \u2014 `FeatureGate` is the single most imported component in the",
|
|
19
|
+
"package. AP3 places FeatureGate in `features/entitlement/`, and `features/`",
|
|
20
|
+
"is explicitly not exported; MfaPromptDialog is used by one page, which by",
|
|
21
|
+
"the reuse axis alone would put it in `internal/`. Either placement removes a",
|
|
22
|
+
"component three consumer repositories depend on.",
|
|
23
|
+
"",
|
|
24
|
+
"So both stay on the exported surface. A component a consumer embeds in their",
|
|
25
|
+
"own application is part of the public surface no matter how many of OUR",
|
|
26
|
+
"pages use it \u2014 the reuse axis measures our reuse, and that is not the same",
|
|
27
|
+
"question."
|
|
28
|
+
],
|
|
29
|
+
"moves": {
|
|
30
|
+
"components/admin-page/AdminPage.vue": "ui/page/AdminPage.vue",
|
|
31
|
+
"components/admin-page/AdminHero.vue": "ui/page/AdminHero.vue",
|
|
32
|
+
"components/admin-page/AdminBody.vue": "ui/page/AdminBody.vue",
|
|
33
|
+
"components/admin-page/AdminSection.vue": "ui/page/AdminSection.vue",
|
|
34
|
+
"components/admin-page/AdminFilters.vue": "ui/page/AdminFilters.vue",
|
|
35
|
+
"components/admin-page/AdminAccordion.vue": "ui/page/AdminAccordion.vue",
|
|
36
|
+
"components/admin-page/AdminTable.vue": "ui/data/AdminTable.vue",
|
|
37
|
+
"components/admin-page/AdminPaginator.vue": "ui/data/AdminPaginator.vue",
|
|
38
|
+
"components/admin-page/AdminStatistics.vue": "ui/data/AdminStatistics.vue",
|
|
39
|
+
"components/admin-page/AdminKpi.vue": "ui/data/AdminKpi.vue",
|
|
40
|
+
"components/KvBlock.vue": "ui/data/KvBlock.vue",
|
|
41
|
+
"components/admin-page/AdminRefreshBtn.vue": "ui/feedback/AdminRefreshBtn.vue",
|
|
42
|
+
"components/wizard-stepper/WizardStepper.vue": "ui/page/WizardStepper.vue",
|
|
43
|
+
"components/plan/PlanCycleToggle.vue": "@saasicat/ui-vue-tenant/plan/PlanCycleToggle.vue",
|
|
44
|
+
"components/plan/PlanGrid.vue": "@saasicat/ui-vue-tenant/plan/PlanGrid.vue",
|
|
45
|
+
"components/plan/PriceSummary.vue": "@saasicat/ui-vue-tenant/plan/PriceSummary.vue",
|
|
46
|
+
"components/plan/PromoCodeInput.vue": "@saasicat/ui-vue-tenant/plan/PromoCodeInput.vue",
|
|
47
|
+
"components/plan/PublicBundleGrid.vue": "@saasicat/ui-vue-tenant/plan/PublicBundleGrid.vue",
|
|
48
|
+
"components/plan-create-dialog/PlanCreateDialog.vue": "features/plan/PlanCreateDialog.vue",
|
|
49
|
+
"components/plan-list/PlanList.vue": "features/plan/PlanList.vue",
|
|
50
|
+
"components/plan-matrix/PlanMatrix.vue": "features/plan/PlanMatrix.vue",
|
|
51
|
+
"components/plan-review/PlanReview.vue": "features/plan/PlanReview.vue",
|
|
52
|
+
"components/plan-detail/PlanDetail.vue": "features/plan/PlanDetail.vue",
|
|
53
|
+
"components/plan-detail/PlanTerminateDialog.vue": "features/plan/PlanTerminateDialog.vue",
|
|
54
|
+
"components/plan-detail/PlanAuditLog.vue": "features/plan/internal/PlanAuditLog.vue",
|
|
55
|
+
"components/plan-detail/PlanDetailKpis.vue": "features/plan/internal/PlanDetailKpis.vue",
|
|
56
|
+
"components/plan-detail/PlanTitleEdit.vue": "features/plan/internal/PlanTitleEdit.vue",
|
|
57
|
+
"components/plan-detail/PlanVersionDiffPanel.vue": "features/plan/internal/PlanVersionDiffPanel.vue",
|
|
58
|
+
"components/plan-detail/PlanVersionsPanel.vue": "features/plan/internal/PlanVersionsPanel.vue",
|
|
59
|
+
"components/plan-detail/types.ts": "features/plan/internal/plan-detail.types.ts",
|
|
60
|
+
"components/plan-version-editor/PlanVersionEditor.vue": "features/plan/PlanVersionEditor.vue",
|
|
61
|
+
"components/plan-version-editor/PlanCatalogPreview.vue": "features/plan/internal/PlanCatalogPreview.vue",
|
|
62
|
+
"components/plan-version-editor/PlanComponentPool.vue": "features/plan/internal/PlanComponentPool.vue",
|
|
63
|
+
"components/plan-version-editor/PlanVersionBasket.vue": "features/plan/internal/PlanVersionBasket.vue",
|
|
64
|
+
"components/plan-version-editor/PlanVersionDiffDialog.vue": "features/plan/internal/PlanVersionDiffDialog.vue",
|
|
65
|
+
"components/plan-version-editor/PlanVersionEditorHeader.vue": "features/plan/internal/PlanVersionEditorHeader.vue",
|
|
66
|
+
"components/plan-version-editor/types.ts": "features/plan/internal/plan-version-editor.types.ts",
|
|
67
|
+
"components/bundle-editor/BundleVersionInlineEditor.vue": "features/bundle/BundleVersionInlineEditor.vue",
|
|
68
|
+
"components/bundle-editor/BundleVersionStrip.vue": "features/bundle/BundleVersionStrip.vue",
|
|
69
|
+
"components/BundleVersionPublishDialog.vue": "features/bundle/BundleVersionPublishDialog.vue",
|
|
70
|
+
"components/bundle-editor/BundleCreatePanel.vue": "features/bundle/internal/BundleCreatePanel.vue",
|
|
71
|
+
"components/bundle-editor/BundleFeaturesEditor.vue": "features/bundle/internal/BundleFeaturesEditor.vue",
|
|
72
|
+
"components/bundle-editor/BundlePlanCompatPicker.vue": "features/bundle/internal/BundlePlanCompatPicker.vue",
|
|
73
|
+
"components/bundle-editor/BundleQuotasEditor.vue": "features/bundle/internal/BundleQuotasEditor.vue",
|
|
74
|
+
"components/bundle-editor/BundleStatusBanner.vue": "features/bundle/internal/BundleStatusBanner.vue",
|
|
75
|
+
"components/bundle-editor/bundle-version-status.ts": "features/bundle/internal/bundle-version-status.ts",
|
|
76
|
+
"components/bundle-editor/catalog-i18n.ts": "features/bundle/internal/catalog-i18n.ts",
|
|
77
|
+
"components/FeatureGate.vue": "ui/entitlement/FeatureGate.vue",
|
|
78
|
+
"components/dialogs/PilotCreateDialog.vue": "internal/dialogs/PilotCreateDialog.vue",
|
|
79
|
+
"components/dialogs/PilotEditDialog.vue": "internal/dialogs/PilotEditDialog.vue",
|
|
80
|
+
"components/dialogs/PromoCodeCreateDialog.vue": "internal/dialogs/PromoCodeCreateDialog.vue",
|
|
81
|
+
"components/dialogs/PromoCodeDialogFields.vue": "internal/dialogs/PromoCodeDialogFields.vue",
|
|
82
|
+
"components/dialogs/PromoCodeEditDialog.vue": "internal/dialogs/PromoCodeEditDialog.vue",
|
|
83
|
+
"components/dialogs/pilot-dialog.css": "internal/dialogs/pilot-dialog.css",
|
|
84
|
+
"components/dialogs/types.ts": "internal/dialogs/types.ts",
|
|
85
|
+
"pages-standard/AdminLayout.vue": "layouts/AdminLayout.vue",
|
|
86
|
+
"pages-standard/SuperAdminLoginPage.vue": "auth/SuperAdminLoginPage.vue",
|
|
87
|
+
"pages-standard/SuperAdminSetupWizard.vue": "auth/SuperAdminSetupWizard.vue",
|
|
88
|
+
"pages-standard/AdminManifestErrorPage.vue": "pages/AdminManifestErrorPage.vue",
|
|
89
|
+
"pages-standard/AuditPage.vue": "pages/AuditPage.vue",
|
|
90
|
+
"pages-standard/BundlesPage.vue": "pages/BundlesPage.vue",
|
|
91
|
+
"pages-standard/DashboardPage.vue": "pages/DashboardPage.vue",
|
|
92
|
+
"pages-standard/DiscoveryPage.vue": "pages/DiscoveryPage.vue",
|
|
93
|
+
"pages-standard/EmailHistoryPage.vue": "pages/EmailHistoryPage.vue",
|
|
94
|
+
"pages-standard/MarketingCatalogPage.vue": "pages/MarketingCatalogPage.vue",
|
|
95
|
+
"pages-standard/PilotsPage.vue": "pages/PilotsPage.vue",
|
|
96
|
+
"pages-standard/PlansPage.vue": "pages/PlansPage.vue",
|
|
97
|
+
"pages-standard/PlatformEmailPage.vue": "pages/PlatformEmailPage.vue",
|
|
98
|
+
"pages-standard/PromoCodeDetailPage.vue": "pages/PromoCodeDetailPage.vue",
|
|
99
|
+
"pages-standard/PromoCodesPage.vue": "pages/PromoCodesPage.vue",
|
|
100
|
+
"pages-standard/SubscriptionsPage.vue": "pages/SubscriptionsPage.vue",
|
|
101
|
+
"pages-standard/TenantDetailPage.vue": "pages/TenantDetailPage.vue",
|
|
102
|
+
"pages-standard/TenantsPage.vue": "pages/TenantsPage.vue",
|
|
103
|
+
"pages-standard/UsersPage.vue": "pages/UsersPage.vue",
|
|
104
|
+
"pages-standard/email-history.types.ts": "internal/email-history/email-history.types.ts",
|
|
105
|
+
"pages-standard/platform-email.types.ts": "internal/platform-email/platform-email.types.ts",
|
|
106
|
+
"components/MfaPromptDialog.vue": "ui/overlay/MfaPromptDialog.vue",
|
|
107
|
+
"components/LocaleSwitcher.vue": "ui/page/LocaleSwitcher.vue",
|
|
108
|
+
"components/ThemeSwitcher.vue": "ui/page/ThemeSwitcher.vue",
|
|
109
|
+
"components/MarketingPromotionsTab.vue": "features/marketing/MarketingPromotionsTab.vue",
|
|
110
|
+
"components/TenantActionConfirmDialog.vue": "features/tenant/TenantActionConfirmDialog.vue",
|
|
111
|
+
"components/VersionDiffPreview.vue": "features/bundle/VersionDiffPreview.vue",
|
|
112
|
+
"pages-standard/sa-theme.css": "ui/theme/sa-theme.css"
|
|
113
|
+
},
|
|
114
|
+
"moveDirectories": {
|
|
115
|
+
"pages-standard/bundles-page": "internal/bundles-page",
|
|
116
|
+
"pages-standard/discovery-page": "internal/discovery-page",
|
|
117
|
+
"pages-standard/marketing-catalog": "internal/marketing-catalog",
|
|
118
|
+
"pages-standard/plan-versions": "internal/plan-versions",
|
|
119
|
+
"pages-standard/plans-page": "internal/plans-page",
|
|
120
|
+
"pages-standard/tenant-detail": "internal/tenant-detail",
|
|
121
|
+
"pages-standard/tenants": "internal/tenants"
|
|
122
|
+
},
|
|
123
|
+
"packages": {
|
|
124
|
+
"_": "Subpaths that left @saasicat/ui-vue for a package of their own. The value is a full specifier, and the codemod emits it verbatim.",
|
|
125
|
+
"pages-tenant/": "@saasicat/ui-vue-tenant/"
|
|
126
|
+
},
|
|
127
|
+
"stays": {
|
|
128
|
+
"client/": "framework-free layer, unchanged",
|
|
129
|
+
"vue/": "composables, unchanged",
|
|
130
|
+
"quasar/": "the one non-SFC place that may import quasar, unchanged",
|
|
131
|
+
"ui/theme/": "already in its destination (AP2)",
|
|
132
|
+
"testing-e2e/ \u2192 testing/": "renamed in phase 5 (5.8); `codemod v1-rename` rewrites the specifier",
|
|
133
|
+
"pages-standard/sa-theme.css \u2192 ui/theme/": "moved so that pages-standard/ can go; renamed to theme.css in 4.2"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_namingHistory": "The 1.0 rename as data. Every old spelling below is named on purpose: this table is what `saasicat codemod v1-rename` runs on, and `tests/one-spelling.test.js` reads this key as the declaration.",
|
|
3
|
+
"_comment": [
|
|
4
|
+
"Phase 5 (AP1) renamed four things a consumer's code can carry:",
|
|
5
|
+
"identifier stems, registry keys, one token that had two meanings, and",
|
|
6
|
+
"one export subpath. Each section is one of those, and the codemod",
|
|
7
|
+
"applies them in that order.",
|
|
8
|
+
"",
|
|
9
|
+
"`identifierStems` is matched anywhere in an identifier — the stem alone",
|
|
10
|
+
"covers `SaasPlatformModule`, `createSaasPlatformTestModule` and",
|
|
11
|
+
"`CreateSaasPlatformTestModuleOptions` without listing them. The lowercase",
|
|
12
|
+
"`saasicat` (scope, files) is not a stem and is never touched.",
|
|
13
|
+
"",
|
|
14
|
+
"`registryKeys` rewrites the string a `Symbol.for` is called with. A",
|
|
15
|
+
"consumer that spelled a key themselves gets the same symbol the platform",
|
|
16
|
+
"now registers; without this their injection would resolve to nothing.",
|
|
17
|
+
"",
|
|
18
|
+
"`packages` renames a whole package — in specifiers and in package.json.",
|
|
19
|
+
"",
|
|
20
|
+
"`entryTokens` is keyed by the import specifier, because the old name",
|
|
21
|
+
"meant different registries in different entries. An import of it from",
|
|
22
|
+
"anywhere else is reported, not guessed."
|
|
23
|
+
],
|
|
24
|
+
"identifierStems": {
|
|
25
|
+
"SaasPlatform": "SaaSiCat",
|
|
26
|
+
"Saasicat": "SaaSiCat",
|
|
27
|
+
"SaaSicat": "SaaSiCat"
|
|
28
|
+
},
|
|
29
|
+
"registryKeys": {
|
|
30
|
+
"saas-platform/": "saasicat/nest/",
|
|
31
|
+
"saas-platform-nest/": "saasicat/nest/",
|
|
32
|
+
"saas-platform-cli/": "saasicat/cli/",
|
|
33
|
+
"@saasicat/ui-vue/": "saasicat/ui-vue/",
|
|
34
|
+
"FakeTransactionRunner.tx": "saasicat/nest/FakeTransactionRunner.tx"
|
|
35
|
+
},
|
|
36
|
+
"entryTokens": {
|
|
37
|
+
"@saasicat/nest/billing": {
|
|
38
|
+
"FEATURE_UI_REGISTRY_TOKEN": "BILLING_FEATURE_UI_REGISTRY_TOKEN"
|
|
39
|
+
},
|
|
40
|
+
"@saasicat/nest/catalog": {
|
|
41
|
+
"FEATURE_UI_REGISTRY_TOKEN": "CATALOG_FEATURE_UI_REGISTRY_TOKEN"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"subpaths": {
|
|
45
|
+
"@saasicat/ui-vue/testing-e2e/": "@saasicat/ui-vue/testing/"
|
|
46
|
+
},
|
|
47
|
+
"packages": {
|
|
48
|
+
"_": "A package that was renamed. Applied to import specifiers AND to the dependency fields of every package.json the walk meets: an import rewritten without its manifest does not resolve under pnpm.",
|
|
49
|
+
"@saasicat/types": "@saasicat/core"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
97f66acb8ca26c7c9470c1991febbb2f68518f1b3cd364af6d3566249550482a
|