@aventara/prisma7-adapter 1.0.0-rc.2 → 1.0.0-rc.3
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# @aventara/prisma7-adapter
|
|
2
2
|
|
|
3
|
+
## 1.0.0-rc.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b38034d: `aventara-prisma7-generate` refuses a `--provider` that the schema's `datasource` block contradicts, or a block naming
|
|
8
|
+
a provider the adapter does not support, before `prisma generate` runs, so neither the Prisma client nor the artifact
|
|
9
|
+
is written:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
aventara-prisma7-generate: --provider postgresql contradicts the schema's datasource `db` (prisma/schema.prisma:12), which names provider "sqlite"; pass --provider sqlite.
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
PSL's `postgres` spelling counts as `postgresql`, and a provider that is not a string literal is not compared.
|
|
16
|
+
Before, the flag was taken on trust, and a wrong one wrote the wrong provider into the artifact and the wrong filter
|
|
17
|
+
modes into the Contract.
|
|
18
|
+
|
|
19
|
+
When the file system refuses the artifact file (`--out`), the step says so in one sentence naming the file and why,
|
|
20
|
+
such as
|
|
21
|
+
`the artifact file /app/src/generated/aventara/discovery.artifact.ts (--out) cannot be written: permission denied (EACCES).`,
|
|
22
|
+
and leaves no staged file behind. Before, every such failure except a directory printed a stack trace.
|
|
23
|
+
|
|
24
|
+
- b38034d: On PostgreSQL, a `@unique` value too long for its index (an index row past the B-tree's 8191 bytes, SQLSTATE
|
|
25
|
+
`54000`) is answered `422 A2004`, not `500 A3001`: one `V1004` issue at `["arguments"]`, as a value too long for its
|
|
26
|
+
column already was. The adapter reads the SQLSTATE, never the message. The issue's message for a value too long now
|
|
27
|
+
reads `The database refused this value: it is longer than the database can hold for its column.`
|
|
28
|
+
(it said `longer than its column can hold`, which an index refusal is not).
|
|
29
|
+
- Updated dependencies [b38034d]
|
|
30
|
+
- Updated dependencies [b38034d]
|
|
31
|
+
- Updated dependencies [b38034d]
|
|
32
|
+
- Updated dependencies [b38034d]
|
|
33
|
+
- Updated dependencies [b38034d]
|
|
34
|
+
- Updated dependencies [b38034d]
|
|
35
|
+
- @aventara/core@1.0.0-rc.3
|
|
36
|
+
|
|
3
37
|
## 1.0.0-rc.2
|
|
4
38
|
|
|
5
39
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -86,8 +86,9 @@ npx aventara-prisma7-generate \
|
|
|
86
86
|
--config src/aventara.config.ts
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
`--provider` and `--driver` are declared, never sniffed. The provider is recorded in the artifact
|
|
90
|
-
|
|
89
|
+
`--provider` and `--driver` are declared, never sniffed. The provider is recorded in the artifact, and the
|
|
90
|
+
step refuses a `--provider` that the schema's `datasource` block contradicts (`provider = "sqlite"` with
|
|
91
|
+
`--provider postgresql`), naming the flag to pass. The driver decides `AvAdapterModel.transactions`, a driver fact the schema cannot state. Declare the driver
|
|
91
92
|
the application will actually construct the adapter with. The two cannot drift silently, but they can
|
|
92
93
|
disagree, and core refuses construction when they do.
|
|
93
94
|
|
|
@@ -26,8 +26,16 @@ export type PrismaSchemaUnknownKind =
|
|
|
26
26
|
| "block"
|
|
27
27
|
/** A line the reader could not classify at all. */
|
|
28
28
|
| "line";
|
|
29
|
+
/** A `datasource` block: the provider it names. */
|
|
30
|
+
export type PrismaSchemaDatasource = {
|
|
31
|
+
readonly name: string;
|
|
32
|
+
readonly provider: string | null;
|
|
33
|
+
readonly site: PrismaSchemaSite;
|
|
34
|
+
};
|
|
29
35
|
export type PrismaSchemaFacts = {
|
|
30
36
|
readonly enums: readonly PrismaSchemaEnum[];
|
|
37
|
+
/** Every `datasource` block, in reading order (Prisma admits one). */
|
|
38
|
+
readonly datasources: readonly PrismaSchemaDatasource[];
|
|
31
39
|
readonly models: readonly PrismaSchemaModel[];
|
|
32
40
|
/**
|
|
33
41
|
* Attributes and blocks the reader does not recognise at all (a `type`/`view`
|
|
@@ -63,12 +63,15 @@ export function readPrismaSchemaSources(sources) {
|
|
|
63
63
|
const enums = [];
|
|
64
64
|
const models = [];
|
|
65
65
|
const unhandled = [];
|
|
66
|
+
const datasources = [];
|
|
66
67
|
for (const source of sources) {
|
|
67
|
-
readOneSource(source, enums, models, unhandled);
|
|
68
|
+
readOneSource(source, enums, models, unhandled, datasources);
|
|
68
69
|
}
|
|
69
|
-
return { enums, models, unhandled };
|
|
70
|
+
return { enums, datasources, models, unhandled };
|
|
70
71
|
}
|
|
71
|
-
|
|
72
|
+
const DATASOURCE_PROVIDER = /^provider\s*=\s*(.*)$/;
|
|
73
|
+
const STRING_LITERAL = /^"([^"\\]*)"$/;
|
|
74
|
+
function readOneSource(source, enums, models, unhandled, datasources) {
|
|
72
75
|
let open = null;
|
|
73
76
|
const lines = source.text.split("\n");
|
|
74
77
|
const unreadableActions = new Set();
|
|
@@ -105,12 +108,26 @@ function readOneSource(source, enums, models, unhandled) {
|
|
|
105
108
|
site: open.site,
|
|
106
109
|
});
|
|
107
110
|
}
|
|
111
|
+
else if (open.kind === "datasource") {
|
|
112
|
+
datasources.push({
|
|
113
|
+
name: open.name,
|
|
114
|
+
provider: open.provider,
|
|
115
|
+
site: open.site,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
108
118
|
open = null;
|
|
109
119
|
continue;
|
|
110
120
|
}
|
|
111
121
|
if (open.kind === "skip") {
|
|
112
122
|
continue;
|
|
113
123
|
}
|
|
124
|
+
if (open.kind === "datasource") {
|
|
125
|
+
const assigned = DATASOURCE_PROVIDER.exec(line)?.[1]?.trim();
|
|
126
|
+
if (assigned !== undefined) {
|
|
127
|
+
open.provider = STRING_LITERAL.exec(assigned)?.[1] ?? null;
|
|
128
|
+
}
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
114
131
|
if (open.kind === "enum") {
|
|
115
132
|
if (line.startsWith("@@")) {
|
|
116
133
|
for (const attribute of splitAttributes(line)) {
|
|
@@ -175,6 +192,9 @@ function openBlock(line, site, record) {
|
|
|
175
192
|
if (keyword === "enum") {
|
|
176
193
|
return { kind: "enum", name, site, values: [] };
|
|
177
194
|
}
|
|
195
|
+
if (keyword === "datasource") {
|
|
196
|
+
return { kind: "datasource", name, site, provider: null };
|
|
197
|
+
}
|
|
178
198
|
if (keyword === "type" || keyword === "view") {
|
|
179
199
|
record("block", keyword, line);
|
|
180
200
|
}
|
|
@@ -5,7 +5,7 @@ import { promisify } from "node:util";
|
|
|
5
5
|
import ts from "typescript";
|
|
6
6
|
import { computeModelHash } from "../discovery/artifact.loader.js";
|
|
7
7
|
import { DISCOVERY_ARTIFACT_FORMAT } from "../discovery/discovery-artifact.interface.js";
|
|
8
|
-
import { readPrismaSchema } from "../discovery/schema.reader.js";
|
|
8
|
+
import { AvPrismaSchemaReaderError, readPrismaSchema, } from "../discovery/schema.reader.js";
|
|
9
9
|
import { readPrismaCapabilitySurface } from "../discovery/types.reader.js";
|
|
10
10
|
import { emitDiscoveryArtifactModule } from "./artifact.emitter.js";
|
|
11
11
|
import { readConfigComputedFields, } from "./computed-fields.reader.js";
|
|
@@ -76,16 +76,38 @@ async function writeArtifactAtomically(file, source) {
|
|
|
76
76
|
if (current === source) {
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
|
-
await mkdir(path.dirname(file), { recursive: true });
|
|
80
79
|
const staged = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
81
80
|
try {
|
|
81
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
82
82
|
await writeFile(staged, source, "utf8");
|
|
83
83
|
await rename(staged, file);
|
|
84
84
|
}
|
|
85
85
|
catch (error) {
|
|
86
|
-
await rm(staged, { force: true });
|
|
87
|
-
throw error;
|
|
86
|
+
await rm(staged, { force: true }).catch(() => undefined);
|
|
87
|
+
throw unwritableArtifact(file, error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const UNWRITABLE_BECAUSE = {
|
|
91
|
+
EACCES: "permission denied",
|
|
92
|
+
EPERM: "permission denied",
|
|
93
|
+
ENOTDIR: "a part of its path is a file, not a directory",
|
|
94
|
+
EEXIST: "a part of its path is a file, not a directory",
|
|
95
|
+
ENOSPC: "no space is left on the device",
|
|
96
|
+
EROFS: "the file system is read-only",
|
|
97
|
+
EISDIR: "it is a directory",
|
|
98
|
+
ENAMETOOLONG: "its path is too long",
|
|
99
|
+
};
|
|
100
|
+
function unwritableArtifact(file, error) {
|
|
101
|
+
const code = error instanceof Error && "code" in error && typeof error.code === "string"
|
|
102
|
+
? error.code
|
|
103
|
+
: undefined;
|
|
104
|
+
if (code === undefined) {
|
|
105
|
+
return error;
|
|
88
106
|
}
|
|
107
|
+
const because = Object.hasOwn(UNWRITABLE_BECAUSE, code)
|
|
108
|
+
? `${UNWRITABLE_BECAUSE[code]} (${code})`
|
|
109
|
+
: code;
|
|
110
|
+
return new AvPrismaGenerateStepError(`the artifact file ${path.resolve(file)} (--out) cannot be written: ${because}.`);
|
|
89
111
|
}
|
|
90
112
|
async function describesModel(file, modelHash) {
|
|
91
113
|
const current = await readFile(file, "utf8").catch(() => undefined);
|
|
@@ -126,6 +148,28 @@ async function assertArtifactPlacement(artifactFile, clientDirectory) {
|
|
|
126
148
|
throw new AvPrismaGenerateStepError(`the artifact file ${file} (--out) is a directory; name the .ts file to write, such as ${path.join(file, "discovery.artifact.ts")}.`);
|
|
127
149
|
}
|
|
128
150
|
}
|
|
151
|
+
const PSL_PROVIDERS = {
|
|
152
|
+
sqlite: "sqlite",
|
|
153
|
+
postgresql: "postgresql",
|
|
154
|
+
postgres: "postgresql",
|
|
155
|
+
};
|
|
156
|
+
function assertDatasourceProvider(facts, provider) {
|
|
157
|
+
for (const datasource of facts.datasources) {
|
|
158
|
+
if (datasource.provider === null) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const named = Object.hasOwn(PSL_PROVIDERS, datasource.provider)
|
|
162
|
+
? PSL_PROVIDERS[datasource.provider]
|
|
163
|
+
: undefined;
|
|
164
|
+
if (named === provider) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const where = `${datasource.site.file}:${datasource.site.line}`;
|
|
168
|
+
throw new AvPrismaGenerateStepError(named === undefined
|
|
169
|
+
? `the schema's datasource \`${datasource.name}\` (${where}) names provider "${datasource.provider}", which this adapter does not support (${Object.keys(PSL_PROVIDERS).join(", ")}).`
|
|
170
|
+
: `--provider ${provider} contradicts the schema's datasource \`${datasource.name}\` (${where}), which names provider "${datasource.provider}"; pass --provider ${named}.`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
129
173
|
function assertNothingUnhandled(facts) {
|
|
130
174
|
if (facts.unhandled.length === 0) {
|
|
131
175
|
return;
|
|
@@ -141,6 +185,17 @@ export async function runPrismaGenerateStep(request) {
|
|
|
141
185
|
const prismaVersion = await toolchain.installedPrismaVersion();
|
|
142
186
|
assertPinnedMajor(prismaVersion);
|
|
143
187
|
assertClientRuntimeResolves(toolchain, request.clientDirectory);
|
|
188
|
+
const declared = await toolchain
|
|
189
|
+
.readSchema(request.schema)
|
|
190
|
+
.catch((error) => {
|
|
191
|
+
if (error instanceof AvPrismaSchemaReaderError) {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
throw error;
|
|
195
|
+
});
|
|
196
|
+
if (declared !== undefined) {
|
|
197
|
+
assertDatasourceProvider(declared, request.provider);
|
|
198
|
+
}
|
|
144
199
|
await toolchain.runPrismaGenerate(request.schema);
|
|
145
200
|
const facts = await toolchain.readSchema(request.schema);
|
|
146
201
|
assertNothingUnhandled(facts);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aventara/prisma7-adapter",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.3",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "The Prisma 7 adapter for Aventara.",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"CHANGELOG.md"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@aventara/core": "1.0.0-rc.
|
|
33
|
+
"@aventara/core": "1.0.0-rc.3"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@prisma/adapter-better-sqlite3": "^7.10.0",
|