Skip to content

feat: bindings #166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 92 additions & 24 deletions packages/config/src/configProcessor/helpers/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,84 @@ const createRuleSchema = (isRequestPhase = false) => ({
},
});

const schemaStorage = {
type: 'object',
properties: {
name: {
type: 'string',
minLength: 6,
maxLength: 63,
pattern: '^.{6,63}$',
errorMessage: "The 'name' field must be a string between 6 and 63 characters.",
},
dir: {
type: 'string',
errorMessage: "The 'dir' field must be a string.",
},
edgeAccess: {
type: 'string',
enum: ['read_only', 'read_write', 'restricted'],
errorMessage: "The 'edge_access' field must be one of: read_only, read_write, restricted.",
},
},
required: ['name', 'dir'],
additionalProperties: false,
errorMessage: {
additionalProperties: 'No additional properties are allowed in storage items.',
required: "The 'name' and 'dir' fields are required.",
},
};

const schemaFunction = {
type: 'object',
properties: {
name: {
type: 'string',
errorMessage: "The 'name' field must be a string",
},
path: {
type: 'string',
errorMessage: "The 'path' field must be a string",
},
args: {
type: 'object',
errorMessage: "The 'args' field must be an object",
},
bindings: {
type: 'object',
properties: {
storage: {
type: 'object',
properties: {
bucket: {
type: 'string',
errorMessage: "The 'bucket' field must be a string",
},
prefix: {
type: 'string',
errorMessage: "The 'prefix' field must be a string",
},
},
required: ['bucket'],
additionalProperties: false,
errorMessage: {
type: "The 'storage' field must be an object",
additionalProperties: 'No additional properties are allowed in the storage object',
required: "The 'bucket' field is required in the storage object",
},
},
},
additionalProperties: false,
errorMessage: {
type: "The 'bindings' field must be an object",
additionalProperties: 'No additional properties are allowed in the bindings object',
},
},
},
required: ['name', 'path'],
additionalProperties: false,
};

const azionConfigSchema = {
$id: 'azionConfig',
definitions: {
Expand Down Expand Up @@ -463,6 +541,10 @@ const azionConfigSchema = {
type: 'string',
errorMessage: "The 'ext' field in preset metadata must be a string",
},
registry: {
type: 'string',
errorMessage: "The 'registry' field in preset metadata must be a string",
},
},
required: ['name'],
additionalProperties: false,
Expand Down Expand Up @@ -520,30 +602,7 @@ const azionConfigSchema = {
},
functions: {
type: 'array',
items: {
type: 'object',
properties: {
name: {
type: 'string',
errorMessage: "The function's 'name' field must be a string",
},
path: {
type: 'string',
errorMessage: "The function's 'path' field must be a string",
},
args: {
type: 'object',
additionalProperties: true,
errorMessage: "The function's 'args' field must be an object",
},
},
required: ['name', 'path'],
additionalProperties: false,
errorMessage: {
additionalProperties: 'No additional properties are allowed in function items',
required: "Both 'name' and 'path' fields are required for each function",
},
},
items: schemaFunction,
},
rules: {
type: 'object',
Expand Down Expand Up @@ -961,7 +1020,11 @@ const azionConfigSchema = {
},
},
},
required: ['name'],
additionalProperties: false,
errorMessage: {
required: "The 'name' field is required in the domain object.",
},
},
purge: {
type: 'array',
Expand Down Expand Up @@ -1295,6 +1358,11 @@ const azionConfigSchema = {
type: "The 'waf' field must be an array",
},
},
storage: {
type: 'array',
items: schemaStorage,
errorMessage: "The 'storage' field must be an array of storage items.",
},
},
additionalProperties: false,
errorMessage: {
Expand Down
90 changes: 89 additions & 1 deletion packages/config/src/configProcessor/helpers/schemaManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,33 @@ const schemaApplicationRules = {
additionalProperties: false,
};

// ... resto do arquivo mantido como está ...
const schemaStorageManifest = {
type: 'object',
properties: {
name: {
type: 'string',
minLength: 6,
maxLength: 63,
pattern: '^.{6,63}$',
errorMessage: "The 'name' field must be a string between 6 and 63 characters.",
},
dir: {
type: 'string',
errorMessage: "The 'dir' field must be a string.",
},
edge_access: {
type: 'string',
enum: ['read_only', 'read_write', 'restricted'],
errorMessage: "The 'edge_access' field must be one of: read_only, read_write, restricted.",
},
},
required: ['name', 'dir'],
additionalProperties: false,
errorMessage: {
additionalProperties: 'No additional properties are allowed in storage items.',
required: "The 'name' and 'dir' fields are required.",
},
};

const schemaApplicationManifest = {
type: 'object',
Expand Down Expand Up @@ -806,6 +832,58 @@ const schemaApplicationManifest = {
},
};

const schemaFunctionManifest = {
type: 'object',
properties: {
name: {
type: 'string',
errorMessage: "The 'name' field must be a string",
},
target: {
type: 'string',
errorMessage: "The 'target' field must be a string",
},
args: {
type: 'object',
errorMessage: "The 'args' field must be an object",
},
bindings: {
type: 'object',
properties: {
edge_storage: {
type: 'array',
items: {
type: 'object',
properties: {
bucket: {
type: 'string',
errorMessage: "The 'bucket' field must be a string",
},
prefix: {
type: 'string',
errorMessage: "The 'prefix' field must be a string",
},
},
required: ['bucket'],
additionalProperties: false,
errorMessage: {
additionalProperties: 'No additional properties are allowed in edge_storage items',
required: "The 'bucket' field is required",
},
},
errorMessage: "The 'edge_storage' field must be an array of storage bindings",
},
},
additionalProperties: false,
errorMessage: {
additionalProperties: 'No additional properties are allowed in bindings object',
},
},
},
required: ['name', 'target'],
additionalProperties: false,
};

const schemaManifest = {
type: 'object',
properties: {
Expand Down Expand Up @@ -838,6 +916,16 @@ const schemaManifest = {
items: schemaApplicationManifest,
errorMessage: "The 'application' field must be an array of application items.",
},
storage: {
type: 'array',
items: schemaStorageManifest,
errorMessage: "The 'storage' field must be an array of storage items.",
},
function: {
type: 'array',
items: schemaFunctionManifest,
errorMessage: "The 'function' field must be an array of function items.",
},
},
};
export { schemaManifest };
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,13 @@ describe('processConfig', () => {
build: {
preset: 'next',
polyfills: true,
custom: {
minify: true,
},
},
};
expect(processConfig(config)).toEqual(
expect.objectContaining({
build: {
preset: 'next',
polyfills: true,
custom: {
minify: true,
},
},
}),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,74 @@ import ProcessConfigStrategy from '../processConfigStrategy';
* @description This class is implementation of the Functions ProcessConfig Strategy.
*/
class FunctionsProcessConfigStrategy extends ProcessConfigStrategy {
private validateStorageBinding(config: AzionConfig, bucketName: string, functionName: string) {
if (!Array.isArray(config?.storage) || !config.storage.find((storage) => storage.name === bucketName)) {
throw new Error(
`Function "${functionName}" references storage bucket "${bucketName}" which is not defined in the storage configuration.`,
);
}
}

transformToManifest(config: AzionConfig) {
if (!Array.isArray(config?.functions) || config?.functions.length === 0) {
return;
}

return config.functions.map((func) => ({
name: func.name,
target: func.path,
args: func.args || {},
}));
return config.functions.map((func) => {
// Validar se o bucket referenciado existe
if (func.bindings?.storage?.bucket) {
this.validateStorageBinding(config, func.bindings.storage.bucket, func.name);
}

return {
name: func.name,
target: func.path,
args: func.args || {},
bindings: func.bindings
? {
edge_storage: func.bindings.storage
? {
bucket: func.bindings.storage.bucket,
prefix: func.bindings.storage.prefix,
}
: undefined,
}
: undefined,
};
});
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
transformToConfig(payload: any, transformedPayload: AzionConfig) {
if (!Array.isArray(payload?.functions) || payload?.functions.length === 0) {
return;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
transformedPayload.functions = payload.functions.map((func: any) => ({
name: func.name,
path: func.target,
args: func.args || {},
}));
transformedPayload.functions = payload.functions.map((func: any) => {
const config = {
name: func.name,
path: func.target,
args: func.args || {},
bindings: func.bindings
? {
storage: func.bindings.edge_storage
? {
bucket: func.bindings.edge_storage.bucket,
prefix: func.bindings.edge_storage.prefix,
}
: undefined,
}
: undefined,
};

// Validar se o bucket referenciado existe
if (config.bindings?.storage?.bucket) {
this.validateStorageBinding(transformedPayload, config.bindings.storage.bucket, config.name);
}

return config;
});

return transformedPayload.functions;
}
Expand Down
Loading