@cedarjs/cli 7.0.0-canary.3107 → 7.0.0-canary.3108
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.
|
@@ -58,13 +58,17 @@ function editSchema(schema, options) {
|
|
|
58
58
|
if (!hasModel(schema, "User")) {
|
|
59
59
|
throw new Error("CEDAR_TENANCY_ERR_NO_USER_MODEL");
|
|
60
60
|
}
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
const organizationIsCustomized = hasModel(schema, "Organization") && !schema.includes(ORGANIZATION_MODEL);
|
|
62
|
+
const membershipIsCustomized = hasModel(schema, "Membership") && !schema.includes(MEMBERSHIP_MODEL);
|
|
63
|
+
const modelsCustomized = organizationIsCustomized || membershipIsCustomized;
|
|
64
|
+
if (modelsCustomized && !options.force) {
|
|
65
|
+
return { schema: addDataMigrationModel(schema), outcome: "skipped" };
|
|
65
66
|
}
|
|
66
67
|
const withTenancyModels = addTenancyModels(schema);
|
|
67
|
-
return
|
|
68
|
+
return {
|
|
69
|
+
schema: addDataMigrationModel(withTenancyModels),
|
|
70
|
+
outcome: modelsCustomized ? "forced" : "added"
|
|
71
|
+
};
|
|
68
72
|
}
|
|
69
73
|
export {
|
|
70
74
|
MEMBERSHIP_MODEL,
|
|
@@ -22,7 +22,12 @@ import {
|
|
|
22
22
|
hasWebAuthFile,
|
|
23
23
|
noUserModelMessage
|
|
24
24
|
} from "./preflight.js";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
editSchema,
|
|
27
|
+
hasModel,
|
|
28
|
+
MEMBERSHIP_MODEL,
|
|
29
|
+
ORGANIZATION_MODEL
|
|
30
|
+
} from "./schemaPrisma.js";
|
|
26
31
|
const DEFAULT_TENANT_FIELD = "organizationId";
|
|
27
32
|
const AUTH_SNIPPET = `
|
|
28
33
|
export const getCurrentUser = async (session) => {
|
|
@@ -104,12 +109,12 @@ const handler = async ({ tenantField, force }) => {
|
|
|
104
109
|
},
|
|
105
110
|
{
|
|
106
111
|
title: "Adding Organization and Membership models to schema.prisma...",
|
|
107
|
-
task: async () => {
|
|
112
|
+
task: async (ctx, task) => {
|
|
108
113
|
const schemaPath = await getSchemaPath(paths.api.prismaConfig);
|
|
109
114
|
const schema = fs.readFileSync(schemaPath, "utf-8");
|
|
110
|
-
let
|
|
115
|
+
let editResult;
|
|
111
116
|
try {
|
|
112
|
-
|
|
117
|
+
editResult = editSchema(schema, { force });
|
|
113
118
|
} catch (e) {
|
|
114
119
|
const message = e instanceof Error ? e.message : String(e);
|
|
115
120
|
if (message === "CEDAR_TENANCY_ERR_NO_USER_MODEL") {
|
|
@@ -119,14 +124,20 @@ const handler = async ({ tenantField, force }) => {
|
|
|
119
124
|
`No \`User\` model found in schema.prisma. Set up authentication first (e.g. \`${authSetup}\`) before running \`${tenancySetup}\`.`
|
|
120
125
|
);
|
|
121
126
|
}
|
|
122
|
-
if (message === "CEDAR_TENANCY_ERR_MODELS_EXIST") {
|
|
123
|
-
throw new Error(
|
|
124
|
-
"`Organization` and/or `Membership` models already exist in schema.prisma. Re-run with --force to keep them as-is and continue with the rest of the setup."
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
127
|
throw e;
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
ctx.modelsExistOutcome = editResult.outcome;
|
|
130
|
+
fs.writeFileSync(schemaPath, editResult.schema);
|
|
131
|
+
if (editResult.outcome === "skipped") {
|
|
132
|
+
task.output = `\`Organization\` and/or \`Membership\` models already exist in schema.prisma and were left as-is. Add these fields and relations by hand so tenancy can use them:
|
|
133
|
+
|
|
134
|
+
${ORGANIZATION_MODEL}
|
|
135
|
+
|
|
136
|
+
${MEMBERSHIP_MODEL}
|
|
137
|
+
|
|
138
|
+
Re-run with --force to have this command append its own versions beside them instead, so you can diff and merge rather than retype.`;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
130
141
|
try {
|
|
131
142
|
await runTransitiveBin(
|
|
132
143
|
"prisma",
|
|
@@ -134,13 +145,21 @@ const handler = async ({ tenantField, force }) => {
|
|
|
134
145
|
{ cwd: paths.base }
|
|
135
146
|
);
|
|
136
147
|
} catch {
|
|
148
|
+
if (editResult.outcome === "forced") {
|
|
149
|
+
task.output = '`prisma format` failed because the appended Organization/Membership clash with your existing ones, as requested by --force. Continuing with the rest of the setup; see "Next steps" for how to merge them.';
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
137
152
|
throw new Error(
|
|
138
153
|
"`prisma format` failed, so the `memberships` relation was not added to the `User` model. Add it by hand: `memberships Membership[]` as the last field of `model User { ... }`, then re-run this command."
|
|
139
154
|
);
|
|
140
155
|
}
|
|
141
156
|
const membershipsOccurrences = (schema2) => (schema2.match(/memberships\s+Membership\[\]/g) ?? []).length;
|
|
142
157
|
const formattedSchema = fs.readFileSync(schemaPath, "utf-8");
|
|
143
|
-
if (membershipsOccurrences(formattedSchema) <= membershipsOccurrences(
|
|
158
|
+
if (membershipsOccurrences(formattedSchema) <= membershipsOccurrences(editResult.schema)) {
|
|
159
|
+
if (editResult.outcome === "forced") {
|
|
160
|
+
task.output = 'The `memberships` relation was not added to the `User` model, likely because of the clash from --force. Continuing with the rest of the setup; see "Next steps" for how to merge the appended models by hand.';
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
144
163
|
throw new Error(
|
|
145
164
|
"`prisma format` did not add the `memberships` relation to the `User` model. Add it by hand: `memberships Membership[]` as the last field of `model User { ... }`, then re-run this command."
|
|
146
165
|
);
|
|
@@ -340,17 +359,22 @@ ${SIGNUP_SNIPPET}`;
|
|
|
340
359
|
},
|
|
341
360
|
{
|
|
342
361
|
title: "Next steps...",
|
|
343
|
-
task: (
|
|
362
|
+
task: (ctx, task) => {
|
|
344
363
|
const migrateCommand = formatCedarCommand([
|
|
345
364
|
"prisma",
|
|
346
365
|
"migrate",
|
|
347
366
|
"dev"
|
|
348
367
|
]);
|
|
349
368
|
const dataMigrateCommand = formatCedarCommand(["data-migrate", "up"]);
|
|
369
|
+
const modelsExistWarning = ctx.modelsExistOutcome === "forced" ? c.error(
|
|
370
|
+
"\nschema.prisma is currently invalid (as requested by --force): merge the appended Organization/Membership blocks with your existing ones, then run `prisma format`.\n"
|
|
371
|
+
) : ctx.modelsExistOutcome === "skipped" ? c.warning(
|
|
372
|
+
"\nOrganization/Membership already existed and were left as-is: add the fields and relations printed above by hand before continuing.\n"
|
|
373
|
+
) : "";
|
|
350
374
|
task.title = `Next steps...
|
|
351
375
|
|
|
352
376
|
${c.success("\nMulti-tenancy configured!\n")}
|
|
353
|
-
|
|
377
|
+
${modelsExistWarning}
|
|
354
378
|
1. Run ${c.highlight(migrateCommand)} to create the Organization/Membership
|
|
355
379
|
tables, then ${c.highlight(dataMigrateCommand)} to give every existing
|
|
356
380
|
user a default organization.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/cli",
|
|
3
|
-
"version": "7.0.0-canary.
|
|
3
|
+
"version": "7.0.0-canary.3108",
|
|
4
4
|
"description": "The CedarJS Command Line",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
"@babel/preset-typescript": "7.29.7",
|
|
37
37
|
"@babel/traverse": "7.29.8",
|
|
38
38
|
"@babel/types": "7.29.8",
|
|
39
|
-
"@cedarjs/api-server": "7.0.0-canary.
|
|
40
|
-
"@cedarjs/babel-config": "7.0.0-canary.
|
|
41
|
-
"@cedarjs/cli-helpers": "7.0.0-canary.
|
|
42
|
-
"@cedarjs/internal": "7.0.0-canary.
|
|
43
|
-
"@cedarjs/prerender": "7.0.0-canary.
|
|
44
|
-
"@cedarjs/project-config": "7.0.0-canary.
|
|
45
|
-
"@cedarjs/structure": "7.0.0-canary.
|
|
46
|
-
"@cedarjs/telemetry": "7.0.0-canary.
|
|
47
|
-
"@cedarjs/utils": "7.0.0-canary.
|
|
48
|
-
"@cedarjs/vite": "7.0.0-canary.
|
|
49
|
-
"@cedarjs/web-server": "7.0.0-canary.
|
|
39
|
+
"@cedarjs/api-server": "7.0.0-canary.3108",
|
|
40
|
+
"@cedarjs/babel-config": "7.0.0-canary.3108",
|
|
41
|
+
"@cedarjs/cli-helpers": "7.0.0-canary.3108",
|
|
42
|
+
"@cedarjs/internal": "7.0.0-canary.3108",
|
|
43
|
+
"@cedarjs/prerender": "7.0.0-canary.3108",
|
|
44
|
+
"@cedarjs/project-config": "7.0.0-canary.3108",
|
|
45
|
+
"@cedarjs/structure": "7.0.0-canary.3108",
|
|
46
|
+
"@cedarjs/telemetry": "7.0.0-canary.3108",
|
|
47
|
+
"@cedarjs/utils": "7.0.0-canary.3108",
|
|
48
|
+
"@cedarjs/vite": "7.0.0-canary.3108",
|
|
49
|
+
"@cedarjs/web-server": "7.0.0-canary.3108",
|
|
50
50
|
"@listr2/prompt-adapter-enquirer": "4.3.1",
|
|
51
51
|
"@opentelemetry/api": "1.9.1",
|
|
52
52
|
"@opentelemetry/core": "1.30.1",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"yargs": "17.7.3"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
|
-
"@cedarjs/framework-tools": "7.0.0-canary.
|
|
97
|
+
"@cedarjs/framework-tools": "7.0.0-canary.3108",
|
|
98
98
|
"@prisma/dmmf": "7.10.0",
|
|
99
99
|
"@types/archiver": "^7.0.0",
|
|
100
100
|
"memfs": "4.68.2",
|