Skip to content

Commit a16eb2e

Browse files
authored
Suggest DNS friendly service ids (#8118)
1 parent be02559 commit a16eb2e

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
- Updated `cross-env` and `cross-spawn` dependencies to avoid vulnerable versions. (#7979)
22
- Fixed an issue with the Data Connect emulator where `dataDir` and `--export` were relative to the current directory insead of `firebase.json`.
3+
- `init dataconnect` now suggests DNS compatible service IDs.

src/init/features/dataconnect/index.spec.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ describe("init dataconnect", () => {
5454
expectEnsureSchemaGQL: false,
5555
},
5656
{
57-
desc: "exiting project should use existing directory",
57+
desc: "existing project should use existing directory",
5858
requiredInfo: mockRequiredInfo(),
5959
config: mockConfig({ dataconnect: { source: "not-dataconnect" } }),
6060
expectedSource: "not-dataconnect",
@@ -161,6 +161,41 @@ describe("init dataconnect", () => {
161161
});
162162
}
163163
});
164+
165+
describe("toDNSCompatibleId", () => {
166+
const cases: { description: string; input: string; expected: string }[] = [
167+
{
168+
description: "Should noop compatible strings",
169+
input: "this-is-compatible",
170+
expected: "this-is-compatible",
171+
},
172+
{
173+
description: "Should lower case",
174+
input: "This-Is-Compatible",
175+
expected: "this-is-compatible",
176+
},
177+
{
178+
description: "Should strip special characters",
179+
input: "this-is-compatible?~!@#$%^&*()_+=",
180+
expected: "this-is-compatible",
181+
},
182+
{
183+
description: "Should strip trailing and leading -",
184+
input: "---this-is-compatible---",
185+
expected: "this-is-compatible",
186+
},
187+
{
188+
description: "Should cut to 63 characters",
189+
input: "a".repeat(1000),
190+
expected: "a".repeat(63),
191+
},
192+
];
193+
for (const c of cases) {
194+
it(c.description, () => {
195+
expect(init.toDNSCompatibleId(c.input)).to.equal(c.expected);
196+
});
197+
}
198+
});
164199
});
165200

166201
function mockConfig(data: Record<string, any> = {}): Config {

src/init/features/dataconnect/index.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ async function askQuestions(setup: Setup, isBillingEnabled: boolean): Promise<Re
141141
}))
142142
);
143143
} else {
144-
info.serviceId = info.serviceId || basename(process.cwd());
144+
// Ensure that the suggested name is DNS compatible
145+
const defaultServiceId = toDNSCompatibleId(basename(process.cwd()));
146+
info.serviceId = info.serviceId || defaultServiceId;
145147
info.cloudSqlInstanceId = info.cloudSqlInstanceId || `${info.serviceId || "app"}-fdc`;
146148
info.locationId = info.locationId || `us-central1`;
147149
info.cloudSqlDatabase = info.cloudSqlDatabase || `fdcdb`;
@@ -447,3 +449,20 @@ async function locationChoices(setup: Setup) {
447449
];
448450
}
449451
}
452+
453+
/**
454+
* Converts any string to a DNS friendly service ID.
455+
*/
456+
export function toDNSCompatibleId(id: string): string {
457+
let defaultServiceId = basename(id)
458+
.toLowerCase()
459+
.replaceAll(/[^a-z0-9-]/g, "")
460+
.slice(0, 63);
461+
while (defaultServiceId.endsWith("-") && defaultServiceId.length) {
462+
defaultServiceId = defaultServiceId.slice(0, defaultServiceId.length - 1);
463+
}
464+
while (defaultServiceId.startsWith("-") && defaultServiceId.length) {
465+
defaultServiceId = defaultServiceId.slice(1, defaultServiceId.length);
466+
}
467+
return defaultServiceId || "app";
468+
}

0 commit comments

Comments
 (0)