@se-studio/project-build 1.0.114 → 1.0.116
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 +12 -0
- package/dist/management/setupColours.js +14 -13
- package/dist/management/setupColours.js.map +1 -1
- package/dist/management/shared.d.ts +9 -4
- package/dist/management/shared.d.ts.map +1 -1
- package/dist/management/shared.js +19 -22
- package/dist/management/shared.js.map +1 -1
- package/package.json +3 -3
- package/skills/contentful-cms/core/SKILL.md +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import * as fs from 'node:fs';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import dotenv from 'dotenv';
|
|
6
|
-
import {
|
|
6
|
+
import { getManagementClient, getValidValues } from './shared.js';
|
|
7
7
|
// Load environment variables from .env.local
|
|
8
8
|
dotenv.config({ path: path.join(process.cwd(), '.env.local') });
|
|
9
9
|
// Load tailwind.config.json from the current working directory
|
|
@@ -17,7 +17,7 @@ function areTheSame(a, b) {
|
|
|
17
17
|
const hasAll = b.every((value) => aSet.has(value));
|
|
18
18
|
return hasAll;
|
|
19
19
|
}
|
|
20
|
-
async function setupColors(
|
|
20
|
+
async function setupColors(client) {
|
|
21
21
|
if (!colorOpposites || !colorOptions)
|
|
22
22
|
throw new Error('Need color options and opposites');
|
|
23
23
|
const backgroundColors = Object.keys(colorOpposites).sort();
|
|
@@ -32,39 +32,40 @@ async function setupColors(environment) {
|
|
|
32
32
|
const allForegroundColors = Array.from(new Set([...foregroundOnlyColors, ...foregroundAndBackgroundColours])).sort();
|
|
33
33
|
console.log('All background colors:', allBackgroundColors);
|
|
34
34
|
console.log('All foreground colors:', allForegroundColors);
|
|
35
|
-
const components = await
|
|
35
|
+
const components = await client.contentType.getMany({ query: {} });
|
|
36
36
|
for (const component of components.items) {
|
|
37
37
|
const backgroundColourField = component.fields.find((f) => f.id === 'backgroundColour');
|
|
38
38
|
const textColourField = component.fields.find((f) => f.id === 'textColour');
|
|
39
39
|
if (!backgroundColourField && !textColourField)
|
|
40
40
|
continue;
|
|
41
|
-
let
|
|
41
|
+
let needsWrite = false;
|
|
42
42
|
if (backgroundColourField) {
|
|
43
|
-
const currentBackgroundColors = await getValidValues(
|
|
43
|
+
const currentBackgroundColors = await getValidValues(client, component.sys.id, backgroundColourField.id);
|
|
44
44
|
if (!areTheSame(allBackgroundColors, currentBackgroundColors)) {
|
|
45
45
|
console.log(`Updating background colours for ${component.name}`);
|
|
46
46
|
backgroundColourField.validations = [{ in: allBackgroundColors }];
|
|
47
|
-
|
|
47
|
+
needsWrite = true;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
if (textColourField) {
|
|
51
|
-
const currentTextColors = await getValidValues(
|
|
51
|
+
const currentTextColors = await getValidValues(client, component.sys.id, textColourField.id);
|
|
52
52
|
if (!areTheSame(allForegroundColors, currentTextColors)) {
|
|
53
53
|
console.log(`Updating text colours for ${component.name}`);
|
|
54
54
|
textColourField.validations = [{ in: allForegroundColors }];
|
|
55
|
-
|
|
55
|
+
needsWrite = true;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
if (
|
|
58
|
+
if (needsWrite) {
|
|
59
59
|
console.log('updating', component.name);
|
|
60
|
-
const
|
|
61
|
-
await
|
|
60
|
+
const contentTypeId = component.sys.id;
|
|
61
|
+
const afterUpdate = await client.contentType.update({ contentTypeId }, component);
|
|
62
|
+
await client.contentType.publish({ contentTypeId }, afterUpdate);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
async function run() {
|
|
66
|
-
const
|
|
67
|
-
await setupColors(
|
|
67
|
+
const client = getManagementClient();
|
|
68
|
+
await setupColors(client);
|
|
68
69
|
}
|
|
69
70
|
run()
|
|
70
71
|
.then(() => console.log('done'))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupColours.js","sourceRoot":"","sources":["../../src/management/setupColours.ts"],"names":[],"mappings":";AACA,gEAAgE;AAChE,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"setupColours.js","sourceRoot":"","sources":["../../src/management/setupColours.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { type PlainClientAPI } from 'contentful-management';
|
|
2
|
+
/**
|
|
3
|
+
* Plain CMA client scoped to `CONTENTFUL_SPACE_ID` and `CONTENTFUL_ENVIRONMENT_NAME`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getManagementClient(): PlainClientAPI;
|
|
6
|
+
/** @deprecated Prefer {@link getManagementClient}; same plain client. */
|
|
7
|
+
export declare const getEnvironment: typeof getManagementClient;
|
|
8
|
+
export declare function getValidValues(client: PlainClientAPI, contentTypeId: string, fieldId: string): Promise<string[]>;
|
|
9
|
+
export declare function setValidValues(client: PlainClientAPI, contentTypeId: string, fieldId: string, values: string[]): Promise<void>;
|
|
5
10
|
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/management/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/management/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE1E;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAQpD;AAED,yEAAyE;AACzE,eAAO,MAAM,cAAc,4BAAsB,CAAC;AAElD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,qBAWhB;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EAAE,iBASjB"}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { createClient } from 'contentful-management';
|
|
2
|
+
/**
|
|
3
|
+
* Plain CMA client scoped to `CONTENTFUL_SPACE_ID` and `CONTENTFUL_ENVIRONMENT_NAME`.
|
|
4
|
+
*/
|
|
5
|
+
export function getManagementClient() {
|
|
6
|
+
const spaceId = process.env.CONTENTFUL_SPACE_ID;
|
|
7
|
+
const accessToken = process.env.CONTENTFUL_MANAGEMENT_TOKEN;
|
|
8
|
+
const environmentName = process.env.CONTENTFUL_ENVIRONMENT_NAME;
|
|
9
|
+
if (!spaceId || !accessToken || !environmentName)
|
|
10
|
+
throw new Error('Env not setup');
|
|
11
|
+
return createClient({ accessToken }, { defaults: { spaceId, environmentId: environmentName } });
|
|
12
|
+
}
|
|
13
|
+
/** @deprecated Prefer {@link getManagementClient}; same plain client. */
|
|
14
|
+
export const getEnvironment = getManagementClient;
|
|
15
|
+
export async function getValidValues(client, contentTypeId, fieldId) {
|
|
16
|
+
const contentType = await client.contentType.get({ contentTypeId });
|
|
7
17
|
const field = contentType.fields.find((f) => f.id === fieldId);
|
|
8
18
|
if (!field)
|
|
9
19
|
throw new Error(`Failed to find field: ${fieldId}`);
|
|
@@ -12,25 +22,12 @@ export async function getValidValues(environment, contentTypeId, fieldId) {
|
|
|
12
22
|
throw new Error(`Field did not have validations`);
|
|
13
23
|
return validValues;
|
|
14
24
|
}
|
|
15
|
-
export async function setValidValues(
|
|
16
|
-
const contentType = await
|
|
17
|
-
if (!contentType)
|
|
18
|
-
throw new Error(`Failed to find content type: ${contentTypeId}`);
|
|
25
|
+
export async function setValidValues(client, contentTypeId, fieldId, values) {
|
|
26
|
+
const contentType = await client.contentType.get({ contentTypeId });
|
|
19
27
|
const field = contentType.fields.find((f) => f.id === fieldId);
|
|
20
28
|
if (!field)
|
|
21
29
|
throw new Error(`Failed to find field: ${fieldId}`);
|
|
22
30
|
field.validations = [{ in: values }];
|
|
23
|
-
await contentType.update();
|
|
24
|
-
}
|
|
25
|
-
export async function getEnvironment() {
|
|
26
|
-
const spaceId = process.env.CONTENTFUL_SPACE_ID;
|
|
27
|
-
const accessToken = process.env.CONTENTFUL_MANAGEMENT_TOKEN;
|
|
28
|
-
const environmentName = process.env.CONTENTFUL_ENVIRONMENT_NAME;
|
|
29
|
-
if (!spaceId || !accessToken || !environmentName)
|
|
30
|
-
throw new Error('Env not setup');
|
|
31
|
-
const client = createClient({ accessToken });
|
|
32
|
-
const space = await client.getSpace(spaceId);
|
|
33
|
-
const environment = await space.getEnvironment(environmentName);
|
|
34
|
-
return environment;
|
|
31
|
+
await client.contentType.update({ contentTypeId }, contentType);
|
|
35
32
|
}
|
|
36
33
|
//# sourceMappingURL=shared.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/management/shared.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/management/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,uBAAuB,CAAC;AAE1E;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAChD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IAC5D,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IAEhE,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IAEnF,OAAO,YAAY,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;AAClG,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAsB,EACtB,aAAqB,EACrB,OAAe;IAEf,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;IAEpE,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IAC/D,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IAEhE,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAEpF,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpE,OAAO,WAAuB,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAsB,EACtB,aAAqB,EACrB,OAAe,EACf,MAAgB;IAEhB,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;IAEpE,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IAC/D,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IAEhE,KAAK,CAAC,WAAW,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACrC,MAAM,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,EAAE,WAAW,CAAC,CAAC;AAClE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@se-studio/project-build",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.116",
|
|
4
4
|
"description": "Build tools and management scripts for SE Studio projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -65,14 +65,14 @@
|
|
|
65
65
|
"@biomejs/wasm-nodejs": "^2.4.9",
|
|
66
66
|
"change-case": "^5.4.4",
|
|
67
67
|
"chroma-js": "^3.2.0",
|
|
68
|
-
"contentful-management": "^
|
|
68
|
+
"contentful-management": "^12.0.0",
|
|
69
69
|
"dotenv": "^17.3.1"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/chroma-js": "^3.1.2",
|
|
73
73
|
"@types/node": "^22.19.15",
|
|
74
74
|
"typescript": "^6.0.2",
|
|
75
|
-
"vitest": "^4.1.
|
|
75
|
+
"vitest": "^4.1.2"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"build": "node scripts/merge-contentful-skills.mjs && tsc --project tsconfig.build.json",
|
|
@@ -48,6 +48,8 @@ cms-edit open 4xKj2abcDef --id
|
|
|
48
48
|
cms-edit open /
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
**Slug `open`:** matches **page**, **article**, **articleType**, and **tag** by `fields.slug` (in that order; first match wins). For **template** or **navigation**, use `open <id> --id` or `cms-edit nav open`.
|
|
52
|
+
|
|
51
53
|
### Step 2: Read the snapshot
|
|
52
54
|
|
|
53
55
|
```bash
|